{"version":3,"sources":["../src/index.ts","../src/context.ts","../src/hooks/useEnsNodeProviderOptions.ts","../src/hooks/useIndexingStatus.ts","../src/utils/query.ts","../src/hooks/useNameTokens.ts","../src/hooks/usePrimaryName.ts","../src/hooks/usePrimaryNames.ts","../src/hooks/useRecords.ts","../src/hooks/useRegistrarActions.ts","../src/hooks/useResolvedIdentity.ts","../src/hooks/useSwrQuery.ts","../src/provider.tsx"],"sourcesContent":["export type { QueryClient } from \"@tanstack/react-query\";\n\nexport type { ResolverRecordsSelection } from \"@ensnode/ensnode-sdk\";\n\nexport * from \"./context\";\nexport * from \"./hooks\";\nexport * from \"./provider\";\nexport * from \"./types\";\nexport * from \"./utils/query\";\n","import { createContext } from \"react\";\n\nimport type { EnsNodeProviderOptions } from \"./types\";\n\n/**\n * React context for ENSNodeProvider options\n */\nexport const EnsNodeContext = createContext<EnsNodeProviderOptions | undefined>(undefined);\n\n/**\n * Display name for debugging\n */\nEnsNodeContext.displayName = \"EnsNodeContext\";\n","\"use client\";\n\nimport { useContext } from \"react\";\n\nimport { EnsNodeContext } from \"../context\";\nimport type { EnsNodeProviderOptions } from \"../types\";\n\n/**\n * Hook to access the {@link EnsNodeProviderOptions} from context or parameters.\n *\n * @param options - Options parameter that overrides context\n * @throws Error if no options are available in context or parameters\n */\nexport function useEnsNodeProviderOptions<\n  ProviderOptionsType extends EnsNodeProviderOptions = EnsNodeProviderOptions,\n>(options?: ProviderOptionsType): ProviderOptionsType {\n  const contextOptions = useContext(EnsNodeContext);\n\n  // Use provided options or fall back to context\n  const resolvedOptions = options ?? contextOptions;\n\n  if (!resolvedOptions) {\n    throw new Error(\n      \"useEnsNodeProviderOptions must be used within an EnsNodeProvider or you must pass the options parameter\",\n    );\n  }\n\n  return resolvedOptions as ProviderOptionsType;\n}\n","import { useQuery } from \"@tanstack/react-query\";\n\nimport type {\n  EnsApiIndexingStatusRequest,\n  EnsApiIndexingStatusResponse,\n} from \"@ensnode/ensnode-sdk\";\n\nimport type { QueryParameter, WithEnsNodeProviderOptions } from \"../types\";\nimport { createIndexingStatusQueryOptions } from \"../utils/query\";\nimport { useEnsNodeProviderOptions } from \"./useEnsNodeProviderOptions\";\n\ninterface UseIndexingStatusParameters\n  extends EnsApiIndexingStatusRequest,\n    QueryParameter<EnsApiIndexingStatusResponse> {}\n\nexport function useIndexingStatus(\n  parameters: WithEnsNodeProviderOptions & UseIndexingStatusParameters = {},\n) {\n  const { options, query = {} } = parameters;\n  const providerOptions = useEnsNodeProviderOptions(options);\n  const queryOptions = createIndexingStatusQueryOptions(providerOptions);\n\n  return useQuery({\n    ...queryOptions,\n    refetchInterval: 10 * 1000, // 10 seconds - indexing status changes frequently\n    ...query,\n    enabled: query.enabled ?? queryOptions.enabled,\n  });\n}\n","\"use client\";\n\nimport type { UndefinedInitialDataOptions } from \"@tanstack/react-query\";\n\nimport {\n  EnsNodeClient,\n  type NameTokensRequest,\n  type RegistrarActionsRequest,\n  type ResolvePrimaryNameRequest,\n  type ResolvePrimaryNamesRequest,\n  type ResolveRecordsRequest,\n  type ResolverRecordsSelection,\n} from \"@ensnode/ensnode-sdk\";\n\nimport type { EnsNodeProviderOptions } from \"../types\";\n\n/**\n * Immutable query options for data that is assumed to be immutable and should only be fetched once per full page refresh per unique key.\n * Similar to SWR's immutable: true API.\n *\n * Use this for data that is assumed not to change (e.g., records for a specific name) until the next full page refresh.\n *\n * @example\n * ```tsx\n * useRecords({\n *   name: \"vitalik.eth\",\n *   selection: { texts: [\"avatar\"] },\n *   query: ASSUME_IMMUTABLE_QUERY\n * })\n * ```\n */\nexport const ASSUME_IMMUTABLE_QUERY = {\n  staleTime: Infinity,\n  gcTime: Infinity,\n  refetchOnWindowFocus: false,\n  refetchOnReconnect: false,\n  refetchOnMount: false,\n} as const satisfies Partial<UndefinedInitialDataOptions>;\n\n/**\n * Query keys for hooks. Simply keys by path and arguments.\n */\nexport const queryKeys = {\n  base: (url: string) => [\"ensnode\", url] as const,\n\n  resolve: (url: string) => [...queryKeys.base(url), \"resolve\"] as const,\n\n  records: (url: string, args: ResolveRecordsRequest<any>) =>\n    [...queryKeys.resolve(url), \"records\", args] as const,\n\n  primaryName: (url: string, args: ResolvePrimaryNameRequest) =>\n    [...queryKeys.resolve(url), \"primary-name\", args] as const,\n\n  primaryNames: (url: string, args: ResolvePrimaryNamesRequest) =>\n    [...queryKeys.resolve(url), \"primary-names\", args] as const,\n\n  indexingStatus: (url: string) => [...queryKeys.base(url), \"indexing-status\"] as const,\n\n  registrarActions: (url: string, args: RegistrarActionsRequest) =>\n    [...queryKeys.base(url), \"registrar-actions\", args] as const,\n\n  nameTokens: (url: string, args: NameTokensRequest) =>\n    [...queryKeys.base(url), \"name-tokens\", args] as const,\n};\n\n/**\n * Creates query options for Records Resolution\n */\nexport function createRecordsQueryOptions<SELECTION extends ResolverRecordsSelection>(\n  config: EnsNodeProviderOptions,\n  args: ResolveRecordsRequest<SELECTION>,\n) {\n  return {\n    enabled: true,\n    queryKey: queryKeys.records(config.client.url.href, args),\n    queryFn: async () => {\n      const client = new EnsNodeClient(config.client);\n      return client.resolveRecords(args.name, args.selection, args);\n    },\n  };\n}\n\n/**\n * Creates query options for Primary Name Resolution\n */\nexport function createPrimaryNameQueryOptions(\n  config: EnsNodeProviderOptions,\n  args: ResolvePrimaryNameRequest,\n) {\n  return {\n    enabled: true,\n    queryKey: queryKeys.primaryName(config.client.url.href, args),\n    queryFn: async () => {\n      const client = new EnsNodeClient(config.client);\n      return client.resolvePrimaryName(args.address, args.chainId, args);\n    },\n  };\n}\n\n/**\n * Creates query options for Primary Name Resolution\n */\nexport function createPrimaryNamesQueryOptions(\n  config: EnsNodeProviderOptions,\n  args: ResolvePrimaryNamesRequest,\n) {\n  return {\n    enabled: true,\n    queryKey: queryKeys.primaryNames(config.client.url.href, args),\n    queryFn: async () => {\n      const client = new EnsNodeClient(config.client);\n      return client.resolvePrimaryNames(args.address, args);\n    },\n  };\n}\n\n/**\n * Creates query options for ENSNode Indexing Status API\n */\nexport function createIndexingStatusQueryOptions(config: EnsNodeProviderOptions) {\n  return {\n    enabled: true,\n    queryKey: queryKeys.indexingStatus(config.client.url.href),\n    queryFn: async () => {\n      const client = new EnsNodeClient(config.client);\n      return client.indexingStatus();\n    },\n  };\n}\n\n/**\n * Creates query options for ENSNode Registrar Actions API\n */\nexport function createRegistrarActionsQueryOptions(\n  config: EnsNodeProviderOptions,\n  args: RegistrarActionsRequest,\n) {\n  return {\n    enabled: true,\n    queryKey: queryKeys.registrarActions(config.client.url.href, args),\n    queryFn: async () => {\n      const client = new EnsNodeClient(config.client);\n\n      return client.registrarActions(args);\n    },\n  };\n}\n\n/**\n * Creates query options for Name Tokens API\n */\nexport function createNameTokensQueryOptions(\n  config: EnsNodeProviderOptions,\n  args: NameTokensRequest,\n) {\n  return {\n    enabled: true,\n    queryKey: queryKeys.nameTokens(config.client.url.href, args),\n    queryFn: async () => {\n      const client = new EnsNodeClient(config.client);\n\n      return client.nameTokens(args);\n    },\n  };\n}\n","import { useQuery } from \"@tanstack/react-query\";\n\nimport type { NameTokensRequest, NameTokensResponse } from \"@ensnode/ensnode-sdk\";\n\nimport type { QueryParameter, WithEnsNodeProviderOptions } from \"../types\";\nimport { createNameTokensQueryOptions } from \"../utils/query\";\nimport { useEnsNodeProviderOptions } from \"./useEnsNodeProviderOptions\";\n\ntype UseNameTokensParameters = NameTokensRequest & QueryParameter<NameTokensResponse>;\n\n/**\n * Use Name Tokens hook\n *\n * Query ENSNode Name Tokens API.\n */\nexport function useNameTokens(parameters: WithEnsNodeProviderOptions & UseNameTokensParameters) {\n  const { options, query = {}, ...request } = parameters;\n  const providerOptions = useEnsNodeProviderOptions(options);\n\n  const queryOptions = createNameTokensQueryOptions(providerOptions, request);\n\n  return useQuery({\n    ...queryOptions,\n    refetchInterval: false, // no refetching - assume data is immutable until a full page refresh\n    ...query,\n    enabled: query.enabled ?? queryOptions.enabled,\n  });\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport type { UsePrimaryNameParameters, WithEnsNodeProviderOptions } from \"../types\";\nimport { createPrimaryNameQueryOptions } from \"../utils/query\";\nimport { useEnsNodeProviderOptions } from \"./useEnsNodeProviderOptions\";\n\n/**\n * Resolves the primary name of a specified address (Reverse Resolution).\n *\n * The returned Primary Name, if set, is guaranteed to be a normalized name.\n * If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.\n *\n * @param parameters - Configuration for the address resolution\n * @returns Query result with resolved primary name\n *\n * @example\n * ```typescript\n * import { usePrimaryName } from \"@ensnode/ensnode-react\";\n *\n * function DisplayPrimaryNameAndAvatar() {\n *   const { data, isLoading, error } = usePrimaryName({\n *     address: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n *     chainId: 1, // Ethereum Mainnet\n *     accelerate: true, // Attempt Protocol Acceleration\n *   });\n *\n *   if (isLoading) return <div>Loading...</div>;\n *   if (error) return <div>Error: {error.message}</div>;\n *\n *   return (\n *     <div>\n *       <h3>Primary Name (for Mainnet)</h3>\n *       <p>{data.name ?? \"No Primary Name\"}</p>\n *     </div>\n *   );\n * }\n * ```\n */\nexport function usePrimaryName(parameters: UsePrimaryNameParameters & WithEnsNodeProviderOptions) {\n  const { options, query = {}, address, ...args } = parameters;\n  const providerOptions = useEnsNodeProviderOptions(options);\n\n  const canEnable = address !== null;\n\n  const queryOptions = canEnable\n    ? createPrimaryNameQueryOptions(providerOptions, { ...args, address })\n    : { enabled: false, queryKey: [\"disabled\"] as const };\n\n  return useQuery({\n    ...queryOptions,\n    ...query,\n    enabled: canEnable && (query.enabled ?? queryOptions.enabled),\n  });\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport type { UsePrimaryNamesParameters, WithEnsNodeProviderOptions } from \"../types\";\nimport { createPrimaryNamesQueryOptions } from \"../utils/query\";\nimport { useEnsNodeProviderOptions } from \"./useEnsNodeProviderOptions\";\n\n/**\n * Resolves the primary names of a specified address across multiple chains.\n *\n * Each returned Primary Name, if set, is guaranteed to be a normalized name.\n * If the primary name set for the address on any chain is not normalized, `null` is returned for that chain as if no primary name was set.\n *\n * @param parameters - Configuration for the address resolution\n * @returns Query result with resolved primary names\n *\n * @example\n * ```typescript\n * import { usePrimaryNames } from \"@ensnode/ensnode-react\";\n *\n * function DisplayPrimaryNames() {\n *   const { data, isLoading, error } = usePrimaryNames({\n *     address: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n *   });\n *\n *   if (isLoading) return <div>Loading...</div>;\n *   if (error) return <div>Error: {error.message}</div>;\n *\n *   return (\n *     <div>\n *       {Object.entries(data.names).map(([chainId, name]) => (\n *         <div key={chainId}>\n *           <h3>Primary Name (Chain Id: {chainId})</h3>\n *           <p>{name}</p>\n *         </div>\n *       ))}\n *     </div>\n *   );\n * }\n * ```\n */\nexport function usePrimaryNames(\n  parameters: UsePrimaryNamesParameters & WithEnsNodeProviderOptions,\n) {\n  const { options, query = {}, address, ...args } = parameters;\n  const providerOptions = useEnsNodeProviderOptions(options);\n\n  const canEnable = address !== null;\n\n  const queryOptions = canEnable\n    ? createPrimaryNamesQueryOptions(providerOptions, { ...args, address })\n    : { enabled: false, queryKey: [\"disabled\"] as const };\n\n  return useQuery({\n    ...queryOptions,\n    ...query,\n    enabled: canEnable && (query.enabled ?? queryOptions.enabled),\n  });\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport type { ResolverRecordsSelection } from \"@ensnode/ensnode-sdk\";\n\nimport type { UseRecordsParameters, WithEnsNodeProviderOptions } from \"../types\";\nimport { createRecordsQueryOptions } from \"../utils/query\";\nimport { useEnsNodeProviderOptions } from \"./useEnsNodeProviderOptions\";\n\n/**\n * Resolves records for an ENS name (Forward Resolution).\n *\n * The returned `name` field, if set, is guaranteed to be a normalized name.\n * If the name record returned by the resolver is not normalized, `null` is returned as if no name record was set.\n *\n * @param parameters - Configuration for the ENS name resolution\n * @returns Query result with resolved records\n *\n * @example\n * ```typescript\n * import { useRecords } from \"@ensnode/ensnode-react\";\n *\n * function DisplayNameRecords() {\n *   const { data, isLoading, error } = useRecords({\n *     name: \"jesse.base.eth\",\n *     selection: {\n *       addresses: [60], // ETH CoinType\n *       texts: [\"avatar\", \"com.twitter\"]\n *     }\n *   });\n *\n *   if (isLoading) return <div>Loading...</div>;\n *   if (error) return <div>Error: {error.message}</div>;\n *\n *   return (\n *     <div>\n *       <h3>Resolved Records for vitalik.eth</h3>\n *       {data.records.addresses && (\n *         <p>ETH Address: {data.records.addresses[60]}</p>\n *       )}\n *       {data.records.texts && (\n *         <div>\n *           <p>Avatar: {data.records.texts.avatar}</p>\n *           <p>Twitter: {data.records.texts[\"com.twitter\"]}</p>\n *         </div>\n *       )}\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useRecords<SELECTION extends ResolverRecordsSelection>(\n  parameters: UseRecordsParameters<SELECTION> & WithEnsNodeProviderOptions,\n) {\n  const { options, query = {}, name, ...args } = parameters;\n  const _config = useEnsNodeProviderOptions(options);\n\n  const canEnable = name !== null;\n\n  const queryOptions = canEnable\n    ? createRecordsQueryOptions(_config, { ...args, name })\n    : { enabled: false, queryKey: [\"disabled\"] as const };\n\n  return useQuery({\n    ...queryOptions,\n    ...query,\n    enabled: canEnable && (query.enabled ?? queryOptions.enabled),\n  });\n}\n","import { useQuery } from \"@tanstack/react-query\";\n\nimport type { RegistrarActionsRequest, RegistrarActionsResponse } from \"@ensnode/ensnode-sdk\";\n\nimport type { QueryParameter, WithEnsNodeProviderOptions } from \"../types\";\nimport { createRegistrarActionsQueryOptions } from \"../utils/query\";\nimport { useEnsNodeProviderOptions } from \"./useEnsNodeProviderOptions\";\n\ninterface UseRegistrarActionsParameters\n  extends RegistrarActionsRequest,\n    QueryParameter<RegistrarActionsResponse> {}\n\n/**\n * Use Registrar Actions hook\n *\n * Query ENSNode Registrar Actions API.\n */\nexport function useRegistrarActions(\n  parameters: WithEnsNodeProviderOptions & UseRegistrarActionsParameters = {},\n) {\n  const { options, query = {}, ...request } = parameters;\n  const providerOptions = useEnsNodeProviderOptions(options);\n\n  const queryOptions = createRegistrarActionsQueryOptions(providerOptions, request);\n\n  return useQuery({\n    ...queryOptions,\n    refetchInterval: 10 * 1000, // 10 seconds - latest registrar actions change frequently\n    ...query,\n    enabled: query.enabled ?? queryOptions.enabled,\n  });\n}\n","\"use client\";\n\nimport {\n  type ENSNamespaceId,\n  ENSNamespaceIds,\n  getResolvePrimaryNameChainIdParam,\n  type Identity,\n  type NamedIdentity,\n  ResolutionStatusIds,\n  ResolvedIdentity,\n  type UnknownIdentity,\n  type UnnamedIdentity,\n  type UnresolvedIdentity,\n} from \"@ensnode/ensnode-sdk\";\n\nimport type { UseResolvedIdentityParameters } from \"../types\";\nimport { ASSUME_IMMUTABLE_QUERY } from \"../utils/query\";\nimport { usePrimaryName } from \"./usePrimaryName\";\n\n/**\n * Hook to perform ENSIP-19 primary name resolution to resolve an\n * {@link UnresolvedIdentity} into a {@link ResolvedIdentity}.\n *\n * @param parameters - Configuration object for the hook\n * @param parameters.identity - An {@link UnresolvedIdentity} containing the {@link DefaultableChainId}\n *                              and {@link Address} to resolve.\n * @param parameters.namespace - The {@link ENSNamespaceId} that `identity.chainId` should be interpreted\n *                                 through (via {@link getResolvePrimaryNameChainIdParam}) to determine the literal\n *                                 chainId that should be used for ENSIP-19 primary name resolution.\n * @param parameters.accelerate - Whether to attempt Protocol Acceleration (default: false)\n *                                when resolving the primary name.\n *\n * @returns An object containing:\n * - `identity`: An {@link Identity} with one of four possible {@link ResolutionStatusIds}:\n *   - {@link ResolutionStatusIds.Unresolved}: While the query is pending (loading state).\n *   - {@link ResolutionStatusIds.Unknown}: If an error occurs during resolution.\n *   - {@link ResolutionStatusIds.Unnamed}: If the resolution found no primary name.\n *   - {@link ResolutionStatusIds.Named}: If a primary name is successfully resolved.\n * - All other properties from the underlying {@link usePrimaryName} query (e.g., `isLoading`, `error`, `refetch`, etc.)\n */\nexport function useResolvedIdentity(parameters: UseResolvedIdentityParameters) {\n  const { identity, namespace, accelerate, query: _query = {} } = parameters;\n\n  const {\n    data: primaryNameData,\n    status,\n    ...query\n  } = usePrimaryName({\n    address: identity.address,\n    chainId: getResolvePrimaryNameChainIdParam(\n      identity.chainId,\n      // NOTE: defaulting here for typechecking, but enabled prevents fetching before namespace is known\n      namespace ?? ENSNamespaceIds.Mainnet,\n    ),\n    accelerate,\n    // NOTE: Overriding `gcTime` to prevent unbounded memory growth\n    // in long-running sessions with many identities.\n    query: {\n      ...ASSUME_IMMUTABLE_QUERY, // identity changes very rarely\n      gcTime: 60 * 60 * 1000, // 1 hour\n      refetchInterval: false, // not covered by ASSUME_IMMUTABLE_QUERY\n      ..._query,\n      enabled: (_query.enabled ?? true) && namespace !== undefined,\n    },\n  });\n\n  let result: Identity;\n\n  if (status === \"pending\") {\n    // loading state\n    // return the `UnresolvedIdentity` to support loading state functionality.\n    result = identity;\n  } else if (status === \"error\") {\n    result = {\n      resolutionStatus: ResolutionStatusIds.Unknown,\n      chainId: identity.chainId,\n      address: identity.address,\n    } satisfies UnknownIdentity;\n  } else if (primaryNameData.name === null) {\n    result = {\n      resolutionStatus: ResolutionStatusIds.Unnamed,\n      chainId: identity.chainId,\n      address: identity.address,\n      name: null,\n    } satisfies UnnamedIdentity;\n  } else {\n    result = {\n      resolutionStatus: ResolutionStatusIds.Named,\n      chainId: identity.chainId,\n      address: identity.address,\n      name: primaryNameData.name,\n    } satisfies NamedIdentity;\n  }\n\n  return {\n    ...query,\n    identity: result,\n  };\n}\n","import {\n  type DefaultError,\n  type DefinedInitialDataOptions,\n  type DefinedUseQueryResult,\n  type QueryClient,\n  type QueryKey,\n  type QueryObserverSuccessResult,\n  type UndefinedInitialDataOptions,\n  type UseQueryOptions,\n  type UseQueryResult,\n  useQuery,\n  useQueryClient,\n} from \"@tanstack/react-query\";\nimport { useMemo } from \"react\";\n\n/**\n * Use Stale-While-Revalidate Query\n *\n * This hooks is a proxy for {@link useQuery} with addition of the following\n * semantics:\n * - if the query has been resolved successfully just once,\n *   the query result will always be success with data being the previously\n *   cached result,\n * - the cached result can never go stale, or be garbage collected\n * - the cached result can be only overridden by the current result when\n *   the query is successfully re-fetched (in other words,\n *   the `options.queryFn` returns a resolved promise).\n *\n * Please note how there can be any number of failed queries before one\n * succeeds. In such case, no successful result has ever been cached and\n * the query fails (`isError: true`, `error` is available) until\n * the first successful resolution (`isSuccess: true`, `data` is available).\n *\n * @example\n * ```tsx\n * const swrQuery = useSwrQuery({\n *   queryKey: ['data'],\n *   queryFn: fetchData,\n * });\n *\n * if (swrQuery.isPending) {\n *   // Show loading state while there's no cached successful result and\n *   // no query attempt was finished yet.\n *   return <>Loading...</>;\n * }\n *\n * if (swrQuery.isError) {\n *   // Show error state when query attempt fails and\n *   // no cached successful result is available.\n *   return <>Error: {swrQuery.error.message}</>;\n * }\n *\n * // Otherwise, show data when the cached successful result is available.\n * return <>Data: {JSON.stringify(swrQuery.data)}</>;\n * ```\n */\nexport function useSwrQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): DefinedUseQueryResult<NoInfer<TData>, TError>;\nexport function useSwrQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError>;\nexport function useSwrQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError>;\nexport function useSwrQuery<\n  TQueryFnData = unknown,\n  TError = DefaultError,\n  TData = TQueryFnData,\n  TQueryKey extends QueryKey = QueryKey,\n>(\n  options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,\n  queryClient?: QueryClient,\n): UseQueryResult<NoInfer<TData>, TError> {\n  const queryClientFromContext = useQueryClient();\n  const derivedQueryClient = queryClient ?? queryClientFromContext;\n\n  // cacheResult, if available, is always the last successfully resolved query data\n  const cachedSuccessfulResult = derivedQueryClient.getQueryData<TData>(options.queryKey);\n\n  const queryResult = useQuery(\n    {\n      ...options,\n      // cached result can never be stale\n      staleTime: cachedSuccessfulResult ? Infinity : undefined,\n      // cached result can never be removed by garbage collector\n      gcTime: cachedSuccessfulResult ? Infinity : undefined,\n    },\n    queryClient,\n  );\n\n  // memoize query results to avoid unnecessary UI re-rendering\n  const memoizedQueryResult = useMemo(() => {\n    // If the query result is error\n    // and the cachedSuccessfulResult is available\n    // override the query result to be success, replacing the unsuccessful\n    // result with the most recent cachedSuccessfulResult\n    if (queryResult.isError && cachedSuccessfulResult) {\n      return {\n        ...queryResult,\n        // set error props\n        isError: false,\n        error: null,\n        isRefetchError: false,\n        isLoadingError: false,\n        // st success props\n        isSuccess: true,\n        status: \"success\",\n        data: cachedSuccessfulResult,\n      } satisfies QueryObserverSuccessResult<TData, TError>;\n    }\n\n    return queryResult;\n  }, [queryResult, cachedSuccessfulResult]);\n\n  return memoizedQueryResult;\n}\n","/** biome-ignore-all lint/correctness/useHookAtTopLevel: conditional hooks used correctly here */\n\"use client\";\n\nimport { QueryClient, QueryClientProvider, useQueryClient } from \"@tanstack/react-query\";\nimport { createElement, useMemo } from \"react\";\n\nimport { EnsNodeClient } from \"@ensnode/ensnode-sdk\";\n\nimport { EnsNodeContext } from \"./context\";\nimport type { EnsNodeProviderOptions } from \"./types\";\n\nexport interface EnsNodeProviderProps {\n  /** ENSNode Provider Options */\n  options: EnsNodeProviderOptions;\n\n  /**\n   * Optional QueryClient instance. If provided, you must wrap your app with QueryClientProvider yourself.\n   * If not provided, EnsNodeProvider will create and manage its own QueryClient internally.\n   */\n  queryClient?: QueryClient;\n\n  /**\n   * Custom query client options when auto-creating a QueryClient.\n   * Only used when queryClient is not provided.\n   */\n  queryClientOptions?: ConstructorParameters<typeof QueryClient>[0];\n}\n\nfunction EnsNodeInternalProvider({\n  children,\n  options,\n}: {\n  children?: React.ReactNode;\n  options: EnsNodeProviderOptions;\n}) {\n  return createElement(EnsNodeContext.Provider, { value: options }, children);\n}\n\nexport function EnsNodeProvider(parameters: React.PropsWithChildren<EnsNodeProviderProps>) {\n  const { children, options, queryClient, queryClientOptions } = parameters;\n\n  // Check if we're already inside a QueryClientProvider\n  let hasExistingQueryClient = false;\n  try {\n    hasExistingQueryClient = Boolean(useQueryClient());\n  } catch {\n    // useQueryClient throws if not inside a QueryClientProvider\n    hasExistingQueryClient = false;\n  }\n\n  // If user provided a queryClient, they must handle QueryClientProvider themselves\n  if (queryClient) {\n    if (!hasExistingQueryClient) {\n      throw new Error(\n        \"When providing a custom queryClient, you must wrap your app with QueryClientProvider. \" +\n          \"Either remove the queryClient prop to use auto-managed setup, or wrap with QueryClientProvider.\",\n      );\n    }\n    return createElement(EnsNodeInternalProvider, { options, children });\n  }\n\n  // If already inside a QueryClientProvider, just use that\n  if (hasExistingQueryClient) {\n    return createElement(EnsNodeInternalProvider, { options, children });\n  }\n\n  // Create our own QueryClient and QueryClientProvider\n  const defaultQueryClient = useMemo(\n    () =>\n      new QueryClient({\n        defaultOptions: {\n          queries: {\n            retry: 3,\n            staleTime: 1000 * 60 * 5, // 5 minutes\n            gcTime: 1000 * 60 * 30, // 30 minutes\n            refetchInterval: 1000 * 10, // 10 seconds\n          },\n        },\n        ...queryClientOptions,\n      }),\n    [queryClientOptions],\n  );\n\n  return createElement(\n    QueryClientProvider,\n    { client: defaultQueryClient },\n    createElement(EnsNodeInternalProvider, { options, children }),\n  );\n}\n\n/**\n * Helper function to create ENSNode Provider Options\n */\nexport function createEnsNodeProviderOptions(options?: {\n  url?: string | URL;\n}): EnsNodeProviderOptions {\n  const url = options?.url ? new URL(options.url) : EnsNodeClient.defaultOptions().url;\n\n  return {\n    client: {\n      ...EnsNodeClient.defaultOptions(),\n      url,\n    },\n  };\n}\n"],"mappings":"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","names":["import_react","import_react_query","import_react_query","import_react_query","import_react_query","import_react_query","import_ensnode_sdk","import_react_query","import_react","import_react_query","import_react","import_ensnode_sdk"]}