@gearbox-protocol/sdk 17.3.0 → 17.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -78,6 +78,7 @@ exports.logSplitterTransport = require_dev_logSplitterTransport.logSplitterTrans
78
78
  exports.makePendingWithdrawalsClaimable = require_dev_withdrawalUtils.makePendingWithdrawalsClaimable;
79
79
  exports.migrateFaucet = require_dev_migrateFaucet.migrateFaucet;
80
80
  exports.providerConfigSchema = require_dev_RevolverTransport.providerConfigSchema;
81
+ exports.rateLimitOptionsSchema = require_dev_resilientTransport.rateLimitOptionsSchema;
81
82
  exports.registerMidasInvestor = require_dev_kycUtils.registerMidasInvestor;
82
83
  exports.registerRWAInvestor = require_dev_kycUtils.registerRWAInvestor;
83
84
  exports.registerSecuritizeInvestor = require_dev_kycUtils.registerSecuritizeInvestor;
@@ -7,6 +7,16 @@ const RATE_LIMIT_PATTERNS = [
7
7
  /exceeded its compute units/i,
8
8
  /retry.{0,10}(in|after)\s+\d/i
9
9
  ];
10
+ const RETRY_HINT_RE = /retry.{0,10}(?:in|after)\s+(\d+(?:\.\d+)?)\s*(ms|milliseconds?|s|secs?|seconds?|m|mins?|minutes?)?\b/i;
11
+ function extractRetryHint(msg) {
12
+ const match = msg.match(RETRY_HINT_RE);
13
+ if (!match) return;
14
+ const value = Number(match[1]);
15
+ const unit = match[2]?.toLowerCase() ?? "s";
16
+ if (unit.startsWith("ms") || unit.startsWith("milli")) return value;
17
+ if (unit.startsWith("m")) return value * 6e4;
18
+ return value * 1e3;
19
+ }
10
20
  function extractRetryAfter(headers) {
11
21
  if (!headers) return;
12
22
  const val = headers.get("retry-after");
@@ -17,24 +27,29 @@ function extractRetryAfter(headers) {
17
27
  if (!Number.isNaN(date)) return Math.max(0, date - Date.now());
18
28
  }
19
29
  /**
20
- * Whether the error indicates rate limiting. Returns `retryAfterMs` from the `Retry-After` header when available.
30
+ * Whether the error indicates rate limiting. Returns `retryAfterMs` from the `Retry-After` header when available,
31
+ * otherwise from a retry hint in the error message (e.g. "retry in 10s").
21
32
  */
22
33
  function isRateLimitError(e) {
23
34
  if (e instanceof viem.BaseError) {
24
35
  let retryAfterMs;
25
36
  if (e.walk((err) => {
26
37
  if (err instanceof viem.HttpRequestError && err.status === 429) {
27
- retryAfterMs = extractRetryAfter(err.headers);
38
+ retryAfterMs = extractRetryAfter(err.headers) ?? extractRetryHint(err.details);
28
39
  return true;
29
40
  }
30
41
  return false;
31
42
  }) !== null) return [true, retryAfterMs];
32
43
  if (e.walk((err) => {
33
44
  const msg = err.details ?? err.message ?? "";
34
- return RATE_LIMIT_PATTERNS.some((re) => re.test(msg));
35
- }) !== null) return [true, void 0];
45
+ if (RATE_LIMIT_PATTERNS.some((re) => re.test(msg))) {
46
+ retryAfterMs = extractRetryHint(msg);
47
+ return true;
48
+ }
49
+ return false;
50
+ }) !== null) return [true, retryAfterMs];
36
51
  }
37
- if (RATE_LIMIT_PATTERNS.some((re) => re.test(e.message))) return [true, void 0];
52
+ if (RATE_LIMIT_PATTERNS.some((re) => re.test(e.message))) return [true, extractRetryHint(e.message)];
38
53
  return [false, void 0];
39
54
  }
40
55
  //#endregion
