@panoptic-eng/sdk 1.0.62 → 1.0.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/cow/index.d.ts +1 -1
  3. package/dist/cow/index.d.ts.map +1 -1
  4. package/dist/cow/index.js +1 -1
  5. package/dist/cow/index.js.map +1 -1
  6. package/dist/{cow-DTi3GjQz.js → cow-BIzmQHon.js} +1 -1
  7. package/dist/index.d.ts +4 -3
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/{irm-BDlcUNgJ.js → irm-BGog_tSR.js} +3 -3
  12. package/dist/panoptic/v2/index.d.ts +137 -135
  13. package/dist/panoptic/v2/index.d.ts.map +1 -1
  14. package/dist/panoptic/v2/index.js +52 -51
  15. package/dist/panoptic/v2/index.js.map +1 -1
  16. package/dist/panoptic/v2/react-public.d.ts +144 -142
  17. package/dist/panoptic/v2/react-public.d.ts.map +1 -1
  18. package/dist/panoptic/v2/react-public.js +55 -54
  19. package/dist/panoptic/v2/react-public.js.map +1 -1
  20. package/dist/providers-1WdiaRbY.js +54 -0
  21. package/dist/{rates-BwZnK0tG.js → rates-O6Sn-xqL.js} +3 -3
  22. package/dist/{router-Y1OxL9Nt.js → router-BuAvFpbu.js} +137 -10
  23. package/dist/{router-jMP7fVno.js → router-DHn0rNd7.js} +2 -2
  24. package/dist/rpc/index.d.ts +112 -0
  25. package/dist/rpc/index.d.ts.map +1 -0
  26. package/dist/rpc/index.js +242 -0
  27. package/dist/rpc/index.js.map +1 -0
  28. package/dist/test/index.d.ts +1 -1
  29. package/dist/test/index.d.ts.map +1 -1
  30. package/dist/test/index.js +1 -14
  31. package/dist/test/index.js.map +1 -1
  32. package/dist/uniswap/index.d.ts +311 -216
  33. package/dist/uniswap/index.d.ts.map +1 -1
  34. package/dist/uniswap/index.js +254 -21
  35. package/dist/uniswap/index.js.map +1 -1
  36. package/dist/{v2-B27ILZl4.js → v2-D2Bg1SeN.js} +19 -144
  37. package/dist/{writes-B8NGXzUG.js → writes-jz-N6C_4.js} +37 -37
  38. package/dist/zodiac/index.d.ts +3 -3
  39. package/dist/zodiac/index.d.ts.map +1 -1
  40. package/dist/zodiac/index.js +3 -3
  41. package/dist/zodiac/index.js.map +1 -1
  42. package/package.json +5 -1
