@gearbox-protocol/sdk 17.2.1 → 17.3.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.
Files changed (46) hide show
  1. package/dist/cjs/dev/index.js +1 -0
  2. package/dist/cjs/dev/isRateLimitError.js +20 -5
  3. package/dist/cjs/dev/resilientTransport.js +31 -8
  4. package/dist/cjs/onchain/accounts/intents/leverage-band.js +1 -1
  5. package/dist/cjs/onchain/accounts/intents/maxBorrow.js +15 -11
  6. package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +5 -2
  7. package/dist/cjs/onchain/chain/chains.js +1 -2
  8. package/dist/cjs/onchain/index.js +2 -0
  9. package/dist/cjs/onchain/market/MarketSuite.js +11 -4
  10. package/dist/cjs/onchain/market/credit/CreditSuite.js +25 -138
  11. package/dist/cjs/onchain/market/credit/CreditSuiteStrategy.js +179 -0
  12. package/dist/cjs/onchain/market/credit/index.js +2 -0
  13. package/dist/cjs/onchain/market/index.js +2 -0
  14. package/dist/cjs/onchain/market/pool/PoolQuotaKeeperV310Contract.js +4 -1
  15. package/dist/cjs/onchain/opportunities/OpportunitiesService.js +7 -9
  16. package/dist/cjs/sdk/prepare/PrepareApi.js +1 -1
  17. package/dist/esm/dev/index.js +2 -2
  18. package/dist/esm/dev/isRateLimitError.js +20 -5
  19. package/dist/esm/dev/resilientTransport.js +31 -9
  20. package/dist/esm/onchain/accounts/intents/leverage-band.js +1 -1
  21. package/dist/esm/onchain/accounts/intents/maxBorrow.js +15 -11
  22. package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +5 -2
  23. package/dist/esm/onchain/chain/chains.js +1 -2
  24. package/dist/esm/onchain/index.js +2 -1
  25. package/dist/esm/onchain/market/MarketSuite.js +11 -4
  26. package/dist/esm/onchain/market/credit/CreditSuite.js +27 -140
  27. package/dist/esm/onchain/market/credit/CreditSuiteStrategy.js +178 -0
  28. package/dist/esm/onchain/market/credit/index.js +2 -1
  29. package/dist/esm/onchain/market/index.js +2 -1
  30. package/dist/esm/onchain/market/pool/PoolQuotaKeeperV310Contract.js +4 -1
  31. package/dist/esm/onchain/opportunities/OpportunitiesService.js +7 -9
  32. package/dist/esm/sdk/prepare/PrepareApi.js +1 -1
  33. package/dist/types/dev/index.d.ts +2 -2
  34. package/dist/types/dev/isRateLimitError.d.ts +2 -1
  35. package/dist/types/dev/resilientTransport.d.ts +18 -2
  36. package/dist/types/model/errors/operation-errors.d.ts +6 -1
  37. package/dist/types/onchain/accounts/intents/maxBorrow.d.ts +12 -10
  38. package/dist/types/onchain/index.d.ts +2 -1
  39. package/dist/types/onchain/market/MarketSuite.d.ts +6 -0
  40. package/dist/types/onchain/market/credit/CreditSuite.d.ts +18 -52
  41. package/dist/types/onchain/market/credit/CreditSuiteStrategy.d.ts +78 -0
  42. package/dist/types/onchain/market/credit/index.d.ts +2 -1
  43. package/dist/types/onchain/market/credit/types.d.ts +3 -1
  44. package/dist/types/onchain/market/index.d.ts +2 -1
  45. package/dist/types/onchain/market/pool/PoolQuotaKeeperV310Contract.d.ts +2 -0
  46. package/package.json +1 -1