@@ -5,6 +5,20 @@ const require_dev_isTransientError = require("./isTransientError.js");
5
5
  let viem = require("viem");
6
6
  let zod_v4 = require("zod/v4");
7
7
  //#region src/dev/resilientTransport.ts
8
+ /** Schema for {@link RateLimitOptions}. */
9
+ const rateLimitOptionsSchema = zod_v4.z.object({
10
+ /**
11
+ * Max retry attempts for rate-limit errors.
12
+ * @default 3
13
+ **/
14
+ retryCount: zod_v4.z.number().int().min(0).default(3),
15
+ /**
16
+ * Upper bound (ms) for rate-limit delay, applied both to backoff and to
17
+ * provider-supplied retry hints.
18
+ * @default 5_000
19
+ **/
20
+ maxDelay: zod_v4.z.number().min(0).default(5e3)
21
+ });
8
22
  /** Schema for {@link ResilientTransportOptions}. */
9
23
  const resilientTransportOptionsSchema = zod_v4.z.object({
10
24
  /**
@@ -28,10 +42,11 @@ const resilientTransportOptionsSchema = zod_v4.z.object({
28
42
  **/
29
43
  jitter: zod_v4.z.number().min(0).default(100),
30
44
  /**
31
- * Retry on rate-limit (HTTP 429) errors.
45
+ * Retry on rate-limit (HTTP 429) errors. `false` disables, `true` uses
46
+ * default {@link RateLimitOptions}, an object overrides them.
32
47
  * @default true
33
48
  **/
34
- handleRateLimit: zod_v4.z.boolean().default(true),
49
+ handleRateLimit: zod_v4.z.union([zod_v4.z.boolean(), rateLimitOptionsSchema]).transform((v) => v === true ? rateLimitOptionsSchema.parse({}) : v).prefault(true),
35
50
  /**
36
51
  * Retry on transient network/infrastructure errors.
37
52
  * @default true
@@ -52,17 +67,24 @@ function resilientTransport(underlyingTransport, options) {
52
67
  return (transportOpts) => {
53
68
  const base = underlyingTransport(transportOpts);
54
69
  const rpcRequest = base.request;
70
+ const rateLimit = opts.handleRateLimit;
71
+ const retryCount = rateLimit ? Math.max(opts.retryCount, rateLimit.retryCount) : opts.retryCount;
55
72
  const request = async (args) => (0, viem.withRetry)(() => rpcRequest(args), {
56
- retryCount: opts.retryCount,
73
+ retryCount,
57
74
  delay({ count, error }) {
58
- if (opts.handleRateLimit) {
75
+ const jitter = Math.floor(Math.random() * opts.jitter);
76
+ if (rateLimit) {
59
77
  const [isRate, retryAfterMs] = require_dev_isRateLimitError.isRateLimitError(error);
60
- if (isRate && retryAfterMs !== void 0) return retryAfterMs + Math.floor(Math.random() * opts.jitter);
78
+ if (isRate) {
79
+ const base = retryAfterMs ?? opts.delay * 2 ** count;
80
+ return Math.min(rateLimit.maxDelay, base) + jitter;
81
+ }
61
82
  }
62
- return Math.min(opts.maxDelay, opts.delay * 2 ** count) + Math.floor(Math.random() * opts.jitter);
83
+ return Math.min(opts.maxDelay, opts.delay * 2 ** count) + jitter;
63
84
  },
64
- shouldRetry({ error }) {
65
- if (opts.handleRateLimit && require_dev_isRateLimitError.isRateLimitError(error)[0]) return true;
85
+ shouldRetry({ count, error }) {
86
+ if (rateLimit && require_dev_isRateLimitError.isRateLimitError(error)[0]) return count < rateLimit.retryCount;
87
+ if (count >= opts.retryCount) return false;
66
88
  if (opts.handleTransient && require_dev_isTransientError.isTransientError(error)) return true;
67
89
  if (opts.handleOutOfSync && require_dev_isOutOfSyncError.isOutOfSyncError(error)) return true;
68
90
  return false;
@@ -75,5 +97,6 @@ function resilientTransport(underlyingTransport, options) {
75
97
  };
76
98
  }
77
99
  //#endregion
100
+ exports.rateLimitOptionsSchema = rateLimitOptionsSchema;
78
101
  exports.resilientTransport = resilientTransport;
79
102
  exports.resilientTransportOptionsSchema = resilientTransportOptionsSchema;
@@ -112,6 +112,8 @@ const strategyOpportunitySchema = zod_v4.z.object({
112
112
  totalValue: require_model_compare_schema.offchainOnly(require_model_primitives_schema.amountSchema).optional(),
113
113
  utilization: require_model_compare_schema.offchainOnly(require_model_primitives_schema.bpsSchema).optional(),
114
114
  availableLiquidity: require_model_compare_schema.tolerance(require_model_primitives_schema.amountSchema, "amount"),
115
+ totalSupply: require_model_compare_schema.onchainOnly(require_model_primitives_schema.amountSchema).optional(),
116
+ feeInterest: require_model_compare_schema.onchainOnly(require_model_primitives_schema.bpsSchema).optional(),
115
117
  minDebt: require_model_primitives_schema.amountSchema,
116
118
  totalDebtLimit: require_model_primitives_schema.amountSchema,
117
119
  maxBorrowAmount: require_model_compare_schema.tolerance(require_model_primitives_schema.amountSchema, "amount"),
@@ -132,6 +132,8 @@ var CreditSuiteStrategy = class {
132
132
  borrowApy: require_onchain_market_math.calcBorrowApy(pool.baseInterestRate, cm.feeInterest),
133
133
  quotaRate: require_onchain_market_math.calcQuotaRate(market.pool.pqk.quotaRate(targetCollateral), cm.feeInterest),
134
134
  availableLiquidity: oracle.toAmount(pool.underlying, pool.availableLiquidity),
135
+ totalSupply: oracle.toAmount(pool.underlying, pool.expectedLiquidity),
136
+ feeInterest: cm.feeInterest,
135
137
  minDebt: oracle.toAmount(pool.underlying, suite.creditFacade.minDebt),
136
138
  totalDebtLimit: oracle.toAmount(pool.underlying, debtParams?.limit ?? 0n),
137
139
  maxBorrowAmount: oracle.toAmount(pool.underlying, this.maxBorrowAmount().amount.value),
@@ -23,7 +23,7 @@ var OpportunitiesNamespace = class extends require_sdk_AbstractNamespace.Abstrac
23
23
  merge = {
24
24
  list: (onchain, offchain) => require_sdk_utils_mergeChains.mergeChainList(onchain, offchain, this.maxOffchainLagSeconds),
25
25
  pool: (onchain, offchain) => require_sdk_utils_mergeChains.mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds),
26
- strategy: (onchain, offchain) => overlayOnchainKyc(require_sdk_utils_mergeChains.mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds), onchain)
26
+ strategy: (onchain, offchain) => overlayOnchainFields(require_sdk_utils_mergeChains.mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds), onchain)
27
27
  };
28
28
  #prepare;
29
29
  #execute;
@@ -102,17 +102,20 @@ var OpportunitiesNamespace = class extends require_sdk_AbstractNamespace.Abstrac
102
102
  }
103
103
  };
104
104
  /**
105
- * Freshness still picks the body; `kyc` is taken from a successful chain
106
- * response because the backend does not evaluate it.
105
+ * Freshness still picks the body; fields the backend does not serve are taken
106
+ * from a successful chain response.
107
107
  **/
108
- function overlayOnchainKyc(merged, onchain) {
108
+ function overlayOnchainFields(merged, onchain) {
109
109
  if (!merged || !onchain || onchain.meta.chains[0]?.status !== "success") return merged;
110
110
  if (merged === onchain) return merged;
111
111
  return {
112
112
  ...merged,
113
113
  data: {
114
114
  ...merged.data,
115
- kyc: onchain.data.kyc
115
+ kyc: onchain.data.kyc,
116
+ feeInterest: onchain.data.feeInterest,
117
+ totalSupply: onchain.data.totalSupply,
118
+ availableLiquidity: onchain.data.availableLiquidity
116
119
  }
117
120
  };
118
121
  }
@@ -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 };
@@ -1,5 +1,5 @@
1
1
  import { ZodAddress } from "../onchain/utils/zod.js";
2
- import { offchainOnly, tolerance } from "./compare.schema.js";
2
+ import { offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
3
3
  import { amountSchema, assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenSchema, underlyingTokenSchema } from "./primitives.schema.js";
4
4
  import { isFilterSet } from "./filters.js";
5
5
  import { booleanParamSchema, encodeFlag, filterable } from "./filters.schema.js";
@@ -111,6 +111,8 @@ const strategyOpportunitySchema = z.object({
111
111
  totalValue: offchainOnly(amountSchema).optional(),
112
112
  utilization: offchainOnly(bpsSchema).optional(),
113
113
  availableLiquidity: tolerance(amountSchema, "amount"),
114
+ totalSupply: onchainOnly(amountSchema).optional(),
115
+ feeInterest: onchainOnly(bpsSchema).optional(),
114
116
  minDebt: amountSchema,
115
117
  totalDebtLimit: amountSchema,
116
118
  maxBorrowAmount: tolerance(amountSchema, "amount"),
@@ -131,6 +131,8 @@ var CreditSuiteStrategy = class {
131
131
  borrowApy: calcBorrowApy(pool.baseInterestRate, cm.feeInterest),
132
132
  quotaRate: calcQuotaRate(market.pool.pqk.quotaRate(targetCollateral), cm.feeInterest),
133
133
  availableLiquidity: oracle.toAmount(pool.underlying, pool.availableLiquidity),
134
+ totalSupply: oracle.toAmount(pool.underlying, pool.expectedLiquidity),
135
+ feeInterest: cm.feeInterest,
134
136
  minDebt: oracle.toAmount(pool.underlying, suite.creditFacade.minDebt),
135
137
  totalDebtLimit: oracle.toAmount(pool.underlying, debtParams?.limit ?? 0n),
136
138
  maxBorrowAmount: oracle.toAmount(pool.underlying, this.maxBorrowAmount().amount.value),
@@ -22,7 +22,7 @@ var OpportunitiesNamespace = class extends AbstractNamespace {
22
22
  merge = {
23
23
  list: (onchain, offchain) => mergeChainList(onchain, offchain, this.maxOffchainLagSeconds),
24
24
  pool: (onchain, offchain) => mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds),
25
- strategy: (onchain, offchain) => overlayOnchainKyc(mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds), onchain)
25
+ strategy: (onchain, offchain) => overlayOnchainFields(mergeChainOne(onchain, offchain, this.maxOffchainLagSeconds), onchain)
26
26
  };
27
27
  #prepare;
28
28
  #execute;
@@ -101,17 +101,20 @@ var OpportunitiesNamespace = class extends AbstractNamespace {
101
101
  }
102
102
  };
103
103
  /**
104
- * Freshness still picks the body; `kyc` is taken from a successful chain
105
- * response because the backend does not evaluate it.
104
+ * Freshness still picks the body; fields the backend does not serve are taken
105
+ * from a successful chain response.
106
106
  **/
107
- function overlayOnchainKyc(merged, onchain) {
107
+ function overlayOnchainFields(merged, onchain) {
108
108
  if (!merged || !onchain || onchain.meta.chains[0]?.status !== "success") return merged;
109
109
  if (merged === onchain) return merged;
110
110
  return {
111
111
  ...merged,
112
112
  data: {
113
113
  ...merged.data,
114
- kyc: onchain.data.kyc
114
+ kyc: onchain.data.kyc,
115
+ feeInterest: onchain.data.feeInterest,
116
+ totalSupply: onchain.data.totalSupply,
117
+ availableLiquidity: onchain.data.availableLiquidity
115
118
  }
116
119
  };
117
120
  }
@@ -21,9 +21,9 @@ import { createMinter } from "./mint/factory.js";
21
21
  import "./mint/index.js";
22
22
  import { RpcProvider, SUPPORTED_RPC_PROVIDERS, getAlchemyUrl, getAnkrUrl, getDrpcUrl, getErpcKey, getRpcProviderUrl, getThirdWebUrl, rpcProvidersSchema } from "./providers.js";
23
23
  import { ReplaceStorageParams, replaceStorage } from "./replaceStorage.js";
24
- import { ResilientTransportOptions, resilientTransport, resilientTransportOptionsSchema } from "./resilientTransport.js";
24
+ import { RateLimitOptions, ResilientTransportOptions, rateLimitOptionsSchema, resilientTransport, resilientTransportOptionsSchema } from "./resilientTransport.js";
25
25
  import { EnableDSTokenBackDatingProps, RestoreDSTokenBackDating, claimDSToken, claimDSTokens, enableDSTokenBackDating } from "./securitizeUtils.js";
26
26
  import { httpTransportOptionsSchema } from "./transports.js";
27
27
  import { ONCHAIN_EXECUTION_ID_ADDRESS, VerifyTestnetParams, verifyTestnet } from "./verifyTestnet.js";
28
28
  import { MakePendingWithdrawalsClaimableOptions, makePendingWithdrawalsClaimable } from "./withdrawalUtils.js";
29
- export { AccountOpener, AccountOpenerOptions, AnvilActions, AnvilClient, AnvilClientConfig, AnvilDealParameters, AnvilNodeInfo, AnvilRPCSchema, CheckMulticallFn, Create2Deployer, Create2Parameters, DEFAULT_CREATE2_SALT, DEFAULT_MIDAS_ADMIN, DetectedCall, EnableDSTokenBackDatingProps, EnsureExistsUsingPublicCreate2ReturnType, EthCallMethod, EthCallRequest, EthCallSpy, GetCreate2AddressParameters, GreenlistMidasGatewayProps, IMinter, type LogSplitterTransportOptions, MakePendingWithdrawalsClaimableOptions, MidasCreditSuite, NoAvailableTransportsError, ONCHAIN_EXECUTION_ID_ADDRESS, OpenAccountHumanizedPreview, OpenAccountResult, OpenAccountsResult, OpenTxRevertedError, PUBLIC_CREATE2_FACTORY, PoolDepositResult, ProviderConfig, ProviderStatus, RWAKycFailure, RegisterMidasInvestorProps, RegisterRWAInvestorProps, RegisterRWAInvestorResult, RegisterSecuritizeInvestorProps, ReplaceStorageParams, ResilientTransportOptions, RestoreDSTokenBackDating, RestoreMidasIssuanceVaultPause, RevolverTransport, RevolverTransportConfig, RevolverTransportValue, RpcErrorResult, RpcProvider, RpcResponse, RpcSuccessResult, SUPPORTED_RPC_PROVIDERS, SelectionStrategy, TargetAccount, UnpauseMidasIssuanceVaultProps, VerifyTestnetParams, 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 };
29
+ export { AccountOpener, AccountOpenerOptions, AnvilActions, AnvilClient, AnvilClientConfig, AnvilDealParameters, AnvilNodeInfo, AnvilRPCSchema, CheckMulticallFn, Create2Deployer, Create2Parameters, DEFAULT_CREATE2_SALT, DEFAULT_MIDAS_ADMIN, DetectedCall, EnableDSTokenBackDatingProps, EnsureExistsUsingPublicCreate2ReturnType, EthCallMethod, EthCallRequest, EthCallSpy, GetCreate2AddressParameters, GreenlistMidasGatewayProps, IMinter, type LogSplitterTransportOptions, MakePendingWithdrawalsClaimableOptions, MidasCreditSuite, NoAvailableTransportsError, ONCHAIN_EXECUTION_ID_ADDRESS, OpenAccountHumanizedPreview, OpenAccountResult, OpenAccountsResult, OpenTxRevertedError, PUBLIC_CREATE2_FACTORY, PoolDepositResult, ProviderConfig, ProviderStatus, RWAKycFailure, RateLimitOptions, RegisterMidasInvestorProps, RegisterRWAInvestorProps, RegisterRWAInvestorResult, RegisterSecuritizeInvestorProps, ReplaceStorageParams, ResilientTransportOptions, RestoreDSTokenBackDating, RestoreMidasIssuanceVaultPause, RevolverTransport, RevolverTransportConfig, RevolverTransportValue, RpcErrorResult, RpcProvider, RpcResponse, RpcSuccessResult, SUPPORTED_RPC_PROVIDERS, SelectionStrategy, TargetAccount, UnpauseMidasIssuanceVaultProps, VerifyTestnetParams, 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 };
@@ -1,6 +1,7 @@
1
1
  //#region src/dev/isRateLimitError.d.ts
2
2
  /**
3
- * Whether the error indicates rate limiting. Returns `retryAfterMs` from the `Retry-After` header when available.
3
+ * Whether the error indicates rate limiting. Returns `retryAfterMs` from the `Retry-After` header when available,
4
+ * otherwise from a retry hint in the error message (e.g. "retry in 10s").
4
5
  */
5
6
  declare function isRateLimitError(e: Error): [checkResult: boolean, retryAfterMs?: number | undefined];
6
7
  //#endregion
@@ -1,13 +1,29 @@
1
1
  import { Transport } from "viem";
2
2
  import { z } from "zod/v4";
3
3
  //#region src/dev/resilientTransport.d.ts
4
+ /** Schema for {@link RateLimitOptions}. */
5
+ declare const rateLimitOptionsSchema: z.ZodObject<{
6
+ retryCount: z.ZodDefault<z.ZodNumber>;
7
+ maxDelay: z.ZodDefault<z.ZodNumber>;
8
+ }, z.core.$strip>;
9
+ /** Rate-limit retry settings accepted by `handleRateLimit`. */
10
+ type RateLimitOptions = z.input<typeof rateLimitOptionsSchema>;
4
11
  /** Schema for {@link ResilientTransportOptions}. */
5
12
  declare const resilientTransportOptionsSchema: z.ZodObject<{
6
13
  retryCount: z.ZodDefault<z.ZodNumber>;
7
14
  delay: z.ZodDefault<z.ZodNumber>;
8
15
  maxDelay: z.ZodDefault<z.ZodNumber>;
9
16
  jitter: z.ZodDefault<z.ZodNumber>;
10
- handleRateLimit: z.ZodDefault<z.ZodBoolean>;
17
+ handleRateLimit: z.ZodPrefault<z.ZodPipe<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
18
+ retryCount: z.ZodDefault<z.ZodNumber>;
19
+ maxDelay: z.ZodDefault<z.ZodNumber>;
20
+ }, z.core.$strip>]>, z.ZodTransform<false | {
21
+ retryCount: number;
22
+ maxDelay: number;
23
+ }, boolean | {
24
+ retryCount: number;
25
+ maxDelay: number;
26
+ }>>>;
11
27
  handleTransient: z.ZodDefault<z.ZodBoolean>;
12
28
  handleOutOfSync: z.ZodDefault<z.ZodBoolean>;
13
29
  }, z.core.$strip>;
@@ -19,4 +35,4 @@ type ResilientTransportOptions = z.input<typeof resilientTransportOptionsSchema>
19
35
  */
20
36
  declare function resilientTransport(underlyingTransport: Transport, options?: ResilientTransportOptions): Transport;
21
37
  //#endregion
22
- export { ResilientTransportOptions, resilientTransport, resilientTransportOptionsSchema };
38
+ export { RateLimitOptions, ResilientTransportOptions, rateLimitOptionsSchema, resilientTransport, resilientTransportOptionsSchema };
@@ -325,6 +325,19 @@ interface StrategyOpportunity extends OpportunityBase {
325
325
  * underlying. Same value the market's {@link PoolOpportunity} reports.
326
326
  **/
327
327
  availableLiquidity: Amount;
328
+ /**
329
+ * Size of the pool the strategy borrows from, `pool.expectedLiquidity`.
330
+ * Same value the market's {@link PoolOpportunity} reports.
331
+ *
332
+ * @mode onchain
333
+ **/
334
+ totalSupply?: Amount;
335
+ /**
336
+ * Percentage of accrued interest in bps taken by the protocol as profit.
337
+ *
338
+ * @mode onchain
339
+ **/
340
+ feeInterest?: Bps;
328
341
  /**
329
342
  * Smallest debt a position in this credit manager may hold, denominated in
330
343
  * the underlying (`creditFacade.minDebt`).
@@ -425,6 +425,11 @@ declare const strategyOpportunitySchema: z.ZodObject<{
425
425
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
426
426
  valueUsd: z.ZodNullable<z.ZodNumber>;
427
427
  }, z.core.$strip>;
428
+ totalSupply: z.ZodOptional<z.ZodObject<{
429
+ value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
430
+ valueUsd: z.ZodNullable<z.ZodNumber>;
431
+ }, z.core.$strip>>;
432
+ feeInterest: z.ZodOptional<z.ZodNumber>;
428
433
  minDebt: z.ZodObject<{
429
434
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
430
435
  valueUsd: z.ZodNullable<z.ZodNumber>;
@@ -693,6 +698,11 @@ declare const opportunitySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
693
698
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
694
699
  valueUsd: z.ZodNullable<z.ZodNumber>;
695
700
  }, z.core.$strip>;
701
+ totalSupply: z.ZodOptional<z.ZodObject<{
702
+ value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
703
+ valueUsd: z.ZodNullable<z.ZodNumber>;
704
+ }, z.core.$strip>>;
705
+ feeInterest: z.ZodOptional<z.ZodNumber>;
696
706
  minDebt: z.ZodObject<{
697
707
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
698
708
  valueUsd: z.ZodNullable<z.ZodNumber>;
@@ -1080,6 +1090,11 @@ declare const strategyOpportunityDetailSchema: z.ZodObject<{
1080
1090
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
1081
1091
  valueUsd: z.ZodNullable<z.ZodNumber>;
1082
1092
  }, z.core.$strip>;
1093
+ totalSupply: z.ZodOptional<z.ZodObject<{
1094
+ value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
1095
+ valueUsd: z.ZodNullable<z.ZodNumber>;
1096
+ }, z.core.$strip>>;
1097
+ feeInterest: z.ZodOptional<z.ZodNumber>;
1083
1098
  minDebt: z.ZodObject<{
1084
1099
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
1085
1100
  valueUsd: z.ZodNullable<z.ZodNumber>;
@@ -1396,6 +1411,11 @@ declare const opportunityDetailSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1396
1411
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
1397
1412
  valueUsd: z.ZodNullable<z.ZodNumber>;
1398
1413
  }, z.core.$strip>;
1414
+ totalSupply: z.ZodOptional<z.ZodObject<{
1415
+ value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
1416
+ valueUsd: z.ZodNullable<z.ZodNumber>;
1417
+ }, z.core.$strip>>;
1418
+ feeInterest: z.ZodOptional<z.ZodNumber>;
1399
1419
  minDebt: z.ZodObject<{
1400
1420
  value: z.ZodCodec<z.ZodUnion<[z.ZodString, z.ZodBigInt]>, z.ZodBigInt>;
1401
1421
  valueUsd: z.ZodNullable<z.ZodNumber>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "17.3.0",
3
+ "version": "17.4.0",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "repository": {