@panoptic-eng/sdk 1.0.69 → 1.0.70
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/cow/index.d.ts.map +1 -1
- package/dist/{cow-BBPknr5W.js → cow-sGuN0eas.js} +1 -1
- package/dist/index.d.ts +36 -36
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/{irm-DurYJ0ht.js → irm-6RzXXa1_.js} +926 -2
- package/dist/panoptic/v2/index.d.ts +156 -2
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +1538 -74
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/panoptic/v2/react-public.d.ts +179 -4
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +1584 -74
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/{providers-DubVMHWU.js → providers-CbcNt27n.js} +2 -1
- package/dist/{rates-B-eRYOTS.js → rates-DDK4ZimJ.js} +2 -2
- package/dist/{router-ChMhfTqT.js → router-njWsLvZc.js} +2 -2
- package/dist/rpc/index.d.ts +9 -1
- package/dist/rpc/index.d.ts.map +1 -1
- package/dist/rpc/index.js +34 -2
- package/dist/rpc/index.js.map +1 -1
- package/dist/{v2-Bo1vZXvR.js → v2-BrG4T_Gh.js} +537 -28
- package/dist/{writes-D53wWDT-.js → writes-CI6Haer-.js} +33 -2
- package/dist/zodiac/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -24,7 +24,8 @@ const infuraChains = {
|
|
|
24
24
|
const RPC_PROVIDER_PRESETS = {
|
|
25
25
|
alchemy: {
|
|
26
26
|
apiKeyEnv: () => ["ALCHEMY_API_KEY"],
|
|
27
|
-
endpoint: (chainId, apiKey) => isAlchemyChainId(chainId) ? { url: `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${apiKey}` } : void 0
|
|
27
|
+
endpoint: (chainId, apiKey) => isAlchemyChainId(chainId) ? { url: `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${apiKey}` } : void 0,
|
|
28
|
+
wsEndpoint: (chainId, apiKey) => isAlchemyChainId(chainId) ? getAlchemyWsRpcUrl(chainId, apiKey) : void 0
|
|
28
29
|
},
|
|
29
30
|
infura: {
|
|
30
31
|
apiKeyEnv: () => ["INFURA_API_KEY"],
|
|
@@ -9704,7 +9704,7 @@ function diagnoseOracleSafeMode(state, parameters, onchainLevel) {
|
|
|
9704
9704
|
* Exported so callers can display the constant; prefer {@link applyMintBuffer}
|
|
9705
9705
|
* over multiplying by it directly, which is how the rounding bug reappears.
|
|
9706
9706
|
*/
|
|
9707
|
-
const MINT_BUFFER =
|
|
9707
|
+
const MINT_BUFFER = 10750000n;
|
|
9708
9708
|
/** `RiskEngine.DECIMALS` — the denominator {@link MINT_BUFFER} is taken over. */
|
|
9709
9709
|
const MINT_BUFFER_DENOMINATOR = 10000000n;
|
|
9710
9710
|
/** The compiled-in default, matching the deployed RiskEngine. */
|
|
@@ -12070,4 +12070,4 @@ function formatPerSecondRateWadAsAprPct(ratePerSecondWad, precision) {
|
|
|
12070
12070
|
}
|
|
12071
12071
|
|
|
12072
12072
|
//#endregion
|
|
12073
|
-
export { AccountInsolventError, AlreadyInitializedError, BatchValidationError, BelowMinimumRedemptionError, CastingError, ChunkHasZeroLiquidityError, ChunkLimitError, CrossPoolError, DEFAULT_MAX_SPREAD, DEFAULT_MINT_BUFFER, DEFAULT_VEGOID, DepositTooLargeError, DuplicateTokenIdError, EffectiveLiquidityAboveThresholdError, ExceedsMaximumRedemptionError, InputListFailError, InsufficientCreditLiquidityError, InvalidBuilderCodeError, InvalidHistoryRangeError, InvalidTickBoundError, InvalidTickError, InvalidTickLimitsError, InvalidTokenIdParameterError, InvalidUniswapCallbackError, LEG_BITS, LEG_LIMITS, LEG_MASKS, LengthMismatchError, LiquidityTooHighError, LoanSlotExhaustedError, MINT_BUFFER, MINT_BUFFER_DENOMINATOR, MaxRetriesExceededError, MissingPositionIdsError, MulticallNoDataError, MulticallResultFailedError, MulticallResultMissingError, NetLiquidityZeroError, NetworkMismatchError, NoLegsExercisableError, NoLoanPositionsError, NotALongLegError, NotBuilderError, NotEnoughLiquidityInChunkError, NotEnoughTokensError, NotGuardianError, NotMarginCalledError, NotPanopticPoolError, OracleRateLimitedError, PanopticError, PanopticHelperNotDeployedError, PanopticValidationError, PoolNotInitializedError, PositionCountNotZeroError, PositionNotOwnedError, PositionSnapshotNotFoundError, PositionTooLargeError, PriceBoundFailError, PriceImpactTooLargeError, ProviderLagError, ReentrancyError, RpcError, RpcResponseError, STANDARD_TICK_WIDTHS, STRIKE_CONVERSION_FACTOR, SafeModeError, StaleDataError, StaleOracleError, StorageDataNotFoundError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, UnsafePremiumSettlementError, WrongPoolIdError, WrongUniswapPoolError, ZeroAddressError, ZeroCollateralRequirementError, annualizePerSecondRateWad, applyMintBuffer, applyMintBufferPerToken, availableToBorrow, clearTrackedPositions, collateralTrackerV2Abi, createFileStorage, createMemoryStorage, createTxResult, decodeAllDispatchCalldata, decodeDispatchCalldata, decodeLeftRightSigned, decodeLeftRightUnsigned, decodeOraclePack, decodeOracleRiskParameters, decodeOracleTiming, decodePosition, decodePositionBalance$1 as decodePositionBalance, decodeSnapshotTransaction, decodeTickSpacing, diagnoseOracleSafeMode, fetchPoolId, formatPerSecondRateWadAsAprPct, formatPerSecondRateWadAsApyPct, formatRateWad, formatTokenAmount, formatTokenAmountSigned, formatTokenDelta, formatTokenFlow, formatWad, formatWadPercent, formatWadSigned, getBlockMeta, getClosedPositionsKey, getOpenPositionIds, getOracleRiskParameters, getOracleState, getPendingPositionsKey, getPool, getPoolCurrentTick, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPosition, getPositionGreeks, getPositionMetaKey, getPositions, getPositionsKey, getRiskParameters, getSchemaVersionKey, getSyncCheckpointKey, getTrackedChunksKey, getTrackedPositionIds, getUtilization, isPanopticErrorType, isPositionTracked, jsonSerializer, mintableAfterBuffer, oracleEpochAt, panopticErrorsAbi, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticLiquidatorAbi, panopticPoolV2Abi, panopticQueryAbi, parsePanopticError, parseTokenAmount, parseWad, recoverSnapshot, recoverSnapshotFromTx, riskEngineAbi, riskEngineMulticall, selectDispatchForAccount, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, submitWrite, uniswapV3PoolAbi, validateBuilderCode };
|
|
12073
|
+
export { AccountInsolventError, AlreadyInitializedError, BatchValidationError, BelowMinimumRedemptionError, CastingError, ChunkHasZeroLiquidityError, ChunkLimitError, CrossPoolError, DEFAULT_MAX_SPREAD, DEFAULT_MINT_BUFFER, DEFAULT_VEGOID, DepositTooLargeError, DuplicateTokenIdError, EffectiveLiquidityAboveThresholdError, ExceedsMaximumRedemptionError, InputListFailError, InsufficientCreditLiquidityError, InvalidBuilderCodeError, InvalidHistoryRangeError, InvalidTickBoundError, InvalidTickError, InvalidTickLimitsError, InvalidTokenIdParameterError, InvalidUniswapCallbackError, LEG_BITS, LEG_LIMITS, LEG_MASKS, LengthMismatchError, LiquidityTooHighError, LoanSlotExhaustedError, MINT_BUFFER, MINT_BUFFER_DENOMINATOR, MaxRetriesExceededError, MissingPositionIdsError, MulticallNoDataError, MulticallResultFailedError, MulticallResultMissingError, NetLiquidityZeroError, NetworkMismatchError, NoLegsExercisableError, NoLoanPositionsError, NotALongLegError, NotBuilderError, NotEnoughLiquidityInChunkError, NotEnoughTokensError, NotGuardianError, NotMarginCalledError, NotPanopticPoolError, OracleRateLimitedError, PanopticError, PanopticHelperNotDeployedError, PanopticValidationError, PoolNotInitializedError, PositionCountNotZeroError, PositionNotOwnedError, PositionSnapshotNotFoundError, PositionTooLargeError, PriceBoundFailError, PriceImpactTooLargeError, ProviderLagError, ReentrancyError, RpcError, RpcResponseError, STANDARD_TICK_WIDTHS, STRIKE_CONVERSION_FACTOR, SafeModeError, StaleDataError, StaleOracleError, StorageDataNotFoundError, SwapTokenMismatchError, SyncTimeoutError, TOKEN_ID_BITS, TokenIdHasZeroLegsError, TooManyLegsOpenError, TransferFailedError, UnauthorizedUniswapCallbackError, UnderOverFlowError, UnhealthyPoolError, UnsafePremiumSettlementError, WrongPoolIdError, WrongUniswapPoolError, ZeroAddressError, ZeroCollateralRequirementError, annualizePerSecondRateWad, applyMintBuffer, applyMintBufferPerToken, availableToBorrow, clearTrackedPositions, collateralTrackerV2Abi, createFileStorage, createMemoryStorage, createTxResult, decodeAllDispatchCalldata, decodeDispatchCalldata, decodeLeftRightSigned, decodeLeftRightUnsigned, decodeOraclePack, decodeOracleRiskParameters, decodeOracleTiming, decodePosition, decodePositionBalance$1 as decodePositionBalance, decodeSnapshotTransaction, decodeTickSpacing, diagnoseOracleSafeMode, fetchPoolId, formatPerSecondRateWadAsAprPct, formatPerSecondRateWadAsApyPct, formatRateWad, formatTokenAmount, formatTokenAmountSigned, formatTokenDelta, formatTokenFlow, formatWad, formatWadPercent, formatWadSigned, getBlockMeta, getClosedPositionsKey, getOpenPositionIds, getOracleRiskParameters, getOracleState, getPendingPositionsKey, getPool, getPoolCurrentTick, getPoolMetaKey, getPoolMetadata, getPoolPrefix, getPosition, getPositionGreeks, getPositionMetaKey, getPositions, getPositionsKey, getRiskParameters, getSchemaVersionKey, getSyncCheckpointKey, getTrackedChunksKey, getTrackedPositionIds, getUtilization, isPanopticErrorType, isPositionTracked, jsonSerializer, mintableAfterBuffer, oracleEpochAt, panopticErrorsAbi, panopticFactoryV3Abi, panopticFactoryV4Abi, panopticGuardianAbi, panopticLiquidatorAbi, panopticPoolV2Abi, panopticQueryAbi as panopticQueryAbi$1, parsePanopticError, parseTokenAmount, parseWad, recoverSnapshot, recoverSnapshotFromTx, riskEngineAbi, riskEngineMulticall, selectDispatchForAccount, semiFungiblePositionManagerV3Abi, semiFungiblePositionManagerV4Abi, stateViewAbi, submitWrite, uniswapV3PoolAbi, validateBuilderCode };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StateViewAbi } from "./StateView-q4yMpBY6.js";
|
|
2
|
-
import { PanopticError, getBlockMeta, getPool, getPoolMetadata, stateViewAbi, submitWrite, uniswapV3PoolAbi } from "./rates-
|
|
2
|
+
import { PanopticError, getBlockMeta, getPool, getPoolMetadata, stateViewAbi, submitWrite, uniswapV3PoolAbi } from "./rates-DDK4ZimJ.js";
|
|
3
3
|
import { getLegLiquidityRange, tickToSqrtPriceX96 } from "./greeks-DNPP24KL.js";
|
|
4
|
-
import { decodeAllLegs, decodeTokenId } from "./writes-
|
|
4
|
+
import { decodeAllLegs, decodeTokenId } from "./writes-CI6Haer-.js";
|
|
5
5
|
import { BaseError, ContractFunctionRevertedError, ExecutionRevertedError, encodeAbiParameters, encodeFunctionData, encodePacked, erc20Abi, isAddressEqual, maxUint256, toHex, zeroAddress } from "viem";
|
|
6
6
|
import Decimal from "decimal.js";
|
|
7
7
|
|
package/dist/rpc/index.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ type RpcProviderPreset = {
|
|
|
21
21
|
url: string;
|
|
22
22
|
headers?: Record<string, string>;
|
|
23
23
|
} | undefined;
|
|
24
|
+
/** Websocket endpoint for `chainId`, or undefined when the vendor does not serve one. */
|
|
25
|
+
wsEndpoint?: (chainId: number, apiKey: string) => string | undefined;
|
|
24
26
|
};
|
|
25
27
|
declare const alchemyChains: {
|
|
26
28
|
readonly 1: "eth-mainnet";
|
|
@@ -74,6 +76,12 @@ declare const DEFAULT_RPC_PROVIDERS: readonly RpcProviderName[];
|
|
|
74
76
|
* Blank values count as unset. Throws when nothing resolves.
|
|
75
77
|
*/
|
|
76
78
|
declare function resolveRpcEndpoints(chainId: number, env: RpcEnv, options?: ResolveRpcEndpointsOptions): RpcEndpoint[];
|
|
79
|
+
/**
|
|
80
|
+
* Websocket RPC URL for `chainId`: `RPC_WS_URL_<chainId>`, else the first preset
|
|
81
|
+
* in `RPC_PROVIDERS` (or the defaults) that has an API key and serves websockets.
|
|
82
|
+
* Returns undefined when nothing is configured; throws on a non-ws(s) URL.
|
|
83
|
+
*/
|
|
84
|
+
declare function resolveRpcWsUrl(chainId: number, env: RpcEnv): string | undefined;
|
|
77
85
|
|
|
78
86
|
//#endregion
|
|
79
87
|
//#region src/rpc/transport.d.ts
|
|
@@ -111,5 +119,5 @@ declare function rpcForkArgs(endpoints: readonly RpcEndpoint[]): {
|
|
|
111
119
|
declare function ponderRpc(endpoints: readonly RpcEndpoint[]): string | string[] | Transport;
|
|
112
120
|
|
|
113
121
|
//#endregion
|
|
114
|
-
export { AlchemyChainId, DEFAULT_RPC_PROVIDERS, RPC_PROVIDER_PRESETS, ResolveRpcEndpointsOptions, RpcEndpoint, RpcEnv, RpcHttpConfig, RpcProviderName, RpcProviderPreset, RpcTransportOptions, getAlchemyRpcUrl, getAlchemyWsRpcUrl, ponderRpc, redactRpcSecrets, resolveRpcEndpoints, rpcForkArgs, rpcHttp, rpcTransport };
|
|
122
|
+
export { AlchemyChainId, DEFAULT_RPC_PROVIDERS, RPC_PROVIDER_PRESETS, ResolveRpcEndpointsOptions, RpcEndpoint, RpcEnv, RpcHttpConfig, RpcProviderName, RpcProviderPreset, RpcTransportOptions, getAlchemyRpcUrl, getAlchemyWsRpcUrl, ponderRpc, redactRpcSecrets, resolveRpcEndpoints, resolveRpcWsUrl, rpcForkArgs, rpcHttp, rpcTransport };
|
|
115
123
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/rpc/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["RpcProviderPreset","Record","alchemyChains","AlchemyChainId","RpcProviderName","RPC_PROVIDER_PRESETS","Readonly","isRpcProviderName","getAlchemyRpcUrl","getAlchemyWsRpcUrl","redactRpcSecrets","RpcProviderName","RpcEnv","Record","Readonly","RpcEndpoint","ResolveRpcEndpointsOptions","DEFAULT_RPC_PROVIDERS","resolveRpcEndpoints","viem1","HttpTransportConfig","Transport","RpcEndpoint","RpcHttpConfig","Omit","rpcHttp","viem0","RpcSchema","HttpTransport","RpcTransportOptions","rpcTransport","failover","requestsPerSecond","rpcForkArgs","ponderRpc"],"sources":["../../src/rpc/providers.d.ts","../../src/rpc/redact.d.ts","../../src/rpc/resolve.d.ts","../../src/rpc/transport.d.ts"],"sourcesContent":null,"mappings":";;;;;;;;;;;;;;;KAKYA,iBAAAA;;;;;IAAAA,GAAAA,EAAAA,MAAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["RpcProviderPreset","Record","alchemyChains","AlchemyChainId","RpcProviderName","RPC_PROVIDER_PRESETS","Readonly","isRpcProviderName","getAlchemyRpcUrl","getAlchemyWsRpcUrl","redactRpcSecrets","RpcProviderName","RpcEnv","Record","Readonly","RpcEndpoint","ResolveRpcEndpointsOptions","DEFAULT_RPC_PROVIDERS","resolveRpcEndpoints","resolveRpcWsUrl","viem1","HttpTransportConfig","Transport","RpcEndpoint","RpcHttpConfig","Omit","rpcHttp","viem0","RpcSchema","HttpTransport","RpcTransportOptions","rpcTransport","failover","requestsPerSecond","rpcForkArgs","ponderRpc"],"sources":["../../src/rpc/providers.d.ts","../../src/rpc/redact.d.ts","../../src/rpc/resolve.d.ts","../../src/rpc/transport.d.ts"],"sourcesContent":null,"mappings":";;;;;;;;;;;;;;;KAKYA,iBAAAA;;;;;IAAAA,GAAAA,EAAAA,MAAAA;IAWEE,OAAAA,CAAAA,EALIW,MAcjB,CAAA,MAAA,EAAA,MAAA,CAAA;EACWV,CAAAA,GAAAA,SAAAA;EACAQ;EACSN,UAAAA,CAAAA,EAAAA,CAAAA,OAAAA,EAA0E,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,GAAA,MAAA,GAAA,SAAA;CAAA;cAZjFH,aAY6CS,EAAAA;EAAe,SAAEX,CAAAA,EAAAA,aAAAA;EAAiB,SAAzCa,GAAAA,EAAAA,iBAAAA;EAAM,SAAfC,KAAAA,EAAAA,aAAAA;EAAQ,SAAA,IAAA,EAAA,cAAA;EAE3BN,SAAAA,EAAAA,EAAAA,aAAgB;EAChBC,SAAAA,GAAAA,EAAAA,kBAA4BN;;;;KALxCA,cAAAA,gBAA8BD;KAC9BS,eAAAA;cACSN,sBAAsBS,SAASD,OAAOF,iBAAiBX;iBAEpDQ,gBAAAA,UAA0BL;ACzB1BO,iBD0BAD,kBAAAA,CC1BgB,OAAA,ED0BYN,cC1BZ,EAAA,aAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA;;;;;;;iBAAhBO,gBAAAA;;;;KCJZE,MAAAA,GAASE,SAASD;KAClBU,WAAAA;;UAEAZ;;;WAGCE;;KAEDG,0BAAAA;EFJAhB;EAWEE,YAAAA,CAAAA,EAAAA,SASb,MAAA,EAAA;EACWC;EACAQ,gBAAAA,CAAAA,EAAe,SEdKA,eFcL,EAAA;AAC3B,CAAA;AAA+F,cEb1EM,qBFa0E,EAAA,SEb1CN,eFa0C,EAAA;;;;;AAA5C;AAEnD;AACA;;;;;iBEJwBO,mBAAAA,uBAA0CN,kBAAkBI,6BAA6BO;;;;ADtBjH;;iBC4BwBJ,eAAAA,uBAAsCP;;;;KC/BlDY,aAAAA,GAAgBC,KAAKJ;;iBAETK,OAAAA,WAAkBH,sBAAsBC,gBAAqEJ,KAAAA,CAAtCS,cAAlBF,KAAAA,CAA+CC,SAAAA;KAChHE,mBAAAA,GAAsBN;;;;;AHAlC;EAWctB,QAAAA,CAAAA,EAAAA,OASb;EACWC;EACAQ,iBAAAA,CAAe,EAAA,MAAA;AAC3B,CAAA;;;;;AAA2CG,iBGTnBiB,YAAAA,CHSmBjB,SAAAA,EAAAA,SGTcS,WHSdT,EAAAA,EAAAA;EAAAA,QAAAA;EAAAA,iBAAAA;EAAAA,GAAAA;AAAAA,CAAAA,CAAAA,EGT0EgB,mBHS1EhB,CAAAA,EGTgGQ,SHShGR;AAAQ;AAE3BN,iBGTA0B,WAAAA,CHS0B/B,SAAAA,EAAc,SGTRoB,WHSQ,EAAA,CAAA,EAAA;EACxCd,OAAAA,EAAAA,MAAAA;;;;;;;iBGFA0B,SAAAA,qBAA8BZ,oCAAoCD"}
|
package/dist/rpc/index.js
CHANGED
|
@@ -26,7 +26,8 @@ const infuraChains = {
|
|
|
26
26
|
const RPC_PROVIDER_PRESETS = {
|
|
27
27
|
alchemy: {
|
|
28
28
|
apiKeyEnv: () => ["ALCHEMY_API_KEY"],
|
|
29
|
-
endpoint: (chainId, apiKey) => isAlchemyChainId(chainId) ? { url: `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${apiKey}` } : void 0
|
|
29
|
+
endpoint: (chainId, apiKey) => isAlchemyChainId(chainId) ? { url: `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${apiKey}` } : void 0,
|
|
30
|
+
wsEndpoint: (chainId, apiKey) => isAlchemyChainId(chainId) ? getAlchemyWsRpcUrl(chainId, apiKey) : void 0
|
|
30
31
|
},
|
|
31
32
|
infura: {
|
|
32
33
|
apiKeyEnv: () => ["INFURA_API_KEY"],
|
|
@@ -106,6 +107,14 @@ function isHttpUrl(value) {
|
|
|
106
107
|
return false;
|
|
107
108
|
}
|
|
108
109
|
}
|
|
110
|
+
function isWsUrl(value) {
|
|
111
|
+
try {
|
|
112
|
+
const { protocol } = new URL(value);
|
|
113
|
+
return protocol === "ws:" || protocol === "wss:";
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
109
118
|
function presetApiKey(name, chainId, env) {
|
|
110
119
|
for (const envName of RPC_PROVIDER_PRESETS[name].apiKeyEnv(chainId)) {
|
|
111
120
|
const key = present(env[envName]);
|
|
@@ -194,6 +203,29 @@ function resolveRpcEndpoints(chainId, env, options = {}) {
|
|
|
194
203
|
...keyEnv
|
|
195
204
|
].join(", ")}`);
|
|
196
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Websocket RPC URL for `chainId`: `RPC_WS_URL_<chainId>`, else the first preset
|
|
208
|
+
* in `RPC_PROVIDERS` (or the defaults) that has an API key and serves websockets.
|
|
209
|
+
* Returns undefined when nothing is configured; throws on a non-ws(s) URL.
|
|
210
|
+
*/
|
|
211
|
+
function resolveRpcWsUrl(chainId, env) {
|
|
212
|
+
const envName = `RPC_WS_URL_${chainId}`;
|
|
213
|
+
const explicit = present(env[envName]);
|
|
214
|
+
if (explicit !== void 0) {
|
|
215
|
+
if (!isWsUrl(explicit)) throw new Error(`${envName} must be a ws(s) URL`);
|
|
216
|
+
return explicit;
|
|
217
|
+
}
|
|
218
|
+
const providers = present(env.RPC_PROVIDERS) ? splitList(env.RPC_PROVIDERS) : DEFAULT_RPC_PROVIDERS;
|
|
219
|
+
for (const name of providers) {
|
|
220
|
+
if (!isRpcProviderName(name)) continue;
|
|
221
|
+
const wsEndpoint = RPC_PROVIDER_PRESETS[name].wsEndpoint;
|
|
222
|
+
const apiKey = presetApiKey(name, chainId, env);
|
|
223
|
+
if (wsEndpoint === void 0 || apiKey === void 0) continue;
|
|
224
|
+
const url = wsEndpoint(chainId, apiKey);
|
|
225
|
+
if (url !== void 0) return url;
|
|
226
|
+
}
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
197
229
|
|
|
198
230
|
//#endregion
|
|
199
231
|
//#region src/rpc/rateLimit.ts
|
|
@@ -266,5 +298,5 @@ function ponderRpc(endpoints) {
|
|
|
266
298
|
}
|
|
267
299
|
|
|
268
300
|
//#endregion
|
|
269
|
-
export { DEFAULT_RPC_PROVIDERS, RPC_PROVIDER_PRESETS, getAlchemyRpcUrl, getAlchemyWsRpcUrl, ponderRpc, redactRpcSecrets, resolveRpcEndpoints, rpcForkArgs, rpcHttp, rpcTransport };
|
|
301
|
+
export { DEFAULT_RPC_PROVIDERS, RPC_PROVIDER_PRESETS, getAlchemyRpcUrl, getAlchemyWsRpcUrl, ponderRpc, redactRpcSecrets, resolveRpcEndpoints, resolveRpcWsUrl, rpcForkArgs, rpcHttp, rpcTransport };
|
|
270
302
|
//# sourceMappingURL=index.js.map
|
package/dist/rpc/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["chainId: number","infuraChains: Record<number, string>","RPC_PROVIDER_PRESETS: Readonly<Record<RpcProviderName, RpcProviderPreset>>","name: string","chainId: AlchemyChainId","alchemyApiKey: string","raw: string","text: string | undefined","DEFAULT_RPC_PROVIDERS: readonly RpcProviderName[]","value: string | undefined","envName: string","headers: Record<string, string>","value: string","name: RpcProviderName","chainId: number","env: RpcEnv","legacyUrlEnv: readonly string[]","providers: readonly string[]","endpoints: RpcEndpoint[]","options: ResolveRpcEndpointsOptions","requestsPerSecond: number","fetchFn: NonNullable<HttpTransportConfig['fetchFn']>","endpoint: RpcEndpoint","config: RpcHttpConfig","endpoints: readonly RpcEndpoint[]"],"sources":["../../src/rpc/providers.ts","../../src/rpc/redact.ts","../../src/rpc/resolve.ts","../../src/rpc/rateLimit.ts","../../src/rpc/transport.ts"],"sourcesContent":["/**\n * The only place that knows RPC vendor URL formats and credentials. Supporting\n * a new vendor means adding one preset here; services select it through env\n * (see `resolveRpcEndpoints`).\n */\n\nexport type RpcProviderPreset = {\n /** Env vars holding the API key for `chainId`, highest precedence first. */\n apiKeyEnv: (chainId: number) => readonly string[]\n /** Endpoint for `chainId`, or undefined when the vendor does not serve it. */\n endpoint: (\n chainId: number,\n apiKey: string,\n ) => { url: string; headers?: Record<string, string> } | undefined\n}\n\nconst alchemyChains = {\n 1: 'eth-mainnet',\n 137: 'polygon-mainnet',\n 42161: 'arb-mainnet',\n 8453: 'base-mainnet',\n 10: 'opt-mainnet',\n 130: 'unichain-mainnet',\n 4663: 'robinhood-mainnet',\n 11155111: 'eth-sepolia',\n} as const\n\nexport type AlchemyChainId = keyof typeof alchemyChains\n\nfunction isAlchemyChainId(chainId: number): chainId is AlchemyChainId {\n return chainId in alchemyChains\n}\n\nconst infuraChains: Record<number, string> = {\n 1: 'mainnet',\n 10: 'optimism-mainnet',\n 137: 'polygon-mainnet',\n 8453: 'base-mainnet',\n 42161: 'arbitrum-mainnet',\n 43114: 'avalanche-mainnet',\n 11155111: 'sepolia',\n}\n\nexport type RpcProviderName = 'alchemy' | 'infura' | 'uniblock'\n\nexport const RPC_PROVIDER_PRESETS: Readonly<Record<RpcProviderName, RpcProviderPreset>> = {\n alchemy: {\n apiKeyEnv: () => ['ALCHEMY_API_KEY'],\n endpoint: (chainId, apiKey) =>\n isAlchemyChainId(chainId)\n ? { url: `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${apiKey}` }\n : undefined,\n },\n infura: {\n apiKeyEnv: () => ['INFURA_API_KEY'],\n endpoint: (chainId, apiKey) =>\n infuraChains[chainId]\n ? { url: `https://${infuraChains[chainId]}.infura.io/v3/${apiKey}` }\n : undefined,\n },\n uniblock: {\n apiKeyEnv: () => ['UNIBLOCK_API_KEY'],\n // Uniblock accepts the key only as a header, and serves keyless requests\n // from an anonymous tier — callers must never send it without one.\n endpoint: (chainId, apiKey) => ({\n url: `https://api.uniblock.dev/uni/v1/json-rpc?chainId=${chainId}`,\n headers: { 'x-api-key': apiKey },\n }),\n },\n}\n\nexport function isRpcProviderName(name: string): name is RpcProviderName {\n return Object.prototype.hasOwnProperty.call(RPC_PROVIDER_PRESETS, name)\n}\n\nexport function getAlchemyRpcUrl(chainId: AlchemyChainId, alchemyApiKey: string): string {\n if (alchemyChains[chainId]) {\n return `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${alchemyApiKey}`\n } else {\n throw new Error(`Unsupported chainId: ${chainId}`)\n }\n}\n\nexport function getAlchemyWsRpcUrl(chainId: AlchemyChainId, alchemyApiKey: string): string {\n if (alchemyChains[chainId]) {\n return `wss://${alchemyChains[chainId]}.g.alchemy.com/v2/${alchemyApiKey}`\n } else {\n throw new Error(`Unsupported chainId: ${chainId}`)\n }\n}\n","const URL_PATTERN = /\\b(?:https?|wss?):\\/\\/[^\\s\"'<>)]+/giu\n// Unquoted authentication values can contain commas and quotes, so mask through the line boundary.\nconst CREDENTIAL_HEADER_PATTERN =\n /\\b(x-api-key|authorization|proxy-authorization)([\"']?\\s*[:=]\\s*)(?:([\"'])(?:\\\\.|(?!\\3)[^\\\\\\r\\n])*\\3|[^\\r\\n]+)/giu\n\nfunction redactUrl(raw: string): string {\n try {\n const url = new URL(raw)\n const port = url.port ? `:${url.port}` : ''\n return `${url.protocol}//${url.hostname}${port}/<redacted>`\n } catch {\n return '<redacted-url>'\n }\n}\n\n/**\n * Strip RPC credentials from text before it is logged or shown. Providers\n * embed keys in the URL path or query, so every URL keeps only its origin;\n * credential header values are masked too.\n */\nexport function redactRpcSecrets(text: string | undefined): string {\n if (!text) return ''\n return text\n .replace(CREDENTIAL_HEADER_PATTERN, '$1$2$3<redacted>$3')\n .replace(URL_PATTERN, redactUrl)\n}\n","import { type RpcProviderName, isRpcProviderName, RPC_PROVIDER_PRESETS } from './providers'\n\nexport type RpcEnv = Readonly<Record<string, string | undefined>>\n\nexport type RpcEndpoint = {\n /** Preset name, or `'url'` for an explicit URL entry. */\n source: RpcProviderName | 'url'\n url: string\n /** Credentials that must accompany every request to `url`, and only to `url`. */\n headers: Record<string, string>\n}\n\nexport type ResolveRpcEndpointsOptions = {\n /** Service-specific URL variables honoured when `RPC_URL_<chainId>` is unset, in order. */\n legacyUrlEnv?: readonly string[]\n /** Presets tried, in order, when no URL is configured. Overridden by `RPC_PROVIDERS`. */\n defaultProviders?: readonly RpcProviderName[]\n}\n\nexport const DEFAULT_RPC_PROVIDERS: readonly RpcProviderName[] = ['alchemy', 'uniblock']\n\nfunction present(value: string | undefined): string | undefined {\n const trimmed = value?.trim()\n return trimmed ? trimmed : undefined\n}\n\nfunction splitList(value: string | undefined): string[] {\n return (value ?? '')\n .split(',')\n .map((entry) => entry.trim())\n .filter((entry) => entry !== '')\n}\n\nfunction parseHeaders(value: string | undefined, envName: string): Record<string, string> {\n const headers: Record<string, string> = {}\n for (const pair of splitHeaderPairs(value)) {\n const separator = pair.indexOf(':')\n const name = pair.slice(0, separator).trim()\n if (separator <= 0 || name === '') {\n throw new Error(`${envName} must be \"Name: value\" pairs separated by \";\"`)\n }\n headers[name] = pair.slice(separator + 1).trim()\n }\n return headers\n}\n\nfunction splitHeaderPairs(value: string | undefined): string[] {\n return (value ?? '')\n .split(';')\n .map((pair) => pair.trim())\n .filter((pair) => pair !== '')\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value)\n return protocol === 'http:' || protocol === 'https:'\n } catch {\n return false\n }\n}\n\nfunction presetApiKey(name: RpcProviderName, chainId: number, env: RpcEnv) {\n for (const envName of RPC_PROVIDER_PRESETS[name].apiKeyEnv(chainId)) {\n const key = present(env[envName])\n if (key !== undefined) return key\n }\n return undefined\n}\n\nfunction presetEndpoint(\n name: RpcProviderName,\n chainId: number,\n env: RpcEnv,\n): RpcEndpoint | undefined {\n const apiKey = presetApiKey(name, chainId, env)\n if (apiKey === undefined) return undefined\n const endpoint = RPC_PROVIDER_PRESETS[name].endpoint(chainId, apiKey)\n return endpoint && { source: name, url: endpoint.url, headers: endpoint.headers ?? {} }\n}\n\nfunction explicitEndpoints(chainId: number, env: RpcEnv): RpcEndpoint[] {\n const listEnv = `RPC_URL_${chainId}`\n return splitList(env[listEnv]).map((entry, index) => {\n if (isHttpUrl(entry)) {\n const headersEnv = `RPC_HEADERS_${chainId}_${index}`\n return { source: 'url', url: entry, headers: parseHeaders(env[headersEnv], headersEnv) }\n }\n if (!isRpcProviderName(entry)) {\n throw new Error(`${listEnv} entry \"${entry}\" is neither an http(s) URL nor a known provider`)\n }\n const endpoint = presetEndpoint(entry, chainId, env)\n if (endpoint === undefined) {\n const keyEnv = RPC_PROVIDER_PRESETS[entry].apiKeyEnv(chainId).join(' or ')\n throw new Error(\n `${listEnv} lists \"${entry}\", which needs ${keyEnv} and must serve chain ${chainId}`,\n )\n }\n return endpoint\n })\n}\n\nfunction legacyEndpoints(env: RpcEnv, legacyUrlEnv: readonly string[]): RpcEndpoint[] {\n return legacyUrlEnv.flatMap((envName) =>\n splitList(env[envName]).map((url): RpcEndpoint => ({ source: 'url', url, headers: {} })),\n )\n}\n\nfunction firstPresetEndpoint(\n chainId: number,\n env: RpcEnv,\n providers: readonly string[],\n): RpcEndpoint | undefined {\n for (const name of providers) {\n if (!isRpcProviderName(name)) {\n throw new Error(`RPC_PROVIDERS entry \"${name}\" is not a known provider`)\n }\n const endpoint = presetEndpoint(name, chainId, env)\n if (endpoint !== undefined) return endpoint\n }\n return undefined\n}\n\nfunction dedupe(endpoints: RpcEndpoint[]): RpcEndpoint[] {\n const seen = new Set<string>()\n return endpoints.filter((endpoint) => {\n const key = `${endpoint.url}\\n${JSON.stringify(endpoint.headers)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\n/**\n * Ordered RPC endpoints for `chainId` (primary first, the rest failover):\n *\n * 1. `RPC_URL_<chainId>` — comma-separated URLs and/or preset names; entry `n`\n * gets headers from `RPC_HEADERS_<chainId>_<n>` (\"Name: value;Name: value\").\n * 2. Otherwise the service's legacy URL variables (`legacyUrlEnv`).\n * 3. Otherwise the first preset in `RPC_PROVIDERS` (or `defaultProviders`)\n * that has an API key and serves the chain.\n *\n * Blank values count as unset. Throws when nothing resolves.\n */\nexport function resolveRpcEndpoints(\n chainId: number,\n env: RpcEnv,\n options: ResolveRpcEndpointsOptions = {},\n): RpcEndpoint[] {\n const explicit = explicitEndpoints(chainId, env)\n if (explicit.length > 0) return dedupe(explicit)\n\n const legacyUrlEnv = options.legacyUrlEnv ?? []\n const legacy = legacyEndpoints(env, legacyUrlEnv)\n if (legacy.length > 0) return dedupe(legacy)\n\n const providers = present(env.RPC_PROVIDERS)\n ? splitList(env.RPC_PROVIDERS)\n : (options.defaultProviders ?? DEFAULT_RPC_PROVIDERS)\n const preset = firstPresetEndpoint(chainId, env, providers)\n if (preset !== undefined) return [preset]\n\n const keyEnv = [\n ...new Set(\n providers.flatMap((name) =>\n isRpcProviderName(name) ? RPC_PROVIDER_PRESETS[name].apiKeyEnv(chainId) : [],\n ),\n ),\n ]\n throw new Error(\n `No RPC configured for chain ${chainId}: set ${[`RPC_URL_${chainId}`, ...legacyUrlEnv, ...keyEnv].join(', ')}`,\n )\n}\n","import type { HttpTransportConfig } from 'viem'\n\n/** Limits HTTP attempts, including retries, across clients sharing this fetch function. */\nexport function rateLimitedRpcFetch(\n requestsPerSecond: number,\n fetchFn: NonNullable<HttpTransportConfig['fetchFn']> = fetch,\n): NonNullable<HttpTransportConfig['fetchFn']> {\n if (!Number.isFinite(requestsPerSecond) || requestsPerSecond <= 0) {\n throw new Error('RPC requestsPerSecond must be positive and finite')\n }\n const intervalMs = Math.ceil(1_000 / requestsPerSecond)\n let nextStart = 0\n let tail = Promise.resolve()\n\n return (input, init) => {\n const signal = init?.signal ?? (input instanceof Request ? input.signal : undefined)\n const request = tail.then(async () => {\n signal?.throwIfAborted()\n const delay = nextStart - Date.now()\n if (delay > 0) await new Promise<void>((resolve) => setTimeout(resolve, delay))\n signal?.throwIfAborted()\n nextStart = Date.now() + intervalMs\n return fetchFn(input, init)\n })\n tail = request.then(\n () => undefined,\n () => undefined,\n )\n return request\n }\n}\n","import { type HttpTransportConfig, type Transport, fallback, http } from 'viem'\n\nimport { rateLimitedRpcFetch } from './rateLimit'\nimport type { RpcEndpoint } from './resolve'\n\nexport type RpcHttpConfig = Omit<HttpTransportConfig, 'fetchOptions'>\n\n/** viem HTTP transport for one endpoint, carrying its credential headers. */\nexport function rpcHttp(endpoint: RpcEndpoint, config: RpcHttpConfig = {}) {\n return http(endpoint.url, { ...config, fetchOptions: { headers: endpoint.headers } })\n}\n\nexport type RpcTransportOptions = RpcHttpConfig & {\n /**\n * Fail over to later endpoints. Disable for clients that submit\n * transactions: a tx broadcast through one provider and retried through\n * another surfaces as \"already known\" / \"nonce too low\" although it was sent.\n */\n failover?: boolean\n /** Shared HTTP attempt limit, including retries and failover. Disables HTTP batching. */\n requestsPerSecond?: number\n}\n\n/**\n * Transport over resolved endpoints: plain HTTP for one endpoint, otherwise an\n * unranked viem `fallback` in configured order.\n */\nexport function rpcTransport(\n endpoints: readonly RpcEndpoint[],\n { failover = true, requestsPerSecond, ...config }: RpcTransportOptions = {},\n): Transport {\n const httpConfig =\n requestsPerSecond === undefined\n ? config\n : {\n ...config,\n batch: false as const,\n fetchFn: rateLimitedRpcFetch(requestsPerSecond, config.fetchFn),\n }\n const [primary, ...rest] = endpoints\n if (primary === undefined) throw new Error('rpcTransport needs at least one endpoint')\n if (!failover || rest.length === 0) return rpcHttp(primary, httpConfig)\n return fallback(\n endpoints.map((endpoint) => rpcHttp(endpoint, httpConfig)),\n { rank: false },\n )\n}\n\n/** anvil fork arguments for the primary endpoint (`--fork-header` only when it needs one). */\nexport function rpcForkArgs(endpoints: readonly RpcEndpoint[]): {\n forkUrl: string\n forkHeader?: string\n} {\n const [primary] = endpoints\n if (primary === undefined) throw new Error('rpcForkArgs needs at least one endpoint')\n const headers = Object.entries(primary.headers)\n if (headers.length === 0) return { forkUrl: primary.url }\n if (headers.length > 1) throw new Error('anvil --fork-header supports one header per fork')\n const [[name, value]] = headers\n return { forkUrl: primary.url, forkHeader: `${name}: ${value}` }\n}\n\n/**\n * Value for a Ponder chain's `rpc`. Header-free endpoints stay plain URLs so\n * Ponder keeps its own load balancing; credential headers need a transport.\n */\nexport function ponderRpc(endpoints: readonly RpcEndpoint[]): string | string[] | Transport {\n if (endpoints.some((endpoint) => Object.keys(endpoint.headers).length > 0)) {\n return rpcTransport(endpoints)\n }\n const urls = endpoints.map((endpoint) => endpoint.url)\n return urls.length === 1 ? urls[0] : urls\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["chainId: number","infuraChains: Record<number, string>","RPC_PROVIDER_PRESETS: Readonly<Record<RpcProviderName, RpcProviderPreset>>","name: string","chainId: AlchemyChainId","alchemyApiKey: string","raw: string","text: string | undefined","DEFAULT_RPC_PROVIDERS: readonly RpcProviderName[]","value: string | undefined","envName: string","headers: Record<string, string>","value: string","name: RpcProviderName","chainId: number","env: RpcEnv","legacyUrlEnv: readonly string[]","providers: readonly string[]","endpoints: RpcEndpoint[]","options: ResolveRpcEndpointsOptions","requestsPerSecond: number","fetchFn: NonNullable<HttpTransportConfig['fetchFn']>","endpoint: RpcEndpoint","config: RpcHttpConfig","endpoints: readonly RpcEndpoint[]"],"sources":["../../src/rpc/providers.ts","../../src/rpc/redact.ts","../../src/rpc/resolve.ts","../../src/rpc/rateLimit.ts","../../src/rpc/transport.ts"],"sourcesContent":["/**\n * The only place that knows RPC vendor URL formats and credentials. Supporting\n * a new vendor means adding one preset here; services select it through env\n * (see `resolveRpcEndpoints`).\n */\n\nexport type RpcProviderPreset = {\n /** Env vars holding the API key for `chainId`, highest precedence first. */\n apiKeyEnv: (chainId: number) => readonly string[]\n /** Endpoint for `chainId`, or undefined when the vendor does not serve it. */\n endpoint: (\n chainId: number,\n apiKey: string,\n ) => { url: string; headers?: Record<string, string> } | undefined\n /** Websocket endpoint for `chainId`, or undefined when the vendor does not serve one. */\n wsEndpoint?: (chainId: number, apiKey: string) => string | undefined\n}\n\nconst alchemyChains = {\n 1: 'eth-mainnet',\n 137: 'polygon-mainnet',\n 42161: 'arb-mainnet',\n 8453: 'base-mainnet',\n 10: 'opt-mainnet',\n 130: 'unichain-mainnet',\n 4663: 'robinhood-mainnet',\n 11155111: 'eth-sepolia',\n} as const\n\nexport type AlchemyChainId = keyof typeof alchemyChains\n\nfunction isAlchemyChainId(chainId: number): chainId is AlchemyChainId {\n return chainId in alchemyChains\n}\n\nconst infuraChains: Record<number, string> = {\n 1: 'mainnet',\n 10: 'optimism-mainnet',\n 137: 'polygon-mainnet',\n 8453: 'base-mainnet',\n 42161: 'arbitrum-mainnet',\n 43114: 'avalanche-mainnet',\n 11155111: 'sepolia',\n}\n\nexport type RpcProviderName = 'alchemy' | 'infura' | 'uniblock'\n\nexport const RPC_PROVIDER_PRESETS: Readonly<Record<RpcProviderName, RpcProviderPreset>> = {\n alchemy: {\n apiKeyEnv: () => ['ALCHEMY_API_KEY'],\n endpoint: (chainId, apiKey) =>\n isAlchemyChainId(chainId)\n ? { url: `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${apiKey}` }\n : undefined,\n wsEndpoint: (chainId, apiKey) =>\n isAlchemyChainId(chainId) ? getAlchemyWsRpcUrl(chainId, apiKey) : undefined,\n },\n infura: {\n apiKeyEnv: () => ['INFURA_API_KEY'],\n endpoint: (chainId, apiKey) =>\n infuraChains[chainId]\n ? { url: `https://${infuraChains[chainId]}.infura.io/v3/${apiKey}` }\n : undefined,\n },\n uniblock: {\n apiKeyEnv: () => ['UNIBLOCK_API_KEY'],\n // Uniblock accepts the key only as a header, and serves keyless requests\n // from an anonymous tier — callers must never send it without one.\n endpoint: (chainId, apiKey) => ({\n url: `https://api.uniblock.dev/uni/v1/json-rpc?chainId=${chainId}`,\n headers: { 'x-api-key': apiKey },\n }),\n },\n}\n\nexport function isRpcProviderName(name: string): name is RpcProviderName {\n return Object.prototype.hasOwnProperty.call(RPC_PROVIDER_PRESETS, name)\n}\n\nexport function getAlchemyRpcUrl(chainId: AlchemyChainId, alchemyApiKey: string): string {\n if (alchemyChains[chainId]) {\n return `https://${alchemyChains[chainId]}.g.alchemy.com/v2/${alchemyApiKey}`\n } else {\n throw new Error(`Unsupported chainId: ${chainId}`)\n }\n}\n\nexport function getAlchemyWsRpcUrl(chainId: AlchemyChainId, alchemyApiKey: string): string {\n if (alchemyChains[chainId]) {\n return `wss://${alchemyChains[chainId]}.g.alchemy.com/v2/${alchemyApiKey}`\n } else {\n throw new Error(`Unsupported chainId: ${chainId}`)\n }\n}\n","const URL_PATTERN = /\\b(?:https?|wss?):\\/\\/[^\\s\"'<>)]+/giu\n// Unquoted authentication values can contain commas and quotes, so mask through the line boundary.\nconst CREDENTIAL_HEADER_PATTERN =\n /\\b(x-api-key|authorization|proxy-authorization)([\"']?\\s*[:=]\\s*)(?:([\"'])(?:\\\\.|(?!\\3)[^\\\\\\r\\n])*\\3|[^\\r\\n]+)/giu\n\nfunction redactUrl(raw: string): string {\n try {\n const url = new URL(raw)\n const port = url.port ? `:${url.port}` : ''\n return `${url.protocol}//${url.hostname}${port}/<redacted>`\n } catch {\n return '<redacted-url>'\n }\n}\n\n/**\n * Strip RPC credentials from text before it is logged or shown. Providers\n * embed keys in the URL path or query, so every URL keeps only its origin;\n * credential header values are masked too.\n */\nexport function redactRpcSecrets(text: string | undefined): string {\n if (!text) return ''\n return text\n .replace(CREDENTIAL_HEADER_PATTERN, '$1$2$3<redacted>$3')\n .replace(URL_PATTERN, redactUrl)\n}\n","import { type RpcProviderName, isRpcProviderName, RPC_PROVIDER_PRESETS } from './providers'\n\nexport type RpcEnv = Readonly<Record<string, string | undefined>>\n\nexport type RpcEndpoint = {\n /** Preset name, or `'url'` for an explicit URL entry. */\n source: RpcProviderName | 'url'\n url: string\n /** Credentials that must accompany every request to `url`, and only to `url`. */\n headers: Record<string, string>\n}\n\nexport type ResolveRpcEndpointsOptions = {\n /** Service-specific URL variables honoured when `RPC_URL_<chainId>` is unset, in order. */\n legacyUrlEnv?: readonly string[]\n /** Presets tried, in order, when no URL is configured. Overridden by `RPC_PROVIDERS`. */\n defaultProviders?: readonly RpcProviderName[]\n}\n\nexport const DEFAULT_RPC_PROVIDERS: readonly RpcProviderName[] = ['alchemy', 'uniblock']\n\nfunction present(value: string | undefined): string | undefined {\n const trimmed = value?.trim()\n return trimmed ? trimmed : undefined\n}\n\nfunction splitList(value: string | undefined): string[] {\n return (value ?? '')\n .split(',')\n .map((entry) => entry.trim())\n .filter((entry) => entry !== '')\n}\n\nfunction parseHeaders(value: string | undefined, envName: string): Record<string, string> {\n const headers: Record<string, string> = {}\n for (const pair of splitHeaderPairs(value)) {\n const separator = pair.indexOf(':')\n const name = pair.slice(0, separator).trim()\n if (separator <= 0 || name === '') {\n throw new Error(`${envName} must be \"Name: value\" pairs separated by \";\"`)\n }\n headers[name] = pair.slice(separator + 1).trim()\n }\n return headers\n}\n\nfunction splitHeaderPairs(value: string | undefined): string[] {\n return (value ?? '')\n .split(';')\n .map((pair) => pair.trim())\n .filter((pair) => pair !== '')\n}\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value)\n return protocol === 'http:' || protocol === 'https:'\n } catch {\n return false\n }\n}\n\nfunction isWsUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value)\n return protocol === 'ws:' || protocol === 'wss:'\n } catch {\n return false\n }\n}\n\nfunction presetApiKey(name: RpcProviderName, chainId: number, env: RpcEnv) {\n for (const envName of RPC_PROVIDER_PRESETS[name].apiKeyEnv(chainId)) {\n const key = present(env[envName])\n if (key !== undefined) return key\n }\n return undefined\n}\n\nfunction presetEndpoint(\n name: RpcProviderName,\n chainId: number,\n env: RpcEnv,\n): RpcEndpoint | undefined {\n const apiKey = presetApiKey(name, chainId, env)\n if (apiKey === undefined) return undefined\n const endpoint = RPC_PROVIDER_PRESETS[name].endpoint(chainId, apiKey)\n return endpoint && { source: name, url: endpoint.url, headers: endpoint.headers ?? {} }\n}\n\nfunction explicitEndpoints(chainId: number, env: RpcEnv): RpcEndpoint[] {\n const listEnv = `RPC_URL_${chainId}`\n return splitList(env[listEnv]).map((entry, index) => {\n if (isHttpUrl(entry)) {\n const headersEnv = `RPC_HEADERS_${chainId}_${index}`\n return { source: 'url', url: entry, headers: parseHeaders(env[headersEnv], headersEnv) }\n }\n if (!isRpcProviderName(entry)) {\n throw new Error(`${listEnv} entry \"${entry}\" is neither an http(s) URL nor a known provider`)\n }\n const endpoint = presetEndpoint(entry, chainId, env)\n if (endpoint === undefined) {\n const keyEnv = RPC_PROVIDER_PRESETS[entry].apiKeyEnv(chainId).join(' or ')\n throw new Error(\n `${listEnv} lists \"${entry}\", which needs ${keyEnv} and must serve chain ${chainId}`,\n )\n }\n return endpoint\n })\n}\n\nfunction legacyEndpoints(env: RpcEnv, legacyUrlEnv: readonly string[]): RpcEndpoint[] {\n return legacyUrlEnv.flatMap((envName) =>\n splitList(env[envName]).map((url): RpcEndpoint => ({ source: 'url', url, headers: {} })),\n )\n}\n\nfunction firstPresetEndpoint(\n chainId: number,\n env: RpcEnv,\n providers: readonly string[],\n): RpcEndpoint | undefined {\n for (const name of providers) {\n if (!isRpcProviderName(name)) {\n throw new Error(`RPC_PROVIDERS entry \"${name}\" is not a known provider`)\n }\n const endpoint = presetEndpoint(name, chainId, env)\n if (endpoint !== undefined) return endpoint\n }\n return undefined\n}\n\nfunction dedupe(endpoints: RpcEndpoint[]): RpcEndpoint[] {\n const seen = new Set<string>()\n return endpoints.filter((endpoint) => {\n const key = `${endpoint.url}\\n${JSON.stringify(endpoint.headers)}`\n if (seen.has(key)) return false\n seen.add(key)\n return true\n })\n}\n\n/**\n * Ordered RPC endpoints for `chainId` (primary first, the rest failover):\n *\n * 1. `RPC_URL_<chainId>` — comma-separated URLs and/or preset names; entry `n`\n * gets headers from `RPC_HEADERS_<chainId>_<n>` (\"Name: value;Name: value\").\n * 2. Otherwise the service's legacy URL variables (`legacyUrlEnv`).\n * 3. Otherwise the first preset in `RPC_PROVIDERS` (or `defaultProviders`)\n * that has an API key and serves the chain.\n *\n * Blank values count as unset. Throws when nothing resolves.\n */\nexport function resolveRpcEndpoints(\n chainId: number,\n env: RpcEnv,\n options: ResolveRpcEndpointsOptions = {},\n): RpcEndpoint[] {\n const explicit = explicitEndpoints(chainId, env)\n if (explicit.length > 0) return dedupe(explicit)\n\n const legacyUrlEnv = options.legacyUrlEnv ?? []\n const legacy = legacyEndpoints(env, legacyUrlEnv)\n if (legacy.length > 0) return dedupe(legacy)\n\n const providers = present(env.RPC_PROVIDERS)\n ? splitList(env.RPC_PROVIDERS)\n : (options.defaultProviders ?? DEFAULT_RPC_PROVIDERS)\n const preset = firstPresetEndpoint(chainId, env, providers)\n if (preset !== undefined) return [preset]\n\n const keyEnv = [\n ...new Set(\n providers.flatMap((name) =>\n isRpcProviderName(name) ? RPC_PROVIDER_PRESETS[name].apiKeyEnv(chainId) : [],\n ),\n ),\n ]\n throw new Error(\n `No RPC configured for chain ${chainId}: set ${[`RPC_URL_${chainId}`, ...legacyUrlEnv, ...keyEnv].join(', ')}`,\n )\n}\n\n/**\n * Websocket RPC URL for `chainId`: `RPC_WS_URL_<chainId>`, else the first preset\n * in `RPC_PROVIDERS` (or the defaults) that has an API key and serves websockets.\n * Returns undefined when nothing is configured; throws on a non-ws(s) URL.\n */\nexport function resolveRpcWsUrl(chainId: number, env: RpcEnv): string | undefined {\n const envName = `RPC_WS_URL_${chainId}`\n const explicit = present(env[envName])\n if (explicit !== undefined) {\n if (!isWsUrl(explicit)) throw new Error(`${envName} must be a ws(s) URL`)\n return explicit\n }\n const providers = present(env.RPC_PROVIDERS)\n ? splitList(env.RPC_PROVIDERS)\n : DEFAULT_RPC_PROVIDERS\n for (const name of providers) {\n if (!isRpcProviderName(name)) continue\n const wsEndpoint = RPC_PROVIDER_PRESETS[name].wsEndpoint\n const apiKey = presetApiKey(name, chainId, env)\n if (wsEndpoint === undefined || apiKey === undefined) continue\n const url = wsEndpoint(chainId, apiKey)\n if (url !== undefined) return url\n }\n return undefined\n}\n","import type { HttpTransportConfig } from 'viem'\n\n/** Limits HTTP attempts, including retries, across clients sharing this fetch function. */\nexport function rateLimitedRpcFetch(\n requestsPerSecond: number,\n fetchFn: NonNullable<HttpTransportConfig['fetchFn']> = fetch,\n): NonNullable<HttpTransportConfig['fetchFn']> {\n if (!Number.isFinite(requestsPerSecond) || requestsPerSecond <= 0) {\n throw new Error('RPC requestsPerSecond must be positive and finite')\n }\n const intervalMs = Math.ceil(1_000 / requestsPerSecond)\n let nextStart = 0\n let tail = Promise.resolve()\n\n return (input, init) => {\n const signal = init?.signal ?? (input instanceof Request ? input.signal : undefined)\n const request = tail.then(async () => {\n signal?.throwIfAborted()\n const delay = nextStart - Date.now()\n if (delay > 0) await new Promise<void>((resolve) => setTimeout(resolve, delay))\n signal?.throwIfAborted()\n nextStart = Date.now() + intervalMs\n return fetchFn(input, init)\n })\n tail = request.then(\n () => undefined,\n () => undefined,\n )\n return request\n }\n}\n","import { type HttpTransportConfig, type Transport, fallback, http } from 'viem'\n\nimport { rateLimitedRpcFetch } from './rateLimit'\nimport type { RpcEndpoint } from './resolve'\n\nexport type RpcHttpConfig = Omit<HttpTransportConfig, 'fetchOptions'>\n\n/** viem HTTP transport for one endpoint, carrying its credential headers. */\nexport function rpcHttp(endpoint: RpcEndpoint, config: RpcHttpConfig = {}) {\n return http(endpoint.url, { ...config, fetchOptions: { headers: endpoint.headers } })\n}\n\nexport type RpcTransportOptions = RpcHttpConfig & {\n /**\n * Fail over to later endpoints. Disable for clients that submit\n * transactions: a tx broadcast through one provider and retried through\n * another surfaces as \"already known\" / \"nonce too low\" although it was sent.\n */\n failover?: boolean\n /** Shared HTTP attempt limit, including retries and failover. Disables HTTP batching. */\n requestsPerSecond?: number\n}\n\n/**\n * Transport over resolved endpoints: plain HTTP for one endpoint, otherwise an\n * unranked viem `fallback` in configured order.\n */\nexport function rpcTransport(\n endpoints: readonly RpcEndpoint[],\n { failover = true, requestsPerSecond, ...config }: RpcTransportOptions = {},\n): Transport {\n const httpConfig =\n requestsPerSecond === undefined\n ? config\n : {\n ...config,\n batch: false as const,\n fetchFn: rateLimitedRpcFetch(requestsPerSecond, config.fetchFn),\n }\n const [primary, ...rest] = endpoints\n if (primary === undefined) throw new Error('rpcTransport needs at least one endpoint')\n if (!failover || rest.length === 0) return rpcHttp(primary, httpConfig)\n return fallback(\n endpoints.map((endpoint) => rpcHttp(endpoint, httpConfig)),\n { rank: false },\n )\n}\n\n/** anvil fork arguments for the primary endpoint (`--fork-header` only when it needs one). */\nexport function rpcForkArgs(endpoints: readonly RpcEndpoint[]): {\n forkUrl: string\n forkHeader?: string\n} {\n const [primary] = endpoints\n if (primary === undefined) throw new Error('rpcForkArgs needs at least one endpoint')\n const headers = Object.entries(primary.headers)\n if (headers.length === 0) return { forkUrl: primary.url }\n if (headers.length > 1) throw new Error('anvil --fork-header supports one header per fork')\n const [[name, value]] = headers\n return { forkUrl: primary.url, forkHeader: `${name}: ${value}` }\n}\n\n/**\n * Value for a Ponder chain's `rpc`. Header-free endpoints stay plain URLs so\n * Ponder keeps its own load balancing; credential headers need a transport.\n */\nexport function ponderRpc(endpoints: readonly RpcEndpoint[]): string | string[] | Transport {\n if (endpoints.some((endpoint) => Object.keys(endpoint.headers).length > 0)) {\n return rpcTransport(endpoints)\n }\n const urls = endpoints.map((endpoint) => endpoint.url)\n return urls.length === 1 ? urls[0] : urls\n}\n"],"mappings":"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"}
|