@@ -0,0 +1,179 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_chain_chains = require("../../chain/chains.js");
3
+ const require_onchain_market_math = require("../math.js");
4
+ const require_onchain_market_strategyName = require("../strategyName.js");
5
+ let viem = require("viem");
6
+ //#region src/onchain/market/credit/CreditSuiteStrategy.ts
7
+ /**
8
+ * Amount of underlying seeded into each pool at market creation to protect
9
+ * from inflation attacks, in raw token units. A strategy whose
10
+ * {@link CreditSuiteStrategy.maxBorrowAmount} is at or below this is treated
11
+ * as having nothing left to lend.
12
+ **/
13
+ const MIN_STRATEGY_BORROW_AMOUNT = 100000n;
14
+ /**
15
+ * The leveraged strategy a credit suite runs: one target collateral bought
16
+ * with underlying borrowed from the pool.
17
+ *
18
+ * A view over live suite state, see {@link CreditSuite.strategy}.
19
+ */
20
+ var CreditSuiteStrategy = class {
21
+ /**
22
+ * Credit suite this strategy borrows through.
23
+ */
24
+ suite;
25
+ /**
26
+ * Collateral token a position in this strategy is built to hold.
27
+ */
28
+ targetCollateral;
29
+ constructor(suite, targetCollateral) {
30
+ this.suite = suite;
31
+ this.targetCollateral = targetCollateral;
32
+ }
33
+ /**
34
+ * {@link targetCollateral} as the shared read model describes it.
35
+ */
36
+ get token() {
37
+ return this.suite.sdk.tokensMeta.mustGetToken(this.targetCollateral);
38
+ }
39
+ /**
40
+ * Display name of this strategy, e.g. `"wstETH / WETH"`.
41
+ */
42
+ get name() {
43
+ return require_onchain_market_strategyName.strategyName(this.token, this.suite.underlyingToken);
44
+ }
45
+ /**
46
+ * Tokens a user can transfer from their wallet when opening a position in
47
+ * this strategy:
48
+ *
49
+ * 1. unwrapped underlying (USDC, never dcUSDC)
50
+ * 2. target collateral
51
+ * 3. remaining CM collaterals in manager order, excluding phantom tokens
52
+ * and tokens without price
53
+ */
54
+ get allowedDepositTokens() {
55
+ const { market, creditManager, sdk } = this.suite;
56
+ const { tokensMeta } = sdk;
57
+ const { targetCollateral } = this;
58
+ const { mainPrices, reservePrices } = market.priceOracle;
59
+ const rest = creditManager.collateralTokens.filter((token) => {
60
+ const contractType = tokensMeta.mustGet(token).contractType;
61
+ return !market.isUnderlyingLike(token) && !(0, viem.isAddressEqual)(token, targetCollateral) && !contractType?.startsWith("PHANTOM_TOKEN::") && (!!mainPrices.get(token)?.price || !!reservePrices.get(token)?.price);
62
+ });
63
+ return [
64
+ market.unwrappedUnderlying,
65
+ targetCollateral,
66
+ ...rest
67
+ ].map((token) => tokensMeta.mustGetToken(token));
68
+ }
69
+ /**
70
+ * Largest debt one new position can take right now, and which limit set
71
+ * that number.
72
+ *
73
+ * `amount` is `0` whenever no position can be opened right now,
74
+ * and `limit` explains why.
75
+ *
76
+ */
77
+ maxBorrowAmount() {
78
+ const { suite } = this;
79
+ const lends = suite.maxBorrowAmount();
80
+ if (lends.limit === "debtPerBlockLimit") return lends;
81
+ let value = lends.amount.value;
82
+ let limit = lends.limit;
83
+ const quota = suite.market.pool.pqk.quotaAvailable(this.targetCollateral);
84
+ if (quota < value) {
85
+ value = quota;
86
+ limit = "quotaAvailable";
87
+ }
88
+ if (value < suite.creditFacade.minDebt) return {
89
+ amount: suite.market.toUnderlyingAmount(0n),
90
+ limit: "minDebt"
91
+ };
92
+ return {
93
+ amount: suite.market.toUnderlyingAmount(value),
94
+ limit
95
+ };
96
+ }
97
+ /**
98
+ * Whether this strategy is offered as an opportunity right now: it lends
99
+ * more than the pool's seed amount, and its target can be opened today.
100
+ */
101
+ get isListed() {
102
+ return this.maxBorrowAmount().amount.value > MIN_STRATEGY_BORROW_AMOUNT && this.suite.isStrategyCollateral(this.targetCollateral, true);
103
+ }
104
+ /**
105
+ * Describes this strategy as the shared read model does. Whether it is
106
+ * listed at all is {@link isListed}.
107
+ */
108
+ opportunity() {
109
+ const { suite, targetCollateral } = this;
110
+ const { market, creditManager: cm } = suite;
111
+ const { pool } = market.pool;
112
+ const oracle = market.priceOracle;
113
+ const debtParams = pool.creditManagerDebtParams.get(cm.address);
114
+ const borrowed = debtParams?.borrowed ?? 0n;
115
+ return {
116
+ kind: "strategy",
117
+ chainId: suite.chainId,
118
+ creditManager: cm.address,
119
+ targetCollateral: this.token,
120
+ name: this.name,
121
+ curator: market.curator,
122
+ underlyingToken: suite.underlyingToken,
123
+ totalBorrowed: oracle.toAmount(pool.underlying, borrowed),
124
+ allowedDepositTokens: this.allowedDepositTokens,
125
+ paused: suite.isPaused,
126
+ rwa: market.rwa,
127
+ sunset: market.sunset || require_onchain_chain_chains.isSunsetStrategy(cm.address, suite.sdk.networkType),
128
+ liquidationThreshold: cm.liquidationThresholds.mustGet(targetCollateral),
129
+ liquidationPremium: cm.liquidationPremium,
130
+ liquidationFee: cm.feeLiquidation,
131
+ expirationDate: suite.expirationDate,
132
+ borrowApy: require_onchain_market_math.calcBorrowApy(pool.baseInterestRate, cm.feeInterest),
133
+ quotaRate: require_onchain_market_math.calcQuotaRate(market.pool.pqk.quotaRate(targetCollateral), cm.feeInterest),
134
+ availableLiquidity: oracle.toAmount(pool.underlying, pool.availableLiquidity),
135
+ minDebt: oracle.toAmount(pool.underlying, suite.creditFacade.minDebt),
136
+ totalDebtLimit: oracle.toAmount(pool.underlying, debtParams?.limit ?? 0n),
137
+ maxBorrowAmount: oracle.toAmount(pool.underlying, this.maxBorrowAmount().amount.value),
138
+ maxLeverage: cm.maxLeverage(targetCollateral)
139
+ };
140
+ }
141
+ /**
142
+ * {@link opportunity} plus the data only its detail screen needs.
143
+ */
144
+ opportunityDetail() {
145
+ const { market } = this.suite;
146
+ return {
147
+ ...this.opportunity(),
148
+ rateCurve: market.pool.rateCurve,
149
+ priceFeeds: market.priceFeedSummary(this.targetCollateral)
150
+ };
151
+ }
152
+ /**
153
+ * The KYC gate of this strategy; `null` when there is none.
154
+ * Wallet-independent.
155
+ */
156
+ async kycRequirement() {
157
+ const nft = await this.suite.degenNFT();
158
+ if (!nft) return null;
159
+ const tokens = await nft.getTokens();
160
+ const token = tokens.find((t) => (0, viem.isAddressEqual)(t, this.targetCollateral)) ?? tokens[0];
161
+ return {
162
+ protocol: nft.protocol,
163
+ token: token ? this.suite.sdk.tokensMeta.getToken(token) : void 0,
164
+ registrationLink: nft.registrationLink
165
+ };
166
+ }
167
+ /**
168
+ * Whether `wallet` may open this strategy today; `true` when there is no
169
+ * KYC gate.
170
+ */
171
+ async isEligible(wallet) {
172
+ const nft = await this.suite.degenNFT();
173
+ if (!nft) return true;
174
+ const requirements = await nft.getOpenAccountRequirements(wallet, { tokenOutAddress: this.targetCollateral });
175
+ return nft.isRegistered(requirements);
176
+ }
177
+ };
178
+ //#endregion
179
+ exports.CreditSuiteStrategy = CreditSuiteStrategy;
@@ -3,6 +3,7 @@ const require_onchain_market_credit_CreditConfiguratorV310Contract = require("./
3
3
  const require_onchain_market_credit_CreditFacadeV310BaseContract = require("./CreditFacadeV310BaseContract.js");
4
4
  const require_onchain_market_credit_CreditFacadeV310Contract = require("./CreditFacadeV310Contract.js");
5
5
  const require_onchain_market_credit_CreditManagerV310Contract = require("./CreditManagerV310Contract.js");
6
+ const require_onchain_market_credit_CreditSuiteStrategy = require("./CreditSuiteStrategy.js");
6
7
  const require_onchain_market_credit_collateralUtils = require("./collateralUtils.js");
7
8
  const require_onchain_market_credit_CreditSuite = require("./CreditSuite.js");
8
9
  const require_onchain_market_credit_expectedBalanceDeltas = require("./expectedBalanceDeltas.js");
@@ -12,6 +13,7 @@ exports.CreditFacadeV310BaseContract = require_onchain_market_credit_CreditFacad
12
13
  exports.CreditFacadeV310Contract = require_onchain_market_credit_CreditFacadeV310Contract.CreditFacadeV310Contract;
13
14
  exports.CreditManagerV310Contract = require_onchain_market_credit_CreditManagerV310Contract.CreditManagerV310Contract;
14
15
  exports.CreditSuite = require_onchain_market_credit_CreditSuite.CreditSuite;
16
+ exports.CreditSuiteStrategy = require_onchain_market_credit_CreditSuiteStrategy.CreditSuiteStrategy;
15
17
  exports.creditFacadeV310Abi = require_onchain_market_credit_CreditFacadeV310BaseContract.creditFacadeV310Abi;
16
18
  exports.dominantCollateral = require_onchain_market_credit_collateralUtils.dominantCollateral;
17
19
  exports.expectedBalanceDeltas = require_onchain_market_credit_expectedBalanceDeltas.expectedBalanceDeltas;
@@ -94,6 +94,7 @@ const require_onchain_market_rwa_midas_constants = require("./rwa/midas/constant
94
94
  const require_onchain_market_rwa_midas_MidasDegenNFT = require("./rwa/midas/MidasDegenNFT.js");
95
95
  const require_onchain_market_rwa_securitize_constants = require("./rwa/securitize/constants.js");
96
96
  const require_onchain_market_strategyName = require("./strategyName.js");
97
+ const require_onchain_market_credit_CreditSuiteStrategy = require("./credit/CreditSuiteStrategy.js");
97
98
  const require_onchain_market_credit_collateralUtils = require("./credit/collateralUtils.js");
98
99
  const require_onchain_market_credit_CreditSuite = require("./credit/CreditSuite.js");
99
100
  const require_onchain_market_credit_expectedBalanceDeltas = require("./credit/expectedBalanceDeltas.js");
@@ -170,6 +171,7 @@ exports.CreditFacadeV310BaseContract = require_onchain_market_credit_CreditFacad
170
171
  exports.CreditFacadeV310Contract = require_onchain_market_credit_CreditFacadeV310Contract.CreditFacadeV310Contract;
171
172
  exports.CreditManagerV310Contract = require_onchain_market_credit_CreditManagerV310Contract.CreditManagerV310Contract;
172
173
  exports.CreditSuite = require_onchain_market_credit_CreditSuite.CreditSuite;
174
+ exports.CreditSuiteStrategy = require_onchain_market_credit_CreditSuiteStrategy.CreditSuiteStrategy;
173
175
  exports.Curve2AssetsAdapterContract = require_onchain_market_adapters_contracts_Curve2AssetsAdapterContract.Curve2AssetsAdapterContract;
174
176
  exports.Curve3AssetsAdapterContract = require_onchain_market_adapters_contracts_Curve3AssetsAdapterContract.Curve3AssetsAdapterContract;
175
177
  exports.Curve4AssetsAdapterContract = require_onchain_market_adapters_contracts_Curve4AssetsAdapterContract.Curve4AssetsAdapterContract;
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_abi_310_generated = require("../../../abi/310/generated.js");
3
3
  const require_onchain_utils_AddressMap = require("../../utils/AddressMap.js");
4
+ const require_onchain_utils_bigint_math = require("../../utils/bigint-math.js");
4
5
  const require_onchain_utils_formatter = require("../../utils/formatter.js");
5
6
  require("../../utils/index.js");
6
7
  const require_onchain_base_BaseContract = require("../../base/BaseContract.js");
@@ -41,10 +42,12 @@ var PoolQuotaKeeperV310Contract = class extends require_onchain_base_BaseContrac
41
42
  /**
42
43
  * How much more quota the market will take for a token, in the underlying.
43
44
  * `0n` when the market has no quota entry; not the same as {@link hasActiveQuota}.
45
+ * Never negative: a limit lowered under what is already quoted leaves no
46
+ * room, not a debt.
44
47
  */
45
48
  quotaAvailable(token) {
46
49
  const quota = this.quotas.get(token);
47
- return quota ? quota.limit - quota.totalQuoted : 0n;
50
+ return quota ? require_onchain_utils_bigint_math.BigIntMath.max(0n, quota.limit - quota.totalQuoted) : 0n;
48
51
  }
49
52
  /**
50
53
  * Annual quota rate paid on a quoted token, in basis points, or `0` when the
@@ -43,12 +43,11 @@ var OpportunitiesService = class extends require_onchain_base_SDKConstruct.SDKCo
43
43
  * strategy.
44
44
  **/
45
45
  async getStrategy(key) {
46
- const suite = this.sdk.marketRegister.findCreditManager(key.creditManager);
47
- const detail = suite.strategyOpportunityDetail();
48
- if (!detail) throw new Error(`credit manager ${key.creditManager} does not currently offer a strategy`);
49
- const kyc = await suite.kycRequirement(detail.targetCollateral.address);
46
+ const strategy = this.sdk.marketRegister.findCreditManager(key.creditManager).strategy;
47
+ if (!strategy?.isListed) throw new Error(`credit manager ${key.creditManager} does not currently offer a strategy`);
48
+ const kyc = await strategy.kycRequirement();
50
49
  return {
51
- ...detail,
50
+ ...strategy.opportunityDetail(),
52
51
  kyc
53
52
  };
54
53
  }
@@ -60,10 +59,9 @@ var OpportunitiesService = class extends require_onchain_base_SDKConstruct.SDKCo
60
59
  * strategy.
61
60
  **/
62
61
  async isEligibleForStrategy(key, wallet) {
63
- const suite = this.sdk.marketRegister.findCreditManager(key.creditManager);
64
- const opportunity = suite.strategyOpportunity();
65
- if (!opportunity) throw new Error(`credit manager ${key.creditManager} does not currently offer a strategy`);
66
- return suite.isEligibleForStrategy(wallet, opportunity.targetCollateral.address);
62
+ const strategy = this.sdk.marketRegister.findCreditManager(key.creditManager).strategy;
63
+ if (!strategy?.isListed) throw new Error(`credit manager ${key.creditManager} does not currently offer a strategy`);
64
+ return strategy.isEligible(wallet);
67
65
  }
68
66
  };
69
67
  //#endregion
@@ -231,7 +231,7 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
231
231
  const sdk = await this.#chain(strategy.chainId);
232
232
  const at = stateBlock(sdk);
233
233
  Object.assign(state, marketOf(sdk, strategy.creditManager));
234
- const targetToken = params.targetToken ?? sdk.marketRegister.findCreditManager(strategy.creditManager).strategyTargetCollateral;
234
+ const targetToken = params.targetToken ?? sdk.marketRegister.findCreditManager(strategy.creditManager).strategy?.targetCollateral;
235
235
  if (!targetToken) return refused(require_model_errors_prepare_errors.noStrategyTargetCollateral(strategy.creditManager), state);
236
236
  const reused = await reusable(sdk, strategy, params.creditAccount);
237
237
  if (reused && "error" in reused) return refused(reused.error, state);
@@ -20,9 +20,9 @@ import { setLTZero, setLTs } from "./ltUtils.js";
20
20
  import { migrateFaucet } from "./migrateFaucet.js";
21
21
  import { SUPPORTED_RPC_PROVIDERS, getAlchemyUrl, getAnkrUrl, getDrpcUrl, getErpcKey, getRpcProviderUrl, getThirdWebUrl, rpcProvidersSchema } from "./providers.js";
22
22
  import { replaceStorage } from "./replaceStorage.js";
23
- import { resilientTransport, resilientTransportOptionsSchema } from "./resilientTransport.js";
23
+ import { rateLimitOptionsSchema, resilientTransport, resilientTransportOptionsSchema } from "./resilientTransport.js";
24
24
  import { claimDSToken, claimDSTokens, enableDSTokenBackDating } from "./securitizeUtils.js";
25
25
  import "./types.js";
26
26
  import { ONCHAIN_EXECUTION_ID_ADDRESS, verifyTestnet } from "./verifyTestnet.js";
27
27
  import { makePendingWithdrawalsClaimable } from "./withdrawalUtils.js";
28
- export { AccountOpener, Create2Deployer, DEFAULT_CREATE2_SALT, DEFAULT_MIDAS_ADMIN, EthCallSpy, NoAvailableTransportsError, ONCHAIN_EXECUTION_ID_ADDRESS, OpenTxRevertedError, PUBLIC_CREATE2_FACTORY, RevolverTransport, SUPPORTED_RPC_PROVIDERS, SelectionStrategy, anvilNodeInfo, calcLiquidatableLTs, claimDSToken, claimDSTokens, claimFromFaucet, createAnvilClient, createMinter, deployUsingPublicCreate2, detectChain, discoverMidasCreditSuites, discoverMidasGateways, discoverMidasMTokens, enableDSTokenBackDating, evmMineDetailed, extendAnvilClient, getAlchemyUrl, getAnkrUrl, getDrpcUrl, getErpcKey, getPublicCreate2Address, getRpcProviderUrl, getSecuritizeAdmin, getThirdWebUrl, greenlistMidasGateway, httpTransportOptionsSchema, iDegenNftv2Abi, iFaucetAbi, iOnchainExecutionIdAbi, iOwnableAbi, iaclTraitAbi, isAnvil, isDeployedUsingPublicCreate2, isOutOfSyncError, isRangeError, isRateLimitError, isTransientError, logSplitterTransport, makePendingWithdrawalsClaimable, migrateFaucet, providerConfigSchema, registerMidasInvestor, registerRWAInvestor, registerSecuritizeInvestor, replaceStorage, resilientTransport, resilientTransportOptionsSchema, revolverTransportConfigBaseSchema, revolverTransportConfigSchema, rpcProvidersSchema, setLTZero, setLTs, unpauseMidasIssuanceVault, verifyTestnet, writeContractSync };
28
+ export { AccountOpener, Create2Deployer, DEFAULT_CREATE2_SALT, DEFAULT_MIDAS_ADMIN, EthCallSpy, NoAvailableTransportsError, ONCHAIN_EXECUTION_ID_ADDRESS, OpenTxRevertedError, PUBLIC_CREATE2_FACTORY, RevolverTransport, SUPPORTED_RPC_PROVIDERS, SelectionStrategy, anvilNodeInfo, calcLiquidatableLTs, claimDSToken, claimDSTokens, claimFromFaucet, createAnvilClient, createMinter, deployUsingPublicCreate2, detectChain, discoverMidasCreditSuites, discoverMidasGateways, discoverMidasMTokens, enableDSTokenBackDating, evmMineDetailed, extendAnvilClient, getAlchemyUrl, getAnkrUrl, getDrpcUrl, getErpcKey, getPublicCreate2Address, getRpcProviderUrl, getSecuritizeAdmin, getThirdWebUrl, greenlistMidasGateway, httpTransportOptionsSchema, iDegenNftv2Abi, iFaucetAbi, iOnchainExecutionIdAbi, iOwnableAbi, iaclTraitAbi, isAnvil, isDeployedUsingPublicCreate2, isOutOfSyncError, isRangeError, isRateLimitError, isTransientError, logSplitterTransport, makePendingWithdrawalsClaimable, migrateFaucet, providerConfigSchema, rateLimitOptionsSchema, registerMidasInvestor, registerRWAInvestor, registerSecuritizeInvestor, replaceStorage, resilientTransport, resilientTransportOptionsSchema, revolverTransportConfigBaseSchema, revolverTransportConfigSchema, rpcProvidersSchema, setLTZero, setLTs, unpauseMidasIssuanceVault, verifyTestnet, writeContractSync };
@@ -6,6 +6,16 @@ const RATE_LIMIT_PATTERNS = [
6
6
  /exceeded its compute units/i,
7
7
  /retry.{0,10}(in|after)\s+\d/i
8
8
  ];
9
+ const RETRY_HINT_RE = /retry.{0,10}(?:in|after)\s+(\d+(?:\.\d+)?)\s*(ms|milliseconds?|s|secs?|seconds?|m|mins?|minutes?)?\b/i;
10
+ function extractRetryHint(msg) {
11
+ const match = msg.match(RETRY_HINT_RE);
12
+ if (!match) return;
13
+ const value = Number(match[1]);
14
+ const unit = match[2]?.toLowerCase() ?? "s";
15
+ if (unit.startsWith("ms") || unit.startsWith("milli")) return value;
16
+ if (unit.startsWith("m")) return value * 6e4;
17
+ return value * 1e3;
18
+ }
9
19
  function extractRetryAfter(headers) {
10
20
  if (!headers) return;
11
21
  const val = headers.get("retry-after");
@@ -16,24 +26,29 @@ function extractRetryAfter(headers) {
16
26
  if (!Number.isNaN(date)) return Math.max(0, date - Date.now());
17
27
  }
18
28
  /**
19
- * Whether the error indicates rate limiting. Returns `retryAfterMs` from the `Retry-After` header when available.
29
+ * Whether the error indicates rate limiting. Returns `retryAfterMs` from the `Retry-After` header when available,
30
+ * otherwise from a retry hint in the error message (e.g. "retry in 10s").
20
31
  */
21
32
  function isRateLimitError(e) {
22
33
  if (e instanceof BaseError) {
23
34
  let retryAfterMs;
24
35
  if (e.walk((err) => {
25
36
  if (err instanceof HttpRequestError && err.status === 429) {
26
- retryAfterMs = extractRetryAfter(err.headers);
37
+ retryAfterMs = extractRetryAfter(err.headers) ?? extractRetryHint(err.details);
27
38
  return true;
28
39
  }
29
40
  return false;
30
41
  }) !== null) return [true, retryAfterMs];
31
42
  if (e.walk((err) => {
32
43
  const msg = err.details ?? err.message ?? "";
33
- return RATE_LIMIT_PATTERNS.some((re) => re.test(msg));
34
- }) !== null) return [true, void 0];
44
+ if (RATE_LIMIT_PATTERNS.some((re) => re.test(msg))) {
45
+ retryAfterMs = extractRetryHint(msg);
46
+ return true;
47
+ }
48
+ return false;
49
+ }) !== null) return [true, retryAfterMs];
35
50
  }