@@ -0,0 +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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"}
@@ -105,7 +105,7 @@ type AnvilArgs = {
105
105
  *
106
106
  * Requires `forkUrl` to be set.
107
107
  */
108
- forkHeader?: Record<string, string> | undefined;
108
+ forkHeader?: string | undefined;
109
109
  /**
110
110
  * Initial retry backoff on encountering errors.
111
111
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["spawnAnvil","AnvilArgs","Promise","killAnvilProcess","killAllAnvilProcesses","Record","ReactNode","Config","ReactTestWrapper","children","wagmiConfig","react_jsx_runtime0","JSX","Element","Address","alice","bob","charlie"],"sources":["../../src/test/test-utils.d.ts","../../src/test/react-test-utils.d.ts","../../src/test/test-accounts.d.ts"],"sourcesContent":null,"mappings":";;;;;;cAAqBA,oBAAoBC,cAAcC;cAClCC,oCAAoCD;cACpCE,6BAA6BF;KAC7CD,SAAAA;;;AAHL;;;EAAkD,QAAKC,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA;EAAO;AAC9D;AACA;AAAgE;;;;ACAhE;;EAG6C,eAHHO,CAAAA,EAAAA,OAAAA,GAAAA,SAAAA;EAAQ;;;;AAGL;;;;ACJ7C;EACqBO,kBAAKF,CAAAA,EAAAA,MAAO,GAAA,MAAA,GAAA,SAAA;EACZG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eFkGJZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCnGIG;;;;aACNF;eACEC;MACiBI,kBAAAA,CAAAC,GAAAA,CAAIC;;;;cCJjBE,OAAOD;cACPE,KAAKF;cACLG,SAASH"}
1
+ {"version":3,"file":"index.d.ts","names":["spawnAnvil","AnvilArgs","Promise","killAnvilProcess","killAllAnvilProcesses","ReactNode","Config","ReactTestWrapper","children","wagmiConfig","react_jsx_runtime0","JSX","Element","Address","alice","bob","charlie"],"sources":["../../src/test/test-utils.d.ts","../../src/test/react-test-utils.d.ts","../../src/test/test-accounts.d.ts"],"sourcesContent":null,"mappings":";;;;;;cAAqBA,oBAAoBC,cAAcC;cAClCC,oCAAoCD;cACpCE,6BAA6BF;KAC7CD,SAAAA;;;AAHL;;;EAAkD,QAAKC,CAAAA,EAAAA,MAAAA,GAAAA,SAAAA;EAAO;AAC9D;AACA;AAAgE;;;;ACAhE;;EAG6C,eAHHM,CAAAA,EAAAA,OAAAA,GAAAA,SAAAA;EAAQ;;;;AAGL;;;;ACJ7C;EACqBO,kBAAKF,CAAAA,EAAAA,MAAO,GAAA,MAAA,GAAA,SAAA;EACZG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cDDAT;;;;aACNF;eACEC;MACiBI,kBAAAA,CAAAC,GAAAA,CAAIC;;;;cCJjBE,OAAOD;cACPE,KAAKF;cACLG,SAASH"}
@@ -41,20 +41,7 @@ function toFlagCase(str, separator = "-") {
41
41
  }
42
42
  const spawnAnvil = (args) => {
43
43
  return new Promise((resolve, reject) => {
44
- const subprocess = spawn(
45
- "anvil",
46
- toArgs({ ...args })
47
- // [
48
- // `--fork-url`,
49
- // `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,
50
- // `--chain-id`,
51
- // `31337`,
52
- // `-vvvvv`,
53
- // `--no-cors`,
54
- // `--fork-block-number`,
55
- // `23146780`,
56
- // ]
57
- );
44
+ const subprocess = spawn("anvil", toArgs({ ...args }));
58
45
  subprocess.stdout.on("data", (data) => {
59
46
  process.stdout.write(data);
60
47
  if (data.toString().includes("Listening on")) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["obj: {\n [key: string]:\n | Record<string, any>\n | string\n | readonly string[]\n | boolean\n | number\n | bigint\n | undefined\n }","options: { casing: 'kebab' | 'snake' }","flag","str: string","args?: AnvilArgs","port: number","alice: Address","bob: Address","charlie: Address"],"sources":["../../src/test/test-utils.ts","../../src/test/react-test-utils.tsx","../../src/test/test-accounts.ts"],"sourcesContent":["/* eslint-disable no-console -- the console message are necessary to provide human-readable output to test runners */\nimport { exec, execSync, spawn } from 'node:child_process'\n\n/**\n * Converts an object of options to an array of command line arguments.\n *\n * @param options The options object.\n * @returns The command line arguments.\n */\nfunction toArgs(\n obj: {\n [key: string]:\n | Record<string, any>\n | string\n | readonly string[]\n | boolean\n | number\n | bigint\n | undefined\n },\n options: { casing: 'kebab' | 'snake' } = { casing: 'kebab' },\n) {\n const { casing } = options\n return Object.entries(obj).flatMap(([key, value]) => {\n if (value === undefined) return []\n\n if (Array.isArray(value)) return [toFlagCase(key), value.join(',')]\n\n if (typeof value === 'object' && value !== null) {\n return Object.entries(value).flatMap(([subKey, subValue]) => {\n if (subValue === undefined) return []\n const flag = toFlagCase(`${key}.${subKey}`, casing === 'kebab' ? '-' : '_')\n return [flag, Array.isArray(subValue) ? subValue.join(',') : subValue]\n })\n }\n\n const flag = toFlagCase(key, casing === 'kebab' ? '-' : '_')\n\n if (value === false) return [flag, 'false']\n if (value === true) return [flag]\n\n const stringified = value.toString()\n if (stringified === '') return [flag]\n\n return [flag, stringified]\n })\n}\n\n/** Converts to a --flag-case string. */\nfunction toFlagCase(str: string, separator = '-') {\n const keys = []\n for (let i = 0; i < str.split('.').length; i++) {\n const key = str.split('.')[i]\n if (!key) continue\n keys.push(\n key\n .replace(/\\s+/g, separator)\n .replace(/([a-z])([A-Z])/g, `$1${separator}$2`)\n .toLowerCase(),\n )\n }\n return `--${keys.join('.')}`\n}\n\n// Relevant prior work:\n// https://github.com/wevm/prool/blob/7016a5be99937715da8356e4cade6de03a8496e0/src/instances/anvil.ts#L5\n// https://github.com/morpho-org/sdks/blob/main/packages/test/src/anvil.ts\nexport const spawnAnvil = (args?: AnvilArgs) => {\n return new Promise<void>((resolve, reject) => {\n const subprocess = spawn(\n 'anvil',\n toArgs({\n // Use newly generated mnemonic to avoid drainers deployed on mainnet and delegated to by default anvil accounts (https://getfoundry.sh/anvil/overview/#eip-7702-and-default-accounts)\n ...args,\n }),\n // [\n // `--fork-url`,\n // `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,\n // `--chain-id`,\n // `31337`,\n // `-vvvvv`,\n // `--no-cors`,\n // `--fork-block-number`,\n // `23146780`,\n // ]\n )\n\n subprocess.stdout.on('data', (data) => {\n process.stdout.write(data)\n if (data.toString().includes('Listening on')) {\n process.stdout.write(data)\n console.log(data.toString())\n resolve()\n }\n })\n\n subprocess.stderr.on('data', (data) => {\n process.stderr.write(data)\n })\n\n subprocess.on('exit', (code) => {\n if (code !== 0) {\n console.error(`Child process exited with code ${code}`)\n reject(new Error(`Anvil process exited with code ${code}`))\n }\n })\n\n subprocess.on('error', (err) => {\n console.error('Failed to start child process:', err)\n reject(err)\n })\n })\n}\n\nexport const killAnvilProcess = async (port: number) => {\n try {\n const data = execSync(`lsof -iTCP:${port} -sTCP:LISTEN -t`)\n\n const pids = data.toString().split('\\n').slice(0, -1)\n\n console.debug(`Clearing ports: ${pids.join(', ')}`)\n\n for (const pid of pids) {\n exec(`kill -9 ${pid}`, (error) => {\n if (error) console.error(`Error while killing ${pid}: ${error}`)\n })\n }\n } catch (e) {\n console.error('Cleanup error: ', (e as any).toString())\n }\n}\n\nexport const killAllAnvilProcesses = async () => {\n try {\n const data = execSync('lsof -c anvil -t')\n\n const pids = data.toString().split('\\n').slice(0, -1)\n\n console.debug(`Clearing ports: ${pids.join(', ')}`)\n\n for (const pid of pids) {\n exec(`kill -9 ${pid}`, (error) => {\n if (error) console.error(`Error while killing ${pid}: ${error}`)\n })\n }\n } catch (e) {\n console.error('Cleanup error: ', (e as any).toString())\n }\n}\n\ntype AnvilArgs = {\n /**\n * Number of dev accounts to generate and configure.\n *\n * @defaultValue 10\n */\n accounts?: number | undefined\n /**\n * Set the Access-Control-Allow-Origin response header (CORS).\n *\n * @defaultValue *\n */\n allowOrigin?: string | undefined\n /**\n * Enable autoImpersonate on startup\n */\n autoImpersonate?: boolean | undefined\n /**\n * The balance of every dev account in Ether.\n *\n * @defaultValue 10000\n */\n balance?: number | bigint | undefined\n /**\n * The base fee in a block.\n */\n blockBaseFeePerGas?: number | bigint | undefined\n /**\n * Block time in seconds for interval mining.\n */\n blockTime?: number | undefined\n /**\n * Path or alias to the Anvil binary.\n */\n binary?: string | undefined\n /**\n * The chain id.\n */\n chainId?: number | undefined\n /**\n * EIP-170: Contract code size limit in bytes. Useful to increase this because of tests.\n *\n * @defaultValue 0x6000 (~25kb)\n */\n codeSizeLimit?: number | undefined\n /**\n * Sets the number of assumed available compute units per second for this fork provider.\n *\n * @defaultValue 350\n * @see https://github.com/alchemyplatform/alchemy-docs/blob/master/documentation/compute-units.md#rate-limits-cups\n */\n computeUnitsPerSecond?: number | undefined\n /**\n * Writes output of `anvil` as json to user-specified file.\n */\n configOut?: string | undefined\n /**\n * Sets the derivation path of the child key to be derived.\n *\n * @defaultValue m/44'/60'/0'/0/\n */\n derivationPath?: string | undefined\n /**\n * Disable the `call.gas_limit <= block.gas_limit` constraint.\n */\n disableBlockGasLimit?: boolean | undefined\n /**\n * Dump the state of chain on exit to the given file. If the value is a directory, the state will be\n * written to `<VALUE>/state.json`.\n */\n dumpState?: string | undefined\n /**\n * Fetch state over a remote endpoint instead of starting from an empty state.\n *\n * If you want to fetch state from a specific block number, add a block number like `http://localhost:8545@1400000`\n * or use the `forkBlockNumber` option.\n */\n forkUrl?: string | undefined\n /**\n * Fetch state from a specific block number over a remote endpoint.\n *\n * Requires `forkUrl` to be set.\n */\n forkBlockNumber?: number | bigint | undefined\n /**\n * Specify chain id to skip fetching it from remote endpoint. This enables offline-start mode.\n *\n * You still must pass both `forkUrl` and `forkBlockNumber`, and already have your required state cached\n * on disk, anything missing locally would be fetched from the remote.\n */\n forkChainId?: number | undefined\n /**\n * Specify headers to send along with any request to the remote JSON-RPC server in forking mode.\n *\n * e.g. \"User-Agent: test-agent\"\n *\n * Requires `forkUrl` to be set.\n */\n forkHeader?: Record<string, string> | undefined\n /**\n * Initial retry backoff on encountering errors.\n */\n forkRetryBackoff?: number | undefined\n /**\n * The block gas limit.\n */\n gasLimit?: number | bigint | undefined\n /**\n * The gas price.\n */\n gasPrice?: number | bigint | undefined\n /**\n * The EVM hardfork to use.\n */\n hardfork?:\n | 'Frontier'\n | 'Homestead'\n | 'Dao'\n | 'Tangerine'\n | 'SpuriousDragon'\n | 'Byzantium'\n | 'Constantinople'\n | 'Petersburg'\n | 'Istanbul'\n | 'Muirglacier'\n | 'Berlin'\n | 'London'\n | 'ArrowGlacier'\n | 'GrayGlacier'\n | 'Paris'\n | 'Shanghai'\n | 'Cancun'\n | 'Prague'\n | 'Latest'\n | undefined\n /**\n * The host the server will listen on.\n */\n host?: string | undefined\n /**\n * Initialize the genesis block with the given `genesis.json` file.\n */\n init?: string | undefined\n /**\n * Launch an ipc server at the given path or default path = `/tmp/anvil.ipc`.\n */\n ipc?: string | undefined\n /**\n * Initialize the chain from a previously saved state snapshot.\n */\n loadState?: string | undefined\n /**\n * BIP39 mnemonic phrase used for generating accounts.\n */\n mnemonic?: string | undefined\n /**\n * Automatically generates a BIP39 mnemonic phrase, and derives accounts from it.\n */\n mnemonicRandom?: boolean | undefined\n /**\n * Disable CORS.\n */\n noCors?: boolean | undefined\n /**\n * Disable auto and interval mining, and mine on demand instead.\n */\n noMining?: boolean | undefined\n /**\n * Disables rate limiting for this node's provider.\n *\n * @defaultValue false\n * @see https://github.com/alchemyplatform/alchemy-docs/blob/master/documentation/compute-units.md#rate-limits-cups\n */\n noRateLimit?: boolean | undefined\n /**\n * Explicitly disables the use of RPC caching.\n *\n * All storage slots are read entirely from the endpoint.\n */\n noStorageCaching?: boolean | undefined\n /**\n * How transactions are sorted in the mempool.\n *\n * @defaultValue fees\n */\n order?: string | undefined\n /**\n * Run an Optimism chain.\n */\n optimism?: boolean | undefined\n /**\n * Port number to listen on.\n *\n * @defaultValue 8545\n */\n port?: number | undefined\n /**\n * Don't keep full chain history. If a number argument is specified, at most this number of states is kept in memory.\n */\n pruneHistory?: number | undefined | boolean\n /**\n * Number of retry requests for spurious networks (timed out requests).\n *\n * @defaultValue 5\n */\n retries?: number | undefined\n /**\n * Don't print anything on startup and don't print logs.\n */\n silent?: boolean | undefined\n /**\n * Slots in an epoch.\n */\n slotsInAnEpoch?: number | undefined\n /**\n * Enable steps tracing used for debug calls returning geth-style traces.\n */\n stepsTracing?: boolean | undefined\n /**\n * Interval in seconds at which the status is to be dumped to disk.\n */\n stateInterval?: number | undefined\n /**\n * This is an alias for both `loadState` and `dumpState`. It initializes the chain with the state stored at the\n * file, if it exists, and dumps the chain's state on exit\n */\n state?: string | undefined\n /**\n * Timeout in ms for requests sent to remote JSON-RPC server in forking mode.\n *\n * @defaultValue 45000\n */\n timeout?: number | undefined\n /**\n * The timestamp of the genesis block.\n */\n timestamp?: number | bigint | undefined\n /**\n * Number of blocks with transactions to keep in memory.\n */\n transactionBlockKeeper?: number | undefined\n}\n","import { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { type ReactNode, useEffect } from 'react'\nimport { type Config, useConnect, WagmiProvider } from 'wagmi'\n\nconst Connect = () => {\n const { connectors, connect } = useConnect()\n\n useEffect(() => {\n if (connectors[0] === undefined) {\n return undefined\n }\n\n connect({ connector: connectors[0] })\n }, [connect, connectors])\n\n return <></>\n}\n\nexport const ReactTestWrapper = ({\n children,\n wagmiConfig,\n}: {\n children?: ReactNode\n wagmiConfig: Config\n}) => {\n const testQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n },\n mutations: {\n retry: false,\n },\n },\n })\n\n return (\n <WagmiProvider config={wagmiConfig}>\n <QueryClientProvider client={testQueryClient}>\n <>\n <Connect />\n {children}\n </>\n </QueryClientProvider>\n </WagmiProvider>\n )\n}\n","import type { Address } from 'viem'\n\n// Test accounts for impersonation\nexport const alice: Address = '0x0000000000000000000000000000000000001234'\nexport const bob: Address = '0x0000000000000000000000000000000000002345'\nexport const charlie: Address = '0x0000000000000000000000000000000000003456'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["obj: {\n [key: string]:\n | Record<string, any>\n | string\n | readonly string[]\n | boolean\n | number\n | bigint\n | undefined\n }","options: { casing: 'kebab' | 'snake' }","flag","str: string","args?: AnvilArgs","port: number","alice: Address","bob: Address","charlie: Address"],"sources":["../../src/test/test-utils.ts","../../src/test/react-test-utils.tsx","../../src/test/test-accounts.ts"],"sourcesContent":["/* eslint-disable no-console -- the console message are necessary to provide human-readable output to test runners */\nimport { exec, execSync, spawn } from 'node:child_process'\n\n/**\n * Converts an object of options to an array of command line arguments.\n *\n * @param options The options object.\n * @returns The command line arguments.\n */\nfunction toArgs(\n obj: {\n [key: string]:\n | Record<string, any>\n | string\n | readonly string[]\n | boolean\n | number\n | bigint\n | undefined\n },\n options: { casing: 'kebab' | 'snake' } = { casing: 'kebab' },\n) {\n const { casing } = options\n return Object.entries(obj).flatMap(([key, value]) => {\n if (value === undefined) return []\n\n if (Array.isArray(value)) return [toFlagCase(key), value.join(',')]\n\n if (typeof value === 'object' && value !== null) {\n return Object.entries(value).flatMap(([subKey, subValue]) => {\n if (subValue === undefined) return []\n const flag = toFlagCase(`${key}.${subKey}`, casing === 'kebab' ? '-' : '_')\n return [flag, Array.isArray(subValue) ? subValue.join(',') : subValue]\n })\n }\n\n const flag = toFlagCase(key, casing === 'kebab' ? '-' : '_')\n\n if (value === false) return [flag, 'false']\n if (value === true) return [flag]\n\n const stringified = value.toString()\n if (stringified === '') return [flag]\n\n return [flag, stringified]\n })\n}\n\n/** Converts to a --flag-case string. */\nfunction toFlagCase(str: string, separator = '-') {\n const keys = []\n for (let i = 0; i < str.split('.').length; i++) {\n const key = str.split('.')[i]\n if (!key) continue\n keys.push(\n key\n .replace(/\\s+/g, separator)\n .replace(/([a-z])([A-Z])/g, `$1${separator}$2`)\n .toLowerCase(),\n )\n }\n return `--${keys.join('.')}`\n}\n\n// Relevant prior work:\n// https://github.com/wevm/prool/blob/7016a5be99937715da8356e4cade6de03a8496e0/src/instances/anvil.ts#L5\n// https://github.com/morpho-org/sdks/blob/main/packages/test/src/anvil.ts\nexport const spawnAnvil = (args?: AnvilArgs) => {\n return new Promise<void>((resolve, reject) => {\n const subprocess = spawn(\n 'anvil',\n toArgs({\n // Use newly generated mnemonic to avoid drainers deployed on mainnet and delegated to by default anvil accounts (https://getfoundry.sh/anvil/overview/#eip-7702-and-default-accounts)\n ...args,\n }),\n )\n\n subprocess.stdout.on('data', (data) => {\n process.stdout.write(data)\n if (data.toString().includes('Listening on')) {\n process.stdout.write(data)\n console.log(data.toString())\n resolve()\n }\n })\n\n subprocess.stderr.on('data', (data) => {\n process.stderr.write(data)\n })\n\n subprocess.on('exit', (code) => {\n if (code !== 0) {\n console.error(`Child process exited with code ${code}`)\n reject(new Error(`Anvil process exited with code ${code}`))\n }\n })\n\n subprocess.on('error', (err) => {\n console.error('Failed to start child process:', err)\n reject(err)\n })\n })\n}\n\nexport const killAnvilProcess = async (port: number) => {\n try {\n const data = execSync(`lsof -iTCP:${port} -sTCP:LISTEN -t`)\n\n const pids = data.toString().split('\\n').slice(0, -1)\n\n console.debug(`Clearing ports: ${pids.join(', ')}`)\n\n for (const pid of pids) {\n exec(`kill -9 ${pid}`, (error) => {\n if (error) console.error(`Error while killing ${pid}: ${error}`)\n })\n }\n } catch (e) {\n console.error('Cleanup error: ', (e as any).toString())\n }\n}\n\nexport const killAllAnvilProcesses = async () => {\n try {\n const data = execSync('lsof -c anvil -t')\n\n const pids = data.toString().split('\\n').slice(0, -1)\n\n console.debug(`Clearing ports: ${pids.join(', ')}`)\n\n for (const pid of pids) {\n exec(`kill -9 ${pid}`, (error) => {\n if (error) console.error(`Error while killing ${pid}: ${error}`)\n })\n }\n } catch (e) {\n console.error('Cleanup error: ', (e as any).toString())\n }\n}\n\ntype AnvilArgs = {\n /**\n * Number of dev accounts to generate and configure.\n *\n * @defaultValue 10\n */\n accounts?: number | undefined\n /**\n * Set the Access-Control-Allow-Origin response header (CORS).\n *\n * @defaultValue *\n */\n allowOrigin?: string | undefined\n /**\n * Enable autoImpersonate on startup\n */\n autoImpersonate?: boolean | undefined\n /**\n * The balance of every dev account in Ether.\n *\n * @defaultValue 10000\n */\n balance?: number | bigint | undefined\n /**\n * The base fee in a block.\n */\n blockBaseFeePerGas?: number | bigint | undefined\n /**\n * Block time in seconds for interval mining.\n */\n blockTime?: number | undefined\n /**\n * Path or alias to the Anvil binary.\n */\n binary?: string | undefined\n /**\n * The chain id.\n */\n chainId?: number | undefined\n /**\n * EIP-170: Contract code size limit in bytes. Useful to increase this because of tests.\n *\n * @defaultValue 0x6000 (~25kb)\n */\n codeSizeLimit?: number | undefined\n /**\n * Sets the number of assumed available compute units per second for this fork provider.\n *\n * @defaultValue 350\n * @see https://github.com/alchemyplatform/alchemy-docs/blob/master/documentation/compute-units.md#rate-limits-cups\n */\n computeUnitsPerSecond?: number | undefined\n /**\n * Writes output of `anvil` as json to user-specified file.\n */\n configOut?: string | undefined\n /**\n * Sets the derivation path of the child key to be derived.\n *\n * @defaultValue m/44'/60'/0'/0/\n */\n derivationPath?: string | undefined\n /**\n * Disable the `call.gas_limit <= block.gas_limit` constraint.\n */\n disableBlockGasLimit?: boolean | undefined\n /**\n * Dump the state of chain on exit to the given file. If the value is a directory, the state will be\n * written to `<VALUE>/state.json`.\n */\n dumpState?: string | undefined\n /**\n * Fetch state over a remote endpoint instead of starting from an empty state.\n *\n * If you want to fetch state from a specific block number, add a block number like `http://localhost:8545@1400000`\n * or use the `forkBlockNumber` option.\n */\n forkUrl?: string | undefined\n /**\n * Fetch state from a specific block number over a remote endpoint.\n *\n * Requires `forkUrl` to be set.\n */\n forkBlockNumber?: number | bigint | undefined\n /**\n * Specify chain id to skip fetching it from remote endpoint. This enables offline-start mode.\n *\n * You still must pass both `forkUrl` and `forkBlockNumber`, and already have your required state cached\n * on disk, anything missing locally would be fetched from the remote.\n */\n forkChainId?: number | undefined\n /**\n * Specify headers to send along with any request to the remote JSON-RPC server in forking mode.\n *\n * e.g. \"User-Agent: test-agent\"\n *\n * Requires `forkUrl` to be set.\n */\n forkHeader?: string | undefined\n /**\n * Initial retry backoff on encountering errors.\n */\n forkRetryBackoff?: number | undefined\n /**\n * The block gas limit.\n */\n gasLimit?: number | bigint | undefined\n /**\n * The gas price.\n */\n gasPrice?: number | bigint | undefined\n /**\n * The EVM hardfork to use.\n */\n hardfork?:\n | 'Frontier'\n | 'Homestead'\n | 'Dao'\n | 'Tangerine'\n | 'SpuriousDragon'\n | 'Byzantium'\n | 'Constantinople'\n | 'Petersburg'\n | 'Istanbul'\n | 'Muirglacier'\n | 'Berlin'\n | 'London'\n | 'ArrowGlacier'\n | 'GrayGlacier'\n | 'Paris'\n | 'Shanghai'\n | 'Cancun'\n | 'Prague'\n | 'Latest'\n | undefined\n /**\n * The host the server will listen on.\n */\n host?: string | undefined\n /**\n * Initialize the genesis block with the given `genesis.json` file.\n */\n init?: string | undefined\n /**\n * Launch an ipc server at the given path or default path = `/tmp/anvil.ipc`.\n */\n ipc?: string | undefined\n /**\n * Initialize the chain from a previously saved state snapshot.\n */\n loadState?: string | undefined\n /**\n * BIP39 mnemonic phrase used for generating accounts.\n */\n mnemonic?: string | undefined\n /**\n * Automatically generates a BIP39 mnemonic phrase, and derives accounts from it.\n */\n mnemonicRandom?: boolean | undefined\n /**\n * Disable CORS.\n */\n noCors?: boolean | undefined\n /**\n * Disable auto and interval mining, and mine on demand instead.\n */\n noMining?: boolean | undefined\n /**\n * Disables rate limiting for this node's provider.\n *\n * @defaultValue false\n * @see https://github.com/alchemyplatform/alchemy-docs/blob/master/documentation/compute-units.md#rate-limits-cups\n */\n noRateLimit?: boolean | undefined\n /**\n * Explicitly disables the use of RPC caching.\n *\n * All storage slots are read entirely from the endpoint.\n */\n noStorageCaching?: boolean | undefined\n /**\n * How transactions are sorted in the mempool.\n *\n * @defaultValue fees\n */\n order?: string | undefined\n /**\n * Run an Optimism chain.\n */\n optimism?: boolean | undefined\n /**\n * Port number to listen on.\n *\n * @defaultValue 8545\n */\n port?: number | undefined\n /**\n * Don't keep full chain history. If a number argument is specified, at most this number of states is kept in memory.\n */\n pruneHistory?: number | undefined | boolean\n /**\n * Number of retry requests for spurious networks (timed out requests).\n *\n * @defaultValue 5\n */\n retries?: number | undefined\n /**\n * Don't print anything on startup and don't print logs.\n */\n silent?: boolean | undefined\n /**\n * Slots in an epoch.\n */\n slotsInAnEpoch?: number | undefined\n /**\n * Enable steps tracing used for debug calls returning geth-style traces.\n */\n stepsTracing?: boolean | undefined\n /**\n * Interval in seconds at which the status is to be dumped to disk.\n */\n stateInterval?: number | undefined\n /**\n * This is an alias for both `loadState` and `dumpState`. It initializes the chain with the state stored at the\n * file, if it exists, and dumps the chain's state on exit\n */\n state?: string | undefined\n /**\n * Timeout in ms for requests sent to remote JSON-RPC server in forking mode.\n *\n * @defaultValue 45000\n */\n timeout?: number | undefined\n /**\n * The timestamp of the genesis block.\n */\n timestamp?: number | bigint | undefined\n /**\n * Number of blocks with transactions to keep in memory.\n */\n transactionBlockKeeper?: number | undefined\n}\n","import { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { type ReactNode, useEffect } from 'react'\nimport { type Config, useConnect, WagmiProvider } from 'wagmi'\n\nconst Connect = () => {\n const { connectors, connect } = useConnect()\n\n useEffect(() => {\n if (connectors[0] === undefined) {\n return undefined\n }\n\n connect({ connector: connectors[0] })\n }, [connect, connectors])\n\n return <></>\n}\n\nexport const ReactTestWrapper = ({\n children,\n wagmiConfig,\n}: {\n children?: ReactNode\n wagmiConfig: Config\n}) => {\n const testQueryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n },\n mutations: {\n retry: false,\n },\n },\n })\n\n return (\n <WagmiProvider config={wagmiConfig}>\n <QueryClientProvider client={testQueryClient}>\n <>\n <Connect />\n {children}\n </>\n </QueryClientProvider>\n </WagmiProvider>\n )\n}\n","import type { Address } from 'viem'\n\n// Test accounts for impersonation\nexport const alice: Address = '0x0000000000000000000000000000000000001234'\nexport const bob: Address = '0x0000000000000000000000000000000000002345'\nexport const charlie: Address = '0x0000000000000000000000000000000000003456'\n"],"mappings":"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"}