@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.
- package/dist/cjs/dev/index.js +1 -0
- package/dist/cjs/dev/isRateLimitError.js +20 -5
- package/dist/cjs/dev/resilientTransport.js +31 -8
- package/dist/cjs/model/opportunities.schema.js +2 -0
- package/dist/cjs/onchain/market/credit/CreditSuiteStrategy.js +2 -0
- package/dist/cjs/sdk/opportunities/OpportunitiesNamespace.js +8 -5
- package/dist/esm/dev/index.js +2 -2
- package/dist/esm/dev/isRateLimitError.js +20 -5
- package/dist/esm/dev/resilientTransport.js +31 -9
- package/dist/esm/model/opportunities.schema.js +3 -1
- package/dist/esm/onchain/market/credit/CreditSuiteStrategy.js +2 -0
- package/dist/esm/sdk/opportunities/OpportunitiesNamespace.js +8 -5
- package/dist/types/dev/index.d.ts +2 -2
- package/dist/types/dev/isRateLimitError.d.ts +2 -1
- package/dist/types/dev/resilientTransport.d.ts +18 -2
- package/dist/types/model/opportunities.d.ts +13 -0
- package/dist/types/model/opportunities.schema.d.ts +20 -0
- package/package.json +1 -1
package/dist/cjs/dev/index.js
CHANGED
|
@@ -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
|
-
|
|
35
|
-
|
|
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,
|
|
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().
|
|
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
|
|
73
|
+
retryCount,
|
|
57
74
|
delay({ count, error }) {
|
|
58
|
-
|
|
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
|
|
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) +
|
|
83
|
+
return Math.min(opts.maxDelay, opts.delay * 2 ** count) + jitter;
|
|
63
84
|
},
|
|
64
|
-
shouldRetry({ error }) {
|
|
65
|
-
if (
|
|
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) =>
|
|
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;
|
|
106
|
-
*
|
|
105
|
+
* Freshness still picks the body; fields the backend does not serve are taken
|
|
106
|
+
* from a successful chain response.
|
|
107
107
|
**/
|
|
108
|
-
function
|
|
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
|
}
|
package/dist/esm/dev/index.js
CHANGED
|
@@ -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
|
-
|
|
34
|
-
|
|
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,
|
|
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().
|
|
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
|
|
72
|
+
retryCount,
|
|
56
73
|
delay({ count, error }) {
|
|
57
|
-
|
|
74
|
+
const jitter = Math.floor(Math.random() * opts.jitter);
|
|
75
|
+
if (rateLimit) {
|
|
58
76
|
const [isRate, retryAfterMs] = isRateLimitError(error);
|
|
59
|
-
if (isRate
|
|
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) +
|
|
82
|
+
return Math.min(opts.maxDelay, opts.delay * 2 ** count) + jitter;
|
|
62
83
|
},
|
|
63
|
-
shouldRetry({ error }) {
|
|
64
|
-
if (
|
|
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) =>
|
|
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;
|
|
105
|
-
*
|
|
104
|
+
* Freshness still picks the body; fields the backend does not serve are taken
|
|
105
|
+
* from a successful chain response.
|
|
106
106
|
**/
|
|
107
|
-
function
|
|
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.
|
|
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>;
|