36
- if (RATE_LIMIT_PATTERNS.some((re) => re.test(e.message))) return [true, void 0];
51
+ if (RATE_LIMIT_PATTERNS.some((re) => re.test(e.message))) return [true, extractRetryHint(e.message)];
37
52
  return [false, void 0];
38
53
  }
39
54
  //#endregion
@@ -4,6 +4,20 @@ import { isTransientError } from "./isTransientError.js";
4
4
  import { withRetry } from "viem";
5
5
  import { z } from "zod/v4";
6
6
  //#region src/dev/resilientTransport.ts
7
+ /** Schema for {@link RateLimitOptions}. */
8
+ const rateLimitOptionsSchema = z.object({
9
+ /**
10
+ * Max retry attempts for rate-limit errors.
11
+ * @default 3
12
+ **/
13
+ retryCount: z.number().int().min(0).default(3),
14
+ /**
15
+ * Upper bound (ms) for rate-limit delay, applied both to backoff and to
16
+ * provider-supplied retry hints.
17
+ * @default 5_000
18
+ **/
19
+ maxDelay: z.number().min(0).default(5e3)
20
+ });
7
21
  /** Schema for {@link ResilientTransportOptions}. */
8
22
  const resilientTransportOptionsSchema = z.object({
9
23
  /**
@@ -27,10 +41,11 @@ const resilientTransportOptionsSchema = z.object({
27
41
  **/
28
42
  jitter: z.number().min(0).default(100),
29
43
  /**
30
- * Retry on rate-limit (HTTP 429) errors.
44
+ * Retry on rate-limit (HTTP 429) errors. `false` disables, `true` uses
45
+ * default {@link RateLimitOptions}, an object overrides them.
31
46
  * @default true
32
47
  **/
33
- handleRateLimit: z.boolean().default(true),
48
+ handleRateLimit: z.union([z.boolean(), rateLimitOptionsSchema]).transform((v) => v === true ? rateLimitOptionsSchema.parse({}) : v).prefault(true),
34
49
  /**
35
50
  * Retry on transient network/infrastructure errors.
36
51
  * @default true
@@ -51,17 +66,24 @@ function resilientTransport(underlyingTransport, options) {
51
66
  return (transportOpts) => {
52
67
  const base = underlyingTransport(transportOpts);
53
68
  const rpcRequest = base.request;
69
+ const rateLimit = opts.handleRateLimit;
70
+ const retryCount = rateLimit ? Math.max(opts.retryCount, rateLimit.retryCount) : opts.retryCount;
54
71
  const request = async (args) => withRetry(() => rpcRequest(args), {
55
- retryCount: opts.retryCount,
72
+ retryCount,
56
73
  delay({ count, error }) {
57
- if (opts.handleRateLimit) {
74
+ const jitter = Math.floor(Math.random() * opts.jitter);
75
+ if (rateLimit) {
58
76
  const [isRate, retryAfterMs] = isRateLimitError(error);
59
- if (isRate && retryAfterMs !== void 0) return retryAfterMs + Math.floor(Math.random() * opts.jitter);
77
+ if (isRate) {
78
+ const base = retryAfterMs ?? opts.delay * 2 ** count;
79
+ return Math.min(rateLimit.maxDelay, base) + jitter;
80
+ }
60
81
  }
61
- return Math.min(opts.maxDelay, opts.delay * 2 ** count) + Math.floor(Math.random() * opts.jitter);
82
+ return Math.min(opts.maxDelay, opts.delay * 2 ** count) + jitter;
62
83
  },
63
- shouldRetry({ error }) {
64
- if (opts.handleRateLimit && isRateLimitError(error)[0]) return true;
84
+ shouldRetry({ count, error }) {
85
+ if (rateLimit && isRateLimitError(error)[0]) return count < rateLimit.retryCount;
86
+ if (count >= opts.retryCount) return false;
65
87
  if (opts.handleTransient && isTransientError(error)) return true;
66
88
  if (opts.handleOutOfSync && isOutOfSyncError(error)) return true;
67
89
  return false;
@@ -74,4 +96,4 @@ function resilientTransport(underlyingTransport, options) {
74
96
  };
75
97
  }
76
98
  //#endregion
77
- export { resilientTransport, resilientTransportOptionsSchema };
99
+ export { rateLimitOptionsSchema, resilientTransport, resilientTransportOptionsSchema };
@@ -33,7 +33,7 @@ function calcLeverageBand({ sdk, creditManager, collateral, targetHF }) {
33
33
  const found = resolveCreditManager(sdk, creditManager);
34
34
  if (!found) return;
35
35
  const { suite, market } = found;
36
- const target = suite.strategyTargetCollateral;
36
+ const target = suite.strategy?.targetCollateral;
37
37
  if (!target) return;
38
38
  const ceiling = suite.creditManager.maxLeverage(target, targetHF);
39
39
  const underlying = market.pool.underlying;
@@ -19,17 +19,19 @@ import { collateralValuation } from "./collateral-valuation.js";
19
19
  * Collateral is valued the way the transaction will be judged — at safe
20
20
  * prices, under its liquidation threshold, capped by the quota the borrow
21
21
  * buys for it, all of which is {@link collateralValuation}'s business. The ceiling
22
- * is then held to what the market will actually lend: the pool's free
23
- * liquidity, the manager's own allowance and the facade's `maxDebt`, whichever
24
- * binds first.
22
+ * is then held to what the market will actually lend,
23
+ * {@link CreditSuite.maxBorrowAmount}: the pool's free liquidity, the
24
+ * manager's own allowance and the facade's `maxDebt`, whichever binds first.
25
25
  *
26
- * The facade's `minDebt` is deliberately not applied. It is a floor, and a
27
- * ceiling answered as `0n` because the collateral is too small for this market
28
- * would tell a form nothing about what it is holding — the number a user needs
29
- * to see is the one they are short of. Collateral that carries something
30
- * therefore answers with it, whether or not the market would lend that little;
31
- * a loan under the floor is refused by `borrow` itself, with `debtOutOfRange`
32
- * naming both ends.
26
+ * The facade's `minDebt` is not applied to the collateral's own ceiling. It
27
+ * is a floor, and a ceiling answered as `0n` because the collateral is too
28
+ * small for this market would tell a form nothing about what it is holding —
29
+ * the number a user needs to see is the one they are short of. Collateral
30
+ * that carries something therefore answers with it, whether or not the market
31
+ * would lend that little; a loan under the floor is refused by `borrow`
32
+ * itself, with `debtOutOfRange` naming both ends. A market whose own capacity
33
+ * is under `minDebt` is different: the answer is `0n`, because no loan of any
34
+ * size exists there.
33
35
  *
34
36
  * Nothing is fetched or simulated — the account does not exist yet and every
35
37
  * input is loaded market state, so a form can call this on each keystroke.
@@ -79,7 +81,9 @@ function maxBorrow(props) {
79
81
  const weighted = valuation.checkedUsd(holding) * valuation.lt(collateralToken);
80
82
  const backed = quotas.some((q) => eq(q.token, collateralToken)) ? BigIntMath.min(valuation.quotaValue(holding), weighted) : weighted;
81
83
  if (backed <= 0n) return 0n;
82
- const ceiling = BigIntMath.min(priceOracle.safeConvertFromUSD(underlying, backed / targetHF).value, suite.maxBorrowAmount().amount.value);
84
+ const lends = suite.maxBorrowAmount().amount.value;
85
+ if (lends < suite.creditFacade.minDebt) return 0n;
86
+ const ceiling = BigIntMath.min(priceOracle.safeConvertFromUSD(underlying, backed / targetHF).value, lends);
83
87
  const unwrapsPayout = !!rwaAsset && eq(borrowToken, rwaAsset);
84
88
  return eq(borrowToken, underlying) ? ceiling : unwrapsPayout ? toTargetDecimals(ceiling, underlying, borrowToken, sdk) : priceOracle.safeConvert(underlying, borrowToken, ceiling).value;
85
89
  }
@@ -1,6 +1,7 @@
1
1
  import "../../../constants/math.js";
2
2
  import "../../../constants/index.js";
3
3
  import { calcMaxLeverage } from "../../../market/math.js";
4
+ import { CreditSuiteStrategy } from "../../../market/credit/CreditSuiteStrategy.js";
4
5
  import { CreditSuite } from "../../../market/credit/CreditSuite.js";
5
6
  import { PositionsService } from "../../../positions/PositionsService.js";
6
7
  import { TestPriceOracle } from "../../../market/oracle/TestPriceOracle.mock.js";
@@ -189,8 +190,10 @@ function buildMockSdk(args) {
189
190
  const strategyName = strategyTargetCollateral ? `${tokenOf(strategyTargetCollateral).symbol} / ${underlyingToken.symbol}` : void 0;
190
191
  const creditManagerSuite = {
191
192
  name: "TestCreditManager",
192
- strategyName,
193
193
  underlyingToken,
194
+ get strategy() {
195
+ return strategyTargetCollateral ? new CreditSuiteStrategy(creditManagerSuite, strategyTargetCollateral) : void 0;
196
+ },
194
197
  accountTargetCollateral: () => strategyTargetCollateral ? tokenOf(strategyTargetCollateral) : null,
195
198
  accountStrategyName: () => strategyName ?? underlyingToken.symbol,
196
199
  liquidationFees: () => MOCK_LIQUIDATION_FEES,
@@ -219,7 +222,6 @@ function buildMockSdk(args) {
219
222
  market,
220
223
  isPaused: facadePaused || poolPaused,
221
224
  forbiddenTokens: [...forbidden],
222
- strategyTargetCollateral,
223
225
  isExpired: expirationDate > 0 && expirationDate < (args.timestamp ?? 0)
224
226
  };
225
227
  const routeCalls = (tokenIn, tokenOut) => {
@@ -356,6 +358,7 @@ function buildMockSdk(args) {
356
358
  }
357
359
  };
358
360
  Object.assign(sdk, { positions: new PositionsService(sdk) });
361
+ Object.assign(creditManagerSuite, { sdk });
359
362
  return sdk;
360
363
  }
361
364
  /** A full account payload carrying exactly what the slice builder reads back. */
@@ -96,8 +96,7 @@ const chains = {
96
96
  "0x89014edc549ffa5c5b6e859b1496731bd035c247": "0x31454faa1daa04cacf59a6bd37681da9160d092a",
97
97
  "0x3b7ab1f4fee570933b24b202de90ffda82f6cae0": "0x31454faa1daa04cacf59a6bd37681da9160d092a",
98
98
  "0x721798d8ccf31ae75c12db82fa72b3806759cbc9": "0x31454faa1daa04cacf59a6bd37681da9160d092a",
99
- "0xd7273d9594ac88f993eda9773041e621633acea0": "0x1a711a5bc48b5c1352c1882fa65dc14b5b9e829d",
100
- "0x34442ca47435e90b80d835aab9737166e76d9962": "0x403cc0d2694ec2639101f32b146b90d766461ce9"
99
+ "0xd7273d9594ac88f993eda9773041e621633acea0": "0x1a711a5bc48b5c1352c1882fa65dc14b5b9e829d"
101
100
  }),
102
101
  sunsetPools: new AddressSet([
103
102
  "0xF791Ecc5F2472637eac9DFe3f7894C0B32C32bDf",
@@ -139,6 +139,7 @@ import { DEGEN_NFT_MIDAS, PHANTOM_TOKEN_MIDAS_REDEMPTION, RWA_LIQUIDATOR_MIDAS }
139
139
  import { MidasDegenNFT } from "./market/rwa/midas/MidasDegenNFT.js";
140
140
  import { DEGEN_NFT_SECURITIZE, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, RWA_LIQUIDATOR_SECURITIZE } from "./market/rwa/securitize/constants.js";
141
141
  import { strategyName } from "./market/strategyName.js";
142
+ import { CreditSuiteStrategy } from "./market/credit/CreditSuiteStrategy.js";
142
143
  import { dominantCollateral, isStrategyCollateral, pickStrategyTargetCollateral } from "./market/credit/collateralUtils.js";
143
144
  import { CreditSuite } from "./market/credit/CreditSuite.js";
144
145
  import { expectedBalanceDeltas } from "./market/credit/expectedBalanceDeltas.js";
@@ -304,4 +305,4 @@ import { replayMulticall } from "./preview/preview/replayMulticall.js";
304
305
  import { previewOperation } from "./preview/preview/previewOperation.js";
305
306
  import "./preview/index.js";
306
307
  import "./types/index.js";
307
- 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_TOKEN_COMPRESSOR, AP_TREASURY, AP_WETH_GATEWAY, AP_WETH_TOKEN, AP_ZAPPER_REGISTER, AP_ZERO_PRICE_FEED, AbstractAdapterContract, AbstractLPPriceFeedContract, AbstractPriceFeedContract, AbstractWithdrawalCompressorContract, AccountBotsService, AccountMigratorAdapterContract, AdapterType, AddressMap, AddressProviderV310Contract, AddressSet, AssetsMap, BLOCKS_PER_WEEK_BY_NETWORK, BalancerStablePriceFeedContract, BalancerV3PoolStatus, BalancerV3RouterAdapterContract, BalancerV3WrapperAdapterContract, BalancerWeightedPriceFeedContract, BaseContract, BasePlugin, BigIntMath, BotPermissions, BoundedPriceFeedContract, CamelotV3AdapterContract, ChainContractsRegister, ChainNotConfiguredError, CompositePriceFeedContract, ConstantPriceFeedContract, Construct, ContractParseError, ConvexV1BaseRewardPoolAdapterContract, ConvexV1BoosterAdapterContract, CreditAccountCompressor, CreditAccountCompressorV310Contract, CreditAccountOperationsService, CreditAccountState, CreditAccountsServiceV310, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, Curve2AssetsAdapterContract, Curve3AssetsAdapterContract, Curve4AssetsAdapterContract, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, CurveV1AdapterStETHContract, CurveV1StableNGAdapterContract, DEFAULT_QUOTA_BUFFER_BPS, DEGEN_NFT_MIDAS, DEGEN_NFT_SECURITIZE, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, DaiUsdsAdapterContract, ERC4626AdapterContract, ERC4626ReferralAdapterContract, EXECUTE_BYTES_SELECTOR, Erc4626PriceFeedContract, ExternalPriceFeedContract, FluidDexAdapterContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, InfinifiGatewayAdapterContract, InfinifiUnwindingGatewayAdapterContract, KelpLRTDepositPoolAdapterContract, KelpLRTWithdrawalManagerAdapterContract, LEVERAGE_DECIMALS, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LidoV1AdapterContract, LinearInterestRateModelContract, LiquidationsService, MAX_INT, MAX_LEVERAGE_BUFFER_BPS, MAX_UINT16, MAX_UINT256, MIN_HEALTH_FACTOR_FACADE, MIN_HEALTH_FACTOR_FORM, MIN_HF_LIMITED, MIN_INT96, MIN_SAFE_HEALTH_FACTOR_FORM, MULTICALL_ADDRESS, MarketRegister, MarketSuite, MellowClaimerAdapterContract, MellowDVVAdapterContract, MellowERC4626VaultAdapterContract, MellowLRTPriceFeedContract, MellowWrapperAdapterContract, MidasDegenNFT, MidasGatewayAdapterContract, MidasIssuanceVaultAdapterContract, MidasLiquidatorContract, MidasRedemptionVaultAdapterContract, 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, PendlePairStatus, PendleRouterAdapterContract, PendleTWAPPTPriceFeed, PendleTokenType, PeripheryCompressorV310Contract, PluginStateVersionError, PoolService, PoolSuite, PoolV310Contract, PositionsService, PriceFeedRef, PriceFeedRegistry, PriceOracleV310Contract, PriceUpdatesCache, PythPriceFeed, RAMP_DURATION_BY_NETWORK, RAY, RAY_DECIMALS_POW, RWARegistry, RWA_COMPRESSOR_ADDRESS, 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, SLIPPAGE_DECIMALS, STATE_VERSION, SUPPORTED_NETWORKS, SdkAlreadyAttachedError, SdkChainMismatchError, SdkMissingChainStateError, SdkNotAttachedError, SdkRWADataNotLoadedError, SdkStateVersionMismatchError, SdkSyncFailedError, SecuritizeDegenNFT, SecuritizeLiquidatorContract, SecuritizeOnRampAdapterContract, SecuritizeRWAFactory, SecuritizeRedemptionGatewayAdapterContract, SimulateWithPriceUpdatesError, SimulationError, StakingRewardsAdapterContract, TokensMeta, TraderJoePoolVersion, TraderJoeRouterAdapterContract, TypedObjectUtils, UniswapV2AdapterContract, UniswapV3AdapterContract, UniswapV4AdapterContract, UpdatablePriceFeedRegistry, UpshiftVaultAdapterContract, VERSION_RANGE_310, VelodromeV2RouterAdapterContract, VotingContractStatus, WAD, WAD_DECIMALS_POW, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, WstETHPriceFeedContract, WstETHV1AdapterContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, ZodAddress, ZodBigInt, ZodHex, accountSnapshotFromCreditAccountData, adapterActionAbi, adapterActionSelectors, adapterActionSignatures, adapterConstructorAbi, allTransfersAsTokenAmounts, amountOf, assetsMap, attachOptionsSchema, botPermissionsToString, bpsToRay, buildDelayedStrategyPositionOperationPreview, bytes32ToString, calcBorrowApy, calcBorrowRate, calcDefaultQuota, calcEffectiveBorrowApy, calcHealthFactor, calcLiquidationPrice, calcLiquidationPriceForTarget, calcMaxLeverage, calcNetStrategyApy, calcPositionLeverage, calcQuotaRate, calcQuotaUpdate, calcRecommendedQuota, calcTimeToLiquidationMs, calcUtilization, calcUtilizationRaw, chains, checkAccountQuotas, checkBorrowLimit, checkCollateralFunding, checkCollateralised, checkCreditAccountFrozen, checkCreditManagerPaused, checkCreditOperation, checkDebtLimits, checkEmergencyLiquidator, checkForbiddenToken, checkHealthFactors, checkIncreaseDebt, checkIncreaseQuota, checkLeverage, checkLiquidation, checkLiquidationEligibility, checkLiquidationFunding, checkLiquidatorEligible, checkMarket, checkMarketExpired, checkMidasAccountGreenlist, checkObtained, checkOperation, checkPoolFunding, checkPoolLiquidity, checkPoolOperation, checkPoolPaused, checkPoolSunset, checkQuotaCount, checkQuotaLimit, checkRWAOpenRequirements, checkRWAOpening, checkReservePriceLimited, checkSimulation, checkWallet, checkWalletAllowance, checkWalletBalance, childLogger, classifyCloseOrRepay, classifyCurveOperation, classifyInnerOperations, collateralPriceInUnderlying, collectTraces, createAdapter, createAddressProvider, createPriceOracle, createRawTx, createRedemptionLogger, createRouter, createWithdrawalCompressor, createZapper, abi as creditFacadeV310Abi, curveAddLiquidityFromTransfers, curveRemoveLiquidityFromTransfers, decodeDelayedIntent, detectDelayedClaim, detectDelayedOperation, detectNetwork, dominantCollateral, encodeDelayedIntent, erc4626ReferralAdapterAbi, estimateClaimableAt, estimateRawTxGas, etherscanApiUrl, etherscanUrl, executeDelegatedMulticalls, executeMulticallBatches, expectedBalanceDeltas, fetchCreditAccountSlice, filterDust, filterDustUSD, findCallTo, findCallWithInput, findCuratorMarketConfigurator, findExecuteBytes, fmtBinaryMask, fnSigToName, formatBN, formatBNvalue, formatDuration, formatLeverage, formatNumberToString_, formatPercentage, formatTimestamp, functionArgsToMap, functionArgsToRecord, generateCastTraceCall, getAccountTargetCollateral, getAdapterActionAbi, getAdapterDeployParamsAbi, getAdapterType, getAssetType, getCastTraceArgs, getChain, getCuratorName, getFunctionSignature, getLegacyStrategyTarget, getNetworkType, getRawPriceUpdates, getSimulateWithPriceUpdatesError, getWithdrawalCompressorAddress, halfRAY, hasAdapterDeployParamsAbi, healthFactorBps, hexEq, hydrateAddressProvider, iBalancerV3RouterAbi, iBalancerV3RouterAdapterAbi, iBalancerV3WrapperAbi, iBalancerV3WrapperAdapterAbi, iBaseOnRampAbi, iBaseRewardPoolAbi, iBoosterAbi, iCamelotV3AdapterAbi, iCamelotV3RouterAbi, iConvexV1BaseRewardPoolAdapterAbi, iConvexV1BoosterAdapterAbi, iCreditAccountAbi, iCurvePoolAbi, iCurvePoolStableNGAbi, iCurvePool_2Abi, iCurvePool_3Abi, iCurvePool_4Abi, iCurveV1StableNgAdapterAbi, iCurveV1_2AssetsAdapterAbi, iCurveV1_3AssetsAdapterAbi, iCurveV1_4AssetsAdapterAbi, iDaiUsdsAbi, iDaiUsdsAdapterAbi, iERC4626Abi, iERC4626ReferralAbi, iFluidDexAbi, iFluidDexAdapterAbi, iInfinifiGatewayAbi, iInfinifiGatewayAdapterAbi, iInfinifiUnwindingGatewayAbi, iInfinifiUnwindingGatewayAdapterAbi, iKelpLRTDepositPoolGatewayAbi, iKelpLRTWithdrawalManagerGatewayAbi, iKelpLrtDepositPoolAdapterAbi, iKelpLrtDepositPoolGatewayAbi, iKelpLrtWithdrawalManagerAdapterAbi, iKelpLrtWithdrawalManagerGatewayAbi, iLidoV1AdapterAbi, iMellow4626VaultAdapterAbi, iMellowClaimerAbi, iMellowClaimerAdapterAbi, iMellowWrapperAbi, iMellowWrapperAdapterAbi, iMidasGatewayAdapterV311Abi, iMidasGatewayV311Abi, iMidasIssuanceVaultAdapterV310Abi, iMidasIssuanceVaultV310Abi, iMidasRedemptionVaultAdapterV310Abi, iMidasRedemptionVaultGatewayV310Abi, iPendleRouterAbi, iPendleRouterAdapterAbi, iSecuritizeOnRampAbi, iSecuritizeOnRampAdapterV310Abi, iSecuritizeRedemptionGatewayAdapterV311Abi, iSecuritizeRedemptionGatewayV311Abi, iStakingRewardsAbi, iStakingRewardsAdapterAbi, iTraderJoeRouterAbi, iTraderJoeRouterAdapterAbi, iUniswapV2AdapterAbi, iUniswapV2Router02Abi, iUniswapV3Abi, iUniswapV3AdapterAbi, iUniswapV4AdapterAbi, iUniswapV4GatewayAbi, iUpshiftVaultAdapterAbi, iUpshiftVaultGatewayAbi, iVelodromeV2RouterAbi, iVelodromeV2RouterAdapterAbi, isCloseOrRepay, isDust, isLPPriceFeed, isPhantomToken, isPoolOperation, isPublicNetwork, isRWAFactory, isRWAOperation, isRWAToken, isStrategyCollateral, isSunsetPool, isSunsetStrategy, isSupportedNetwork, isUpdatablePriceFeed, isV310, isVersionRange, isZeroBalance, iwstETHAbi, iwstEthv1AdapterAbi, json_parse, json_stringify, lidoV1_WETHGatewayAbi, makeReplayState, mellowDvvAdapterAbi, midasGreenlistsAccount, minSeizedAmount, numberWithCommas, onchainSDKOptionsSchema, optimalHFForPartialLiquidation, optimalRepaidAmount, parseAdapterAction, parseAdapterDeployParams, parseFacadeOperationCalldata, parseOperationCalldata, parsePoolOperationCalldata, parsePosNegAmount, parseRWAFactoryOperationCalldata, percentFmt, pickStrategyTargetCollateral, previewAdjustStrategyPosition, previewExitOrRepayStrategyPosition, previewOperation, raise, rayToBps, rayToNumber, replayInnerOperations, replayMulticall, resolveDelayedClaimIntent, resolveProtocolCall, retry, rewardsFromTransfers, roundUpQuota, sendRawTx, shortAddress, shortHash, simulateCall, simulateMulticall, simulateWithPriceUpdates, soleNonUnderlyingCollateral, strategyName, swapFromTransfers, toAddress, toBN, toBigInt, toChainIds, toClaimableWithdrawal, toCreditAccountSlice, toNetTransfers, toPendingWithdrawal, toRequestableWithdrawal, toSignificant, toToken, toTokenAmount, toWithdrawalStatus, updatableDependencies, usdToNumber, watchBlocksAsync };
308
+ 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_TOKEN_COMPRESSOR, AP_TREASURY, AP_WETH_GATEWAY, AP_WETH_TOKEN, AP_ZAPPER_REGISTER, AP_ZERO_PRICE_FEED, AbstractAdapterContract, AbstractLPPriceFeedContract, AbstractPriceFeedContract, AbstractWithdrawalCompressorContract, AccountBotsService, AccountMigratorAdapterContract, AdapterType, AddressMap, AddressProviderV310Contract, AddressSet, AssetsMap, BLOCKS_PER_WEEK_BY_NETWORK, BalancerStablePriceFeedContract, BalancerV3PoolStatus, BalancerV3RouterAdapterContract, BalancerV3WrapperAdapterContract, BalancerWeightedPriceFeedContract, BaseContract, BasePlugin, BigIntMath, BotPermissions, BoundedPriceFeedContract, CamelotV3AdapterContract, ChainContractsRegister, ChainNotConfiguredError, CompositePriceFeedContract, ConstantPriceFeedContract, Construct, ContractParseError, ConvexV1BaseRewardPoolAdapterContract, ConvexV1BoosterAdapterContract, CreditAccountCompressor, CreditAccountCompressorV310Contract, CreditAccountOperationsService, CreditAccountState, CreditAccountsServiceV310, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CreditSuiteStrategy, Curve2AssetsAdapterContract, Curve3AssetsAdapterContract, Curve4AssetsAdapterContract, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, CurveV1AdapterStETHContract, CurveV1StableNGAdapterContract, DEFAULT_QUOTA_BUFFER_BPS, DEGEN_NFT_MIDAS, DEGEN_NFT_SECURITIZE, DELAYED_INTENT_TYPES, DELAYED_INTENT_VERSION, DUST_THRESHOLD, DaiUsdsAdapterContract, ERC4626AdapterContract, ERC4626ReferralAdapterContract, EXECUTE_BYTES_SELECTOR, Erc4626PriceFeedContract, ExternalPriceFeedContract, FluidDexAdapterContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, InfinifiGatewayAdapterContract, InfinifiUnwindingGatewayAdapterContract, KelpLRTDepositPoolAdapterContract, KelpLRTWithdrawalManagerAdapterContract, LEVERAGE_DECIMALS, LIQUIDATION_APPROVAL_BUFFER, LIQUIDATION_COMPRESSOR_V313_ADDRESS, LidoV1AdapterContract, LinearInterestRateModelContract, LiquidationsService, MAX_INT, MAX_LEVERAGE_BUFFER_BPS, MAX_UINT16, MAX_UINT256, MIN_HEALTH_FACTOR_FACADE, MIN_HEALTH_FACTOR_FORM, MIN_HF_LIMITED, MIN_INT96, MIN_SAFE_HEALTH_FACTOR_FORM, MULTICALL_ADDRESS, MarketRegister, MarketSuite, MellowClaimerAdapterContract, MellowDVVAdapterContract, MellowERC4626VaultAdapterContract, MellowLRTPriceFeedContract, MellowWrapperAdapterContract, MidasDegenNFT, MidasGatewayAdapterContract, MidasIssuanceVaultAdapterContract, MidasLiquidatorContract, MidasRedemptionVaultAdapterContract, 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, PendlePairStatus, PendleRouterAdapterContract, PendleTWAPPTPriceFeed, PendleTokenType, PeripheryCompressorV310Contract, PluginStateVersionError, PoolService, PoolSuite, PoolV310Contract, PositionsService, PriceFeedRef, PriceFeedRegistry, PriceOracleV310Contract, PriceUpdatesCache, PythPriceFeed, RAMP_DURATION_BY_NETWORK, RAY, RAY_DECIMALS_POW, RWARegistry, RWA_COMPRESSOR_ADDRESS, 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, SLIPPAGE_DECIMALS, STATE_VERSION, SUPPORTED_NETWORKS, SdkAlreadyAttachedError, SdkChainMismatchError, SdkMissingChainStateError, SdkNotAttachedError, SdkRWADataNotLoadedError, SdkStateVersionMismatchError, SdkSyncFailedError, SecuritizeDegenNFT, SecuritizeLiquidatorContract, SecuritizeOnRampAdapterContract, SecuritizeRWAFactory, SecuritizeRedemptionGatewayAdapterContract, SimulateWithPriceUpdatesError, SimulationError, StakingRewardsAdapterContract, TokensMeta, TraderJoePoolVersion, TraderJoeRouterAdapterContract, TypedObjectUtils, UniswapV2AdapterContract, UniswapV3AdapterContract, UniswapV4AdapterContract, UpdatablePriceFeedRegistry, UpshiftVaultAdapterContract, VERSION_RANGE_310, VelodromeV2RouterAdapterContract, VotingContractStatus, WAD, WAD_DECIMALS_POW, WithdrawalCompressorV310Contract, WithdrawalCompressorV311Contract, WithdrawalCompressorV313Contract, WstETHPriceFeedContract, WstETHV1AdapterContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, ZodAddress, ZodBigInt, ZodHex, accountSnapshotFromCreditAccountData, adapterActionAbi, adapterActionSelectors, adapterActionSignatures, adapterConstructorAbi, allTransfersAsTokenAmounts, amountOf, assetsMap, attachOptionsSchema, botPermissionsToString, bpsToRay, buildDelayedStrategyPositionOperationPreview, bytes32ToString, calcBorrowApy, calcBorrowRate, calcDefaultQuota, calcEffectiveBorrowApy, calcHealthFactor, calcLiquidationPrice, calcLiquidationPriceForTarget, calcMaxLeverage, calcNetStrategyApy, calcPositionLeverage, calcQuotaRate, calcQuotaUpdate, calcRecommendedQuota, calcTimeToLiquidationMs, calcUtilization, calcUtilizationRaw, chains, checkAccountQuotas, checkBorrowLimit, checkCollateralFunding, checkCollateralised, checkCreditAccountFrozen, checkCreditManagerPaused, checkCreditOperation, checkDebtLimits, checkEmergencyLiquidator, checkForbiddenToken, checkHealthFactors, checkIncreaseDebt, checkIncreaseQuota, checkLeverage, checkLiquidation, checkLiquidationEligibility, checkLiquidationFunding, checkLiquidatorEligible, checkMarket, checkMarketExpired, checkMidasAccountGreenlist, checkObtained, checkOperation, checkPoolFunding, checkPoolLiquidity, checkPoolOperation, checkPoolPaused, checkPoolSunset, checkQuotaCount, checkQuotaLimit, checkRWAOpenRequirements, checkRWAOpening, checkReservePriceLimited, checkSimulation, checkWallet, checkWalletAllowance, checkWalletBalance, childLogger, classifyCloseOrRepay, classifyCurveOperation, classifyInnerOperations, collateralPriceInUnderlying, collectTraces, createAdapter, createAddressProvider, createPriceOracle, createRawTx, createRedemptionLogger, createRouter, createWithdrawalCompressor, createZapper, abi as creditFacadeV310Abi, curveAddLiquidityFromTransfers, curveRemoveLiquidityFromTransfers, decodeDelayedIntent, detectDelayedClaim, detectDelayedOperation, detectNetwork, dominantCollateral, encodeDelayedIntent, erc4626ReferralAdapterAbi, estimateClaimableAt, estimateRawTxGas, etherscanApiUrl, etherscanUrl, executeDelegatedMulticalls, executeMulticallBatches, expectedBalanceDeltas, fetchCreditAccountSlice, filterDust, filterDustUSD, findCallTo, findCallWithInput, findCuratorMarketConfigurator, findExecuteBytes, fmtBinaryMask, fnSigToName, formatBN, formatBNvalue, formatDuration, formatLeverage, formatNumberToString_, formatPercentage, formatTimestamp, functionArgsToMap, functionArgsToRecord, generateCastTraceCall, getAccountTargetCollateral, getAdapterActionAbi, getAdapterDeployParamsAbi, getAdapterType, getAssetType, getCastTraceArgs, getChain, getCuratorName, getFunctionSignature, getLegacyStrategyTarget, getNetworkType, getRawPriceUpdates, getSimulateWithPriceUpdatesError, getWithdrawalCompressorAddress, halfRAY, hasAdapterDeployParamsAbi, healthFactorBps, hexEq, hydrateAddressProvider, iBalancerV3RouterAbi, iBalancerV3RouterAdapterAbi, iBalancerV3WrapperAbi, iBalancerV3WrapperAdapterAbi, iBaseOnRampAbi, iBaseRewardPoolAbi, iBoosterAbi, iCamelotV3AdapterAbi, iCamelotV3RouterAbi, iConvexV1BaseRewardPoolAdapterAbi, iConvexV1BoosterAdapterAbi, iCreditAccountAbi, iCurvePoolAbi, iCurvePoolStableNGAbi, iCurvePool_2Abi, iCurvePool_3Abi, iCurvePool_4Abi, iCurveV1StableNgAdapterAbi, iCurveV1_2AssetsAdapterAbi, iCurveV1_3AssetsAdapterAbi, iCurveV1_4AssetsAdapterAbi, iDaiUsdsAbi, iDaiUsdsAdapterAbi, iERC4626Abi, iERC4626ReferralAbi, iFluidDexAbi, iFluidDexAdapterAbi, iInfinifiGatewayAbi, iInfinifiGatewayAdapterAbi, iInfinifiUnwindingGatewayAbi, iInfinifiUnwindingGatewayAdapterAbi, iKelpLRTDepositPoolGatewayAbi, iKelpLRTWithdrawalManagerGatewayAbi, iKelpLrtDepositPoolAdapterAbi, iKelpLrtDepositPoolGatewayAbi, iKelpLrtWithdrawalManagerAdapterAbi, iKelpLrtWithdrawalManagerGatewayAbi, iLidoV1AdapterAbi, iMellow4626VaultAdapterAbi, iMellowClaimerAbi, iMellowClaimerAdapterAbi, iMellowWrapperAbi, iMellowWrapperAdapterAbi, iMidasGatewayAdapterV311Abi, iMidasGatewayV311Abi, iMidasIssuanceVaultAdapterV310Abi, iMidasIssuanceVaultV310Abi, iMidasRedemptionVaultAdapterV310Abi, iMidasRedemptionVaultGatewayV310Abi, iPendleRouterAbi, iPendleRouterAdapterAbi, iSecuritizeOnRampAbi, iSecuritizeOnRampAdapterV310Abi, iSecuritizeRedemptionGatewayAdapterV311Abi, iSecuritizeRedemptionGatewayV311Abi, iStakingRewardsAbi, iStakingRewardsAdapterAbi, iTraderJoeRouterAbi, iTraderJoeRouterAdapterAbi, iUniswapV2AdapterAbi, iUniswapV2Router02Abi, iUniswapV3Abi, iUniswapV3AdapterAbi, iUniswapV4AdapterAbi, iUniswapV4GatewayAbi, iUpshiftVaultAdapterAbi, iUpshiftVaultGatewayAbi, iVelodromeV2RouterAbi, iVelodromeV2RouterAdapterAbi, isCloseOrRepay, isDust, isLPPriceFeed, isPhantomToken, isPoolOperation, isPublicNetwork, isRWAFactory, isRWAOperation, isRWAToken, isStrategyCollateral, isSunsetPool, isSunsetStrategy, isSupportedNetwork, isUpdatablePriceFeed, isV310, isVersionRange, isZeroBalance, iwstETHAbi, iwstEthv1AdapterAbi, json_parse, json_stringify, lidoV1_WETHGatewayAbi, makeReplayState, mellowDvvAdapterAbi, midasGreenlistsAccount, minSeizedAmount, numberWithCommas, onchainSDKOptionsSchema, optimalHFForPartialLiquidation, optimalRepaidAmount, parseAdapterAction, parseAdapterDeployParams, parseFacadeOperationCalldata, parseOperationCalldata, parsePoolOperationCalldata, parsePosNegAmount, parseRWAFactoryOperationCalldata, percentFmt, pickStrategyTargetCollateral, previewAdjustStrategyPosition, previewExitOrRepayStrategyPosition, previewOperation, raise, rayToBps, rayToNumber, replayInnerOperations, replayMulticall, resolveDelayedClaimIntent, resolveProtocolCall, retry, rewardsFromTransfers, roundUpQuota, sendRawTx, shortAddress, shortHash, simulateCall, simulateMulticall, simulateWithPriceUpdates, soleNonUnderlyingCollateral, strategyName, swapFromTransfers, toAddress, toBN, toBigInt, toChainIds, toClaimableWithdrawal, toCreditAccountSlice, toNetTransfers, toPendingWithdrawal, toRequestableWithdrawal, toSignificant, toToken, toTokenAmount, toWithdrawalStatus, updatableDependencies, usdToNumber, watchBlocksAsync };
@@ -236,13 +236,20 @@ var MarketSuite = class extends SDKConstruct {
236
236
  const rows = [];
237
237
  const kind = filter?.kind;
238
238
  if (!isFilterSet(kind) || kind === "pool") rows.push(this.poolOpportunity());
239
- if (!isFilterSet(kind) || kind === "strategy") for (const suite of this.creditManagers) {
240
- const opportunity = suite.strategyOpportunity();
241
- if (opportunity) rows.push(opportunity);
242
- }
239
+ if (!isFilterSet(kind) || kind === "strategy") rows.push(...this.strategies().map((s) => s.opportunity()));
243
240
  return rows.filter((row) => matchesOpportunityFilter(row, filter));
244
241
  }
245
242
  /**
243
+ * Strategies this market lists as opportunities; see
244
+ * {@link CreditSuiteStrategy.isListed}.
245
+ */
246
+ strategies() {
247
+ return this.creditManagers.flatMap((suite) => {
248
+ const strategy = suite.strategy;
249
+ return strategy?.isListed ? [strategy] : [];
250
+ });
251
+ }
252
+ /**
246
253
  * Passive lending into this market's pool, as the shared read model
247
254
  * describes it.
248
255
  */