@panoptic-eng/sdk 1.0.67 → 1.0.69
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/{chainDeployments-CwnYHCg7.js → chainDeployments-BGvEeQSH.js} +24 -6
- package/dist/cow/index.d.ts.map +1 -1
- package/dist/cow/index.js +47 -2
- package/dist/cow/index.js.map +1 -1
- package/dist/{cow-CGgPXhY6.js → cow-BBPknr5W.js} +1 -1
- package/dist/deployments.d.ts +2 -0
- package/dist/deployments.d.ts.map +1 -1
- package/dist/deployments.js +24 -6
- package/dist/deployments.js.map +1 -1
- package/dist/{greeks-CGtgLUyh.js → greeks-DNPP24KL.js} +115 -9
- package/dist/index.d.ts +197 -46
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2359 -2180
- package/dist/index.js.map +1 -1
- package/dist/{irm-BDxwCFDm.js → irm-DurYJ0ht.js} +3 -3
- package/dist/panoptic/v2/greeks/index.d.ts +7 -4
- package/dist/panoptic/v2/greeks/index.d.ts.map +1 -1
- package/dist/panoptic/v2/greeks/index.js +74 -7
- package/dist/panoptic/v2/greeks/index.js.map +1 -1
- package/dist/panoptic/v2/index.d.ts +89 -5
- package/dist/panoptic/v2/index.d.ts.map +1 -1
- package/dist/panoptic/v2/index.js +699 -55
- package/dist/panoptic/v2/index.js.map +1 -1
- package/dist/panoptic/v2/react-public.d.ts +80 -6
- package/dist/panoptic/v2/react-public.d.ts.map +1 -1
- package/dist/panoptic/v2/react-public.js +2717 -2463
- package/dist/panoptic/v2/react-public.js.map +1 -1
- package/dist/{rates-BHS-Qiu7.js → rates-B-eRYOTS.js} +39 -3
- package/dist/{router-BW6TqwOO.js → router-ChMhfTqT.js} +969 -39
- package/dist/rpc/index.d.ts +3 -0
- package/dist/rpc/index.d.ts.map +1 -1
- package/dist/rpc/index.js +31 -3
- package/dist/rpc/index.js.map +1 -1
- package/dist/{transactionFees-B4jz-v7d.js → transactionFees-BGfyq3Jo.js} +1 -1
- package/dist/uniswap/index.js +53 -13
- package/dist/uniswap/index.js.map +1 -1
- package/dist/{v2-Dgh6JxG_.js → v2-Bo1vZXvR.js} +150 -10
- package/dist/vault-transaction-fees.js +24 -6
- package/dist/vault-transaction-fees.js.map +1 -1
- package/dist/{writes-CG612Vuk.js → writes-D53wWDT-.js} +2 -2
- package/package.json +1 -1
- package/dist/router-IDtCENST.js +0 -942
package/dist/rpc/index.d.ts
CHANGED
|
@@ -87,6 +87,8 @@ type RpcTransportOptions = RpcHttpConfig & {
|
|
|
87
87
|
* another surfaces as "already known" / "nonce too low" although it was sent.
|
|
88
88
|
*/
|
|
89
89
|
failover?: boolean;
|
|
90
|
+
/** Shared HTTP attempt limit, including retries and failover. Disables HTTP batching. */
|
|
91
|
+
requestsPerSecond?: number;
|
|
90
92
|
};
|
|
91
93
|
/**
|
|
92
94
|
* Transport over resolved endpoints: plain HTTP for one endpoint, otherwise an
|
|
@@ -94,6 +96,7 @@ type RpcTransportOptions = RpcHttpConfig & {
|
|
|
94
96
|
*/
|
|
95
97
|
declare function rpcTransport(endpoints: readonly RpcEndpoint[], {
|
|
96
98
|
failover,
|
|
99
|
+
requestsPerSecond,
|
|
97
100
|
...config
|
|
98
101
|
}?: RpcTransportOptions): Transport;
|
|
99
102
|
/** anvil fork arguments for the primary endpoint (`--fork-header` only when it needs one). */
|
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","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;IASEE,OAAAA,CAAAA,EAHIW,MAYjB,CAAA,MAAA,EAAA,MAAA,CAAA;EACWV,CAAAA,GAAAA,SAAAA;AACZ,CAAA;AACA,cAZcD,aAYiF,EAAA;EAAA,SAAA,CAAA,EAAA,aAAA;EAAA,SAApCS,GAAAA,EAAAA,iBAAAA;EAAe,SAAEX,KAAAA,EAAAA,aAAAA;EAAiB,SAAzCa,IAAAA,EAAAA,cAAAA;EAAM,SAAfC,EAAAA,EAAAA,aAAAA;EAAQ,SAAA,GAAA,EAAA,kBAAA;EAE3BN,SAAAA,IAAAA,EAAAA,mBAA0BL;EAC1BM,SAAAA,QAAAA,EAAAA,aAA4BN;;KALxCA,cAAAA,gBAA8BD;KAC9BS,eAAAA;cACSN,sBAAsBS,SAASD,OAAOF,iBAAiBX;iBAEpDQ,gBAAAA,UAA0BL;iBAC1BM,kBAAAA,UAA4BN;;;;;;;iBCxB5BO,gBAAAA;;;;KCJZE,MAAAA,GAASE,SAASD;KAClBS,WAAAA;;UAEAX;;;WAGCE;;KAEDG,0BAAAA;EFJAhB;EASEE,YAAAA,CAAAA,EAAAA,SASb,MAAA,EAAA;EACWC;EACAQ,gBAAAA,CAAAA,EAAe,SEZKA,eFYL,EAAA;AAC3B,CAAA;AAA+F,cEX1EM,qBFW0E,EAAA,SEX1CN,eFW0C,EAAA;;;;;AAA5C;AAEnD;AACA;;;;;iBEFwBO,mBAAAA,uBAA0CN,kBAAkBI,6BAA6BM;;;;KCzBrGC,aAAAA,GAAgBC,KAAKJ;;iBAETK,OAAAA,WAAkBH,sBAAsBC,gBAAqEJ,KAAAA,CAAtCS,cAAlBF,KAAAA,CAA+CC,SAAAA;KAChHE,mBAAAA,GAAsBN;;;;;AHAlC;EAScrB,QAAAA,CAAAA,EAAAA,OASb;
|
|
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;IASEE,OAAAA,CAAAA,EAHIW,MAYjB,CAAA,MAAA,EAAA,MAAA,CAAA;EACWV,CAAAA,GAAAA,SAAAA;AACZ,CAAA;AACA,cAZcD,aAYiF,EAAA;EAAA,SAAA,CAAA,EAAA,aAAA;EAAA,SAApCS,GAAAA,EAAAA,iBAAAA;EAAe,SAAEX,KAAAA,EAAAA,aAAAA;EAAiB,SAAzCa,IAAAA,EAAAA,cAAAA;EAAM,SAAfC,EAAAA,EAAAA,aAAAA;EAAQ,SAAA,GAAA,EAAA,kBAAA;EAE3BN,SAAAA,IAAAA,EAAAA,mBAA0BL;EAC1BM,SAAAA,QAAAA,EAAAA,aAA4BN;;KALxCA,cAAAA,gBAA8BD;KAC9BS,eAAAA;cACSN,sBAAsBS,SAASD,OAAOF,iBAAiBX;iBAEpDQ,gBAAAA,UAA0BL;iBAC1BM,kBAAAA,UAA4BN;;;;;;;iBCxB5BO,gBAAAA;;;;KCJZE,MAAAA,GAASE,SAASD;KAClBS,WAAAA;;UAEAX;;;WAGCE;;KAEDG,0BAAAA;EFJAhB;EASEE,YAAAA,CAAAA,EAAAA,SASb,MAAA,EAAA;EACWC;EACAQ,gBAAAA,CAAAA,EAAe,SEZKA,eFYL,EAAA;AAC3B,CAAA;AAA+F,cEX1EM,qBFW0E,EAAA,SEX1CN,eFW0C,EAAA;;;;;AAA5C;AAEnD;AACA;;;;;iBEFwBO,mBAAAA,uBAA0CN,kBAAkBI,6BAA6BM;;;;KCzBrGC,aAAAA,GAAgBC,KAAKJ;;iBAETK,OAAAA,WAAkBH,sBAAsBC,gBAAqEJ,KAAAA,CAAtCS,cAAlBF,KAAAA,CAA+CC,SAAAA;KAChHE,mBAAAA,GAAsBN;;;;;AHAlC;EAScrB,QAAAA,CAAAA,EAAAA,OASb;EACWC;EACAQ,iBAAAA,CAAe,EAAA,MAAA;AAC3B,CAAA;;;;;AAA2CG,iBGPnBgB,YAAAA,CHOmBhB,SAAAA,EAAAA,SGPcQ,WHOdR,EAAAA,EAAAA;EAAAA,QAAAA;EAAAA,iBAAAA;EAAAA,GAAAA;AAAAA,CAAAA,CAAAA,EGP0Ee,mBHO1Ef,CAAAA,EGPgGO,SHOhGP;AAAQ;AAE3BN,iBGPAyB,WAAAA,CHO0B9B,SAAAA,EAAc,SGPRmB,WHOQ,EAAA,CAAA,EAAA;EACxCb,OAAAA,EAAAA,MAAAA;;;;;;;iBGAAyB,SAAAA,qBAA8BZ,oCAAoCD"}
|
package/dist/rpc/index.js
CHANGED
|
@@ -195,6 +195,29 @@ function resolveRpcEndpoints(chainId, env, options = {}) {
|
|
|
195
195
|
].join(", ")}`);
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/rpc/rateLimit.ts
|
|
200
|
+
/** Limits HTTP attempts, including retries, across clients sharing this fetch function. */
|
|
201
|
+
function rateLimitedRpcFetch(requestsPerSecond, fetchFn = fetch) {
|
|
202
|
+
if (!Number.isFinite(requestsPerSecond) || requestsPerSecond <= 0) throw new Error("RPC requestsPerSecond must be positive and finite");
|
|
203
|
+
const intervalMs = Math.ceil(1e3 / requestsPerSecond);
|
|
204
|
+
let nextStart = 0;
|
|
205
|
+
let tail = Promise.resolve();
|
|
206
|
+
return (input, init) => {
|
|
207
|
+
const signal = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
208
|
+
const request = tail.then(async () => {
|
|
209
|
+
signal?.throwIfAborted();
|
|
210
|
+
const delay = nextStart - Date.now();
|
|
211
|
+
if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
|
|
212
|
+
signal?.throwIfAborted();
|
|
213
|
+
nextStart = Date.now() + intervalMs;
|
|
214
|
+
return fetchFn(input, init);
|
|
215
|
+
});
|
|
216
|
+
tail = request.then(() => void 0, () => void 0);
|
|
217
|
+
return request;
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
198
221
|
//#endregion
|
|
199
222
|
//#region src/rpc/transport.ts
|
|
200
223
|
/** viem HTTP transport for one endpoint, carrying its credential headers. */
|
|
@@ -208,11 +231,16 @@ function rpcHttp(endpoint, config = {}) {
|
|
|
208
231
|
* Transport over resolved endpoints: plain HTTP for one endpoint, otherwise an
|
|
209
232
|
* unranked viem `fallback` in configured order.
|
|
210
233
|
*/
|
|
211
|
-
function rpcTransport(endpoints, { failover = true,...config } = {}) {
|
|
234
|
+
function rpcTransport(endpoints, { failover = true, requestsPerSecond,...config } = {}) {
|
|
235
|
+
const httpConfig = requestsPerSecond === void 0 ? config : {
|
|
236
|
+
...config,
|
|
237
|
+
batch: false,
|
|
238
|
+
fetchFn: rateLimitedRpcFetch(requestsPerSecond, config.fetchFn)
|
|
239
|
+
};
|
|
212
240
|
const [primary, ...rest] = endpoints;
|
|
213
241
|
if (primary === void 0) throw new Error("rpcTransport needs at least one endpoint");
|
|
214
|
-
if (!failover || rest.length === 0) return rpcHttp(primary,
|
|
215
|
-
return fallback(endpoints.map((endpoint) => rpcHttp(endpoint,
|
|
242
|
+
if (!failover || rest.length === 0) return rpcHttp(primary, httpConfig);
|
|
243
|
+
return fallback(endpoints.map((endpoint) => rpcHttp(endpoint, httpConfig)), { rank: false });
|
|
216
244
|
}
|
|
217
245
|
/** anvil fork arguments for the primary endpoint (`--fork-header` only when it needs one). */
|
|
218
246
|
function rpcForkArgs(endpoints) {
|
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","endpoint: RpcEndpoint","config: RpcHttpConfig","endpoints: readonly RpcEndpoint[]"],"sources":["../../src/rpc/providers.ts","../../src/rpc/redact.ts","../../src/rpc/resolve.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, type Transport, fallback, http } from 'viem'\n\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}\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, ...config }: RpcTransportOptions = {},\n): Transport {\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, config)\n return fallback(\n endpoints.map((endpoint) => rpcHttp(endpoint, config)),\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}\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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"}
|
package/dist/uniswap/index.js
CHANGED
|
@@ -792,7 +792,7 @@ async function getUniswapV3LpPositionState(params) {
|
|
|
792
792
|
|
|
793
793
|
//#endregion
|
|
794
794
|
//#region src/uniswap/lpGreeks.ts
|
|
795
|
-
const Q96$
|
|
795
|
+
const Q96$5 = 1n << 96n;
|
|
796
796
|
const Q192$5 = 1n << 192n;
|
|
797
797
|
/**
|
|
798
798
|
* Compute the token0/token1 amounts backing `liquidity` over `[sqrtA, sqrtB]`
|
|
@@ -803,8 +803,8 @@ const Q192$5 = 1n << 192n;
|
|
|
803
803
|
function getAmountsForLiquidity(sqrtPriceX96, sqrtRatioAX96, sqrtRatioBX96, liquidity) {
|
|
804
804
|
const [sqrtA, sqrtB] = sqrtRatioAX96 <= sqrtRatioBX96 ? [sqrtRatioAX96, sqrtRatioBX96] : [sqrtRatioBX96, sqrtRatioAX96];
|
|
805
805
|
const sqrtC = sqrtPriceX96 < sqrtA ? sqrtA : sqrtPriceX96 > sqrtB ? sqrtB : sqrtPriceX96;
|
|
806
|
-
const amount0 = sqrtC < sqrtB ? liquidity * (sqrtB - sqrtC) * Q96$
|
|
807
|
-
const amount1 = sqrtC > sqrtA ? liquidity * (sqrtC - sqrtA) / Q96$
|
|
806
|
+
const amount0 = sqrtC < sqrtB ? liquidity * (sqrtB - sqrtC) * Q96$5 / (sqrtC * sqrtB) : 0n;
|
|
807
|
+
const amount1 = sqrtC > sqrtA ? liquidity * (sqrtC - sqrtA) / Q96$5 : 0n;
|
|
808
808
|
return {
|
|
809
809
|
amount0,
|
|
810
810
|
amount1
|
|
@@ -833,7 +833,7 @@ function getLpGreeks(input) {
|
|
|
833
833
|
if (assetIndex === 0) {
|
|
834
834
|
const value$1 = amount1 + amount0 * sqrtP2 / Q192$5;
|
|
835
835
|
const delta$1 = amount0;
|
|
836
|
-
const gamma$1 = inRange ? -(liquidity * sqrtP) / (2n * Q96$
|
|
836
|
+
const gamma$1 = inRange ? -(liquidity * sqrtP) / (2n * Q96$5) : 0n;
|
|
837
837
|
return {
|
|
838
838
|
value: value$1,
|
|
839
839
|
delta: delta$1,
|
|
@@ -842,7 +842,7 @@ function getLpGreeks(input) {
|
|
|
842
842
|
}
|
|
843
843
|
const value = amount0 + amount1 * Q192$5 / sqrtP2;
|
|
844
844
|
const delta = amount1;
|
|
845
|
-
const gamma = inRange ? -(liquidity * Q96$
|
|
845
|
+
const gamma = inRange ? -(liquidity * Q96$5) / (2n * sqrtP) : 0n;
|
|
846
846
|
return {
|
|
847
847
|
value,
|
|
848
848
|
delta,
|
|
@@ -1075,6 +1075,9 @@ var NotMarginCalledError = class extends PanopticError {
|
|
|
1075
1075
|
*/
|
|
1076
1076
|
var NotEnoughTokensError = class extends PanopticError {
|
|
1077
1077
|
name = "NotEnoughTokensError";
|
|
1078
|
+
get deficit() {
|
|
1079
|
+
return this.assetsRequested > this.assetBalance ? this.assetsRequested - this.assetBalance : 0n;
|
|
1080
|
+
}
|
|
1078
1081
|
constructor(tokenAddress, assetsRequested, assetBalance, cause) {
|
|
1079
1082
|
super(`Not enough tokens: requested=${assetsRequested}, balance=${assetBalance}, token=${tokenAddress}`, cause);
|
|
1080
1083
|
this.tokenAddress = tokenAddress;
|
|
@@ -4764,6 +4767,39 @@ const panopticErrorsAbi = [
|
|
|
4764
4767
|
}
|
|
4765
4768
|
]
|
|
4766
4769
|
},
|
|
4770
|
+
{
|
|
4771
|
+
type: "error",
|
|
4772
|
+
name: "NotEnoughTokens",
|
|
4773
|
+
inputs: [
|
|
4774
|
+
{
|
|
4775
|
+
name: "tokenAddress",
|
|
4776
|
+
type: "address"
|
|
4777
|
+
},
|
|
4778
|
+
{
|
|
4779
|
+
name: "account",
|
|
4780
|
+
type: "address"
|
|
4781
|
+
},
|
|
4782
|
+
{
|
|
4783
|
+
name: "assetsRequested",
|
|
4784
|
+
type: "uint256"
|
|
4785
|
+
},
|
|
4786
|
+
{
|
|
4787
|
+
name: "assetBalance",
|
|
4788
|
+
type: "uint256"
|
|
4789
|
+
}
|
|
4790
|
+
]
|
|
4791
|
+
},
|
|
4792
|
+
{
|
|
4793
|
+
type: "error",
|
|
4794
|
+
name: "ExecuteError",
|
|
4795
|
+
inputs: [{
|
|
4796
|
+
name: "callIndex",
|
|
4797
|
+
type: "uint256"
|
|
4798
|
+
}, {
|
|
4799
|
+
name: "revertData",
|
|
4800
|
+
type: "bytes"
|
|
4801
|
+
}]
|
|
4802
|
+
},
|
|
4767
4803
|
{
|
|
4768
4804
|
type: "error",
|
|
4769
4805
|
name: "NotGuardian",
|
|
@@ -4905,7 +4941,7 @@ const errorConstructors = {
|
|
|
4905
4941
|
AccountInsolvent: (args, cause) => new AccountInsolventError(args[0], args[1], cause),
|
|
4906
4942
|
NotMarginCalled: (_args, cause) => new NotMarginCalledError(cause),
|
|
4907
4943
|
CreateFail: (_args, cause) => new CreateFailError(cause),
|
|
4908
|
-
NotEnoughTokens: (args, cause) => new NotEnoughTokensError(args[0], args[1], args[2], cause),
|
|
4944
|
+
NotEnoughTokens: (args, cause) => new NotEnoughTokensError(args[0], args[args.length === 4 ? 2 : 1], args[args.length === 4 ? 3 : 2], cause),
|
|
4909
4945
|
NotEnoughLiquidityInChunk: (_args, cause) => new NotEnoughLiquidityInChunkError(cause),
|
|
4910
4946
|
InsufficientCreditLiquidity: (_args, cause) => new InsufficientCreditLiquidityError(cause),
|
|
4911
4947
|
DepositTooLarge: (_args, cause) => new DepositTooLargeError(cause),
|
|
@@ -5295,7 +5331,7 @@ const MAX_UINT256 = (1n << 256n) - 1n;
|
|
|
5295
5331
|
|
|
5296
5332
|
//#endregion
|
|
5297
5333
|
//#region src/uniswap/lpDeposit.ts
|
|
5298
|
-
const Q96$
|
|
5334
|
+
const Q96$4 = 1n << 96n;
|
|
5299
5335
|
const ceilDiv = (n, d) => (n + d - 1n) / d;
|
|
5300
5336
|
/** Uniswap mint principal in raw token units, rounded up per leg, plus 5% headroom. */
|
|
5301
5337
|
function getLpDepositAmounts(ranges, sqrtPriceX96) {
|
|
@@ -5311,8 +5347,8 @@ function getLpDepositBreakdown(ranges, sqrtPriceX96) {
|
|
|
5311
5347
|
const lower = tickToSqrtPriceX96(BigInt(tickLower));
|
|
5312
5348
|
const upper = tickToSqrtPriceX96(BigInt(tickUpper));
|
|
5313
5349
|
const price = sqrtPriceX96 < lower ? lower : sqrtPriceX96 > upper ? upper : sqrtPriceX96;
|
|
5314
|
-
amount0 += ceilDiv(liquidity * Q96$
|
|
5315
|
-
amount1 += ceilDiv(liquidity * (price - lower), Q96$
|
|
5350
|
+
amount0 += ceilDiv(liquidity * Q96$4 * (upper - price), upper * price);
|
|
5351
|
+
amount1 += ceilDiv(liquidity * (price - lower), Q96$4);
|
|
5316
5352
|
}
|
|
5317
5353
|
const buffer = {
|
|
5318
5354
|
amount0: ceilDiv(amount0 * 5n, 100n),
|
|
@@ -5340,7 +5376,7 @@ function getUnhedgedLpRanges({ tokenId, positionSize, tickSpacing }) {
|
|
|
5340
5376
|
const lower = tickToSqrtPriceX96(tickLower);
|
|
5341
5377
|
const upper = tickToSqrtPriceX96(tickUpper);
|
|
5342
5378
|
const amount = positionSize * leg.optionRatio;
|
|
5343
|
-
const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96$
|
|
5379
|
+
const liquidity = leg.asset === 0n ? amount * (lower * upper / Q96$4) / (upper - lower) : amount * Q96$4 / (upper - lower);
|
|
5344
5380
|
return liquidity <= 0n ? [] : [{
|
|
5345
5381
|
tickLower: Number(tickLower),
|
|
5346
5382
|
tickUpper: Number(tickUpper),
|
|
@@ -5361,7 +5397,7 @@ function getLpPositionFunding(params) {
|
|
|
5361
5397
|
});
|
|
5362
5398
|
const breakdown = getLpDepositBreakdown(ranges, sqrtPriceX96);
|
|
5363
5399
|
const priceSquared = valuationSqrtPriceX96 * valuationSqrtPriceX96;
|
|
5364
|
-
const value = ({ amount0, amount1 }) => quoteTokenIndex === 0 ? amount0 + ceilDiv(amount1 * Q96$
|
|
5400
|
+
const value = ({ amount0, amount1 }) => quoteTokenIndex === 0 ? amount0 + ceilDiv(amount1 * Q96$4 * Q96$4, priceSquared) : amount1 + ceilDiv(amount0 * priceSquared, Q96$4 * Q96$4);
|
|
5365
5401
|
const principalInQuote = value(breakdown.principal);
|
|
5366
5402
|
const totalInQuote = value(breakdown.total);
|
|
5367
5403
|
return {
|
|
@@ -5391,8 +5427,8 @@ function getLpFundingDeposit({ funding, availableInQuote, minimumInQuote = 0n, q
|
|
|
5391
5427
|
requiredInQuote,
|
|
5392
5428
|
shortfallInQuote,
|
|
5393
5429
|
defaultQuotePercent,
|
|
5394
|
-
amount0: quoteTokenIndex === 0 ? quoteAmount : ceilDiv(assetValue * Q96$
|
|
5395
|
-
amount1: quoteTokenIndex === 1 ? quoteAmount : ceilDiv(assetValue * priceSquared, Q96$
|
|
5430
|
+
amount0: quoteTokenIndex === 0 ? quoteAmount : ceilDiv(assetValue * Q96$4 * Q96$4, priceSquared),
|
|
5431
|
+
amount1: quoteTokenIndex === 1 ? quoteAmount : ceilDiv(assetValue * priceSquared, Q96$4 * Q96$4)
|
|
5396
5432
|
};
|
|
5397
5433
|
}
|
|
5398
5434
|
/** Largest raw size funded by available collateral, including native-token rounding. */
|
|
@@ -5595,6 +5631,10 @@ function summarizeLpPositionHistory(events) {
|
|
|
5595
5631
|
};
|
|
5596
5632
|
}
|
|
5597
5633
|
|
|
5634
|
+
//#endregion
|
|
5635
|
+
//#region src/panoptic/v2/greeks/legLiquidity.ts
|
|
5636
|
+
const Q96$3 = 1n << 96n;
|
|
5637
|
+
|
|
5598
5638
|
//#endregion
|
|
5599
5639
|
//#region src/panoptic/v2/greeks/positionVolatility.ts
|
|
5600
5640
|
const Precision$1 = Decimal.clone({ precision: 80 });
|