Skip to content

feat(enskit-react-example): add alpha instance selector - #2299

Merged
sevenzing merged 4 commits into
mainfrom
ll/enskit-example-add-alpha-instance
Jun 17, 2026
Merged

feat(enskit-react-example): add alpha instance selector#2299
sevenzing merged 4 commits into
mainfrom
ll/enskit-example-add-alpha-instance

Conversation

@sevenzing

@sevenzing sevenzing commented Jun 15, 2026

Copy link
Copy Markdown
Member

Lite PR

Tip: Review docs on the ENSNode PR process

Summary

  • What changed (1-3 bullets, no essays).

Why

  • Why this change exists. Link to related GitHub issues where relevant.

Testing

  • How this was tested.
  • If you didn't test it, say why.

Notes for Reviewer (Optional)

  • Anything non-obvious or worth a heads-up.

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
enskit-react-example.ensnode.io Ready Ready Preview, Comment Jun 16, 2026 5:21pm
ensnode.io Ready Ready Preview, Comment Jun 16, 2026 5:21pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Jun 16, 2026 5:21pm
ensrainbow.io Skipped Skipped Jun 16, 2026 5:21pm

@changeset-bot

changeset-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: e7c0819

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8b5547d5-71ad-4788-9b1a-0b588535d6f9

📥 Commits

Reviewing files that changed from the base of the PR and between b97acc8 and e7c0819.

📒 Files selected for processing (5)
  • docs/ensnode.io/src/lib/examples/stackblitz/interactive/loadEnskitExampleProject.test.ts
  • examples/enskit-react-example/src/App.tsx
  • examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx
  • examples/enskit-react-example/src/NamegraphView.tsx
  • examples/enskit-react-example/src/instances.ts
💤 Files with no reviewable changes (1)
  • examples/enskit-react-example/src/instances.ts

📝 Walkthrough

Walkthrough

Replaces the static module-level ENSNode client (ensnode.ts) with a new EnsnodeInstanceProvider that manages dynamic instance selection via URL query params, localStorage, and an optional VITE_ENSNODE_URL env override. Introduces path routing helpers that automatically preserve the instance query param across navigation. All views consume the client and instance constants through a useEnsnodeInstance() hook.

Changes

ENSNode Instance Selection Provider

Layer / File(s) Summary
Instance config model and client factory
examples/enskit-react-example/src/instances.ts, examples/enskit-react-example/src/client.ts
Defines EnsnodeInstanceConstants and EnsnodeInstance interfaces, exports ENSNODE_INSTANCES array (two hardcoded instances), DEFAULT_ENSNODE_INSTANCE, storage key, and getEnsnodeInstanceById lookup helper. Adds createOmnigraphEnsNodeClient(url) factory and OmnigraphEnsNodeClient type alias. Removes the legacy ENNODE_URL and client exports from ensnode.ts.
EnsnodeInstanceProvider context and InstanceSelector
examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx
Implements resolveInstanceId (URL param → localStorage → default fallback), EnsnodeInstanceProvider with memoized client and OmnigraphProvider keying by ensnodeUrl, useEnsnodeInstance() hook, and InstanceSelector <select> component. When VITE_ENSNODE_URL is set, instance selection is disabled and that URL is used directly.
App root provider swap, header wiring, and test update
examples/enskit-react-example/src/App.tsx, docs/ensnode.io/src/lib/examples/stackblitz/interactive/loadEnskitExampleProject.test.ts
Replaces OmnigraphProvider with EnsnodeInstanceProvider at the app root, adds InstanceSelector to the header with instance-derived nav defaults, updates the Namegraph route remount key to include ensnodeUrl, and adds conditional Home page messaging for when instance selection is disabled. Updates test assertion to expect EnsnodeInstanceProvider.
Path routing helpers with instance param support
examples/enskit-react-example/src/app-paths.ts
Introduces path constructors (domainNamePath, domainIdPath, accountPath, namegraphPath) with encodeURIComponent, withInstanceSearch for appending instance query param, useAppPath hook deriving a path-building closure from router search params, and parentDomainPath selector for parent domain routes.
NamegraphView client and routing refactor
examples/enskit-react-example/src/NamegraphView.tsx
Replaces static client imports with useEnsnodeInstance(); fetchRegistryPage gains explicit client parameter with all call sites updated; details panel now passes registryId and constructs subregistry navigation via appPath with fromRegistryId state; adds conditional back-link for nested registry navigation; ResolutionPanels and NamegraphRootRedirect obtain client from context and use appPath for routing.
DomainView routing and constants refactor
examples/enskit-react-example/src/DomainView.tsx
Adds useEnsnodeInstance import to access constants; extends GraphQL query to include parent.canonical.name.interpreted; updates all domain/account/parent-domain link routing through useAppPath and path helpers; introduces CoercedNameRedirect for name-based redirects; updates malformed-name error link and label to use constants.defaultDomainName.
SearchView and AccountView routing updates
examples/enskit-react-example/src/SearchView.tsx, examples/enskit-react-example/src/AccountView.tsx
SearchView reads constants.defaultSearchLabel from useEnsnodeInstance() for placeholder and uses appPath(domainIdPath) for domain links; AccountView centralizes route construction via useAppPath, replacing hardcoded /account/${normalized} and / paths with appPath-based routing.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant InstanceSelector
  participant EnsnodeInstanceProvider
  participant localStorage
  participant OmnigraphProvider
  participant NamegraphView

  User->>InstanceSelector: select new instance
  InstanceSelector->>EnsnodeInstanceProvider: setInstanceId(id)
  EnsnodeInstanceProvider->>localStorage: persist ENSNODE_INSTANCE_STORAGE_KEY
  EnsnodeInstanceProvider->>EnsnodeInstanceProvider: update instance query param (replace)
  EnsnodeInstanceProvider->>EnsnodeInstanceProvider: recompute ensnodeUrl, memoize new client
  EnsnodeInstanceProvider->>OmnigraphProvider: remount keyed by ensnodeUrl
  OmnigraphProvider->>NamegraphView: new client via useEnsnodeInstance()
  NamegraphView->>NamegraphView: re-fetch registry page with new client
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • namehash/ensnode#2295: Directly related — refactors the same enskit-react-example files (App.tsx, NamegraphView.tsx, ensnode.ts) to use EnsnodeInstanceProvider/useEnsnodeInstance() for client and URL management.
  • namehash/ensnode#2044: Overlaps in Account browser route wiring (AccountView.tsx, App.tsx) and hardcoded navigation refactoring that the main PR now centralizes via useAppPath/app-paths helpers.
  • namehash/ensnode#2142: Both PRs modify the docs test assertion for the enskit-react-example App.tsx—the main PR introduces EnsnodeInstanceProvider and the retrieved PR updates the test expectation.

Suggested labels

javascript

🐇 No more hardcoded URL, no more static client!
The instances now live in a context so dynamic,
Pick your ENSNode from a <select> with a click,
localStorage remembers — it's quite the neat trick.
Routes stay in sync with appPath throughout,
Hop hop hooray, the provider's in! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description uses the correct template but all substantive sections (Summary, Why, Testing, Notes for Reviewer) are empty, containing only placeholder headers. Fill in the Summary (1-3 bullets about what changed), Why (motivation/linked issues), Testing (how tested), and optionally Notes for Reviewer sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding an instance selector feature to the enskit-react-example.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ll/enskit-example-add-alpha-instance

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx`:
- Around line 50-53: The EnsnodeInstanceProvider component initializes
instanceId from searchParams only once without synchronizing when the URL
changes. Add a useEffect hook that listens to searchParams as a dependency and
calls setInstanceIdState with the resolved value whenever searchParams changes.
This ensures that browser navigation (back/forward) or deep links with different
instance query parameters will properly update the instanceId state to match the
current URL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8da28fcb-5d05-4eec-9485-510856b6b341

📥 Commits

Reviewing files that changed from the base of the PR and between 09b4aa5 and c060018.

📒 Files selected for processing (8)
  • examples/enskit-react-example/src/App.tsx
  • examples/enskit-react-example/src/DomainView.tsx
  • examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx
  • examples/enskit-react-example/src/NamegraphView.tsx
  • examples/enskit-react-example/src/SearchView.tsx
  • examples/enskit-react-example/src/client.ts
  • examples/enskit-react-example/src/ensnode.ts
  • examples/enskit-react-example/src/instances.ts
💤 Files with no reviewable changes (1)
  • examples/enskit-react-example/src/ensnode.ts

Comment thread examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
examples/enskit-react-example/src/instances.ts (2)

1-5: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add JSDoc to document the type alias invariants.

The coding guidelines require that "Type aliases must document invariants; each invariant MUST be documented exactly once on its type alias". This interface should have JSDoc explaining its purpose and any invariants (e.g., defaultAddress must be a valid Ethereum address, defaultDomainName must be a valid ENS domain).

📝 Example JSDoc documentation
+/**
+ * Per-instance configuration constants used for defaults throughout the UI.
+ * Invariants:
+ * - defaultAddress must be a valid checksummed Ethereum address
+ * - defaultDomainName must be a valid ENS domain name
+ * - defaultSearchLabel must be a non-empty string
+ */
 export interface EnsnodeInstanceConstants {
   defaultAddress: string;
   defaultSearchLabel: string;
   defaultDomainName: string;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/enskit-react-example/src/instances.ts` around lines 1 - 5, Add JSDoc
documentation to the EnsnodeInstanceConstants interface to document its purpose
and invariants as required by the coding guidelines. The JSDoc should include a
description of the interface's purpose and clearly document the invariants for
each property (for example, that defaultAddress must be a valid Ethereum
address, defaultDomainName must be a valid ENS domain, etc.). Place this JSDoc
comment immediately above the interface declaration.

Source: Coding guidelines


7-12: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add JSDoc to document the type alias invariants.

Per coding guidelines, type aliases must document their invariants. This interface should explain its purpose and constraints (e.g., id must be unique across all instances, url must be a valid HTTPS endpoint).

📝 Example JSDoc documentation
+/**
+ * Represents a single ENSNode instance configuration.
+ * Invariants:
+ * - id must be unique within ENSNODE_INSTANCES
+ * - url must be a valid HTTPS endpoint
+ * - label is displayed in the instance selector UI
+ * - constants provides per-instance default values
+ */
 export interface EnsnodeInstance {
   id: string;
   url: string;
   label: string;
   constants: EnsnodeInstanceConstants;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/enskit-react-example/src/instances.ts` around lines 7 - 12, The
EnsnodeInstance interface is missing JSDoc documentation that describes its
purpose and invariants. Add a JSDoc comment block above the EnsnodeInstance
interface definition that explains the interface's purpose and documents the
constraints for each property, including that the id must be unique across all
instances, the url must be a valid HTTPS endpoint, and any other relevant
invariants for the label and constants properties.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/enskit-react-example/src/app-paths.ts`:
- Around line 21-25: The withInstanceSearch function on lines 21-25 always uses
a question mark as the separator when appending the instance parameter, but if
the input path already contains query parameters, this creates malformed URLs.
Fix this by checking whether the path already contains a question mark before
constructing the final URL. If the path already has a question mark, use an
ampersand as the separator; otherwise, use a question mark. This ensures proper
query parameter formatting regardless of whether the input path has existing
parameters.

In `@examples/enskit-react-example/src/instances.ts`:
- Around line 15-36: The hardcoded ENSNODE_INSTANCES array lacks validation,
allowing configuration errors to potentially slip into runtime. Create a Zod
schema that matches the EnsnodeInstance type structure (including validations
for URLs, Ethereum addresses, and required fields like id, url, label, and
constants), then use zod.parse() to validate the ENSNODE_INSTANCES array at
module load time. This ensures any malformed configuration data or invalid field
values are caught immediately when the module loads.

---

Outside diff comments:
In `@examples/enskit-react-example/src/instances.ts`:
- Around line 1-5: Add JSDoc documentation to the EnsnodeInstanceConstants
interface to document its purpose and invariants as required by the coding
guidelines. The JSDoc should include a description of the interface's purpose
and clearly document the invariants for each property (for example, that
defaultAddress must be a valid Ethereum address, defaultDomainName must be a
valid ENS domain, etc.). Place this JSDoc comment immediately above the
interface declaration.
- Around line 7-12: The EnsnodeInstance interface is missing JSDoc documentation
that describes its purpose and invariants. Add a JSDoc comment block above the
EnsnodeInstance interface definition that explains the interface's purpose and
documents the constraints for each property, including that the id must be
unique across all instances, the url must be a valid HTTPS endpoint, and any
other relevant invariants for the label and constants properties.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 712d9019-f755-4d39-ba6b-a08922835b15

📥 Commits

Reviewing files that changed from the base of the PR and between c060018 and 7949d25.

📒 Files selected for processing (7)
  • examples/enskit-react-example/src/AccountView.tsx
  • examples/enskit-react-example/src/App.tsx
  • examples/enskit-react-example/src/DomainView.tsx
  • examples/enskit-react-example/src/NamegraphView.tsx
  • examples/enskit-react-example/src/SearchView.tsx
  • examples/enskit-react-example/src/app-paths.ts
  • examples/enskit-react-example/src/instances.ts

Comment thread examples/enskit-react-example/src/app-paths.ts
Comment thread examples/enskit-react-example/src/instances.ts
@sevenzing

Copy link
Copy Markdown
Member Author

@greptile review

@sevenzing
sevenzing marked this pull request as ready for review June 16, 2026 17:32
@sevenzing
sevenzing requested a review from a team as a code owner June 16, 2026 17:32
@greptile-apps

greptile-apps Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a runtime ENSNode instance selector to the enskit-react-example app, letting users (or the hosted StackBlitz demo) switch between the Alpha Mainnet and V2 Sepolia instances without rebuilding. The selected instance is persisted in localStorage and surfaced in the URL as ?instance=<id>, which all internal navigation links carry forward via the new useAppPath hook.

  • EnsnodeInstanceProvider replaces the old static OmnigraphProvider + module-level client with a dynamic context that creates a new OmnigraphEnsNodeClient per instance and force-remounts OmnigraphProvider (via key={ensnodeUrl}) to flush stale query state on switch.
  • app-paths.ts centralises path construction and ensures every generated link preserves the active ?instance= param, so the user's selection survives navigation.
  • instances.ts / client.ts extract instance metadata (URLs, demo addresses, domain names) and the client factory into dedicated modules, replacing the deleted ensnode.ts.

Confidence Score: 4/5

  • The change is a well-scoped example-app feature with no impact on production library code; the core switching logic is correct and the OmnigraphProvider remount strategy is sound.
  • The implementation is clean and the instance-switching flow works correctly end-to-end. Two minor style nits exist: the useState lazy initializer and its corresponding useEffect both run resolveInstanceId on mount (harmless due to React's same-value bail-out), and ENSNODE_INSTANCES[0] is used without a non-null assertion, leaving a silent runtime gap if the array were ever emptied.
  • EnsnodeInstanceProvider.tsx for the redundant mount-time effect, and instances.ts for the unguarded array index on DEFAULT_ENSNODE_INSTANCE.

Important Files Changed

Filename Overview
examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx New provider that manages ENSNode instance selection via URL params and localStorage; dual initialization (useState + useEffect on mount) is redundant but harmless, and OmnigraphProvider remounts correctly on URL change via key prop
examples/enskit-react-example/src/instances.ts Defines the two ENSNode instances (alpha mainnet, v2-sepolia) and exports DEFAULT_ENSNODE_INSTANCE as ENSNODE_INSTANCES[0] — typed as EnsnodeInstance without undefined, so an empty array would silently yield undefined at runtime
examples/enskit-react-example/src/app-paths.ts New path helpers that encode URL segments and preserve ?instance= query param across all internal navigation via useAppPath hook
examples/enskit-react-example/src/App.tsx Swaps static OmnigraphProvider for dynamic EnsnodeInstanceProvider; moves OmnigraphProvider inside HashRouter so useSearchParams works correctly
examples/enskit-react-example/src/client.ts Extracts client factory from deleted ensnode.ts into a reusable createOmnigraphEnsNodeClient function
examples/enskit-react-example/src/NamegraphView.tsx Wires client from context instead of a module singleton, adds client to useCallback/useEffect deps, and adds a "back to parent registry" link via location.state
examples/enskit-react-example/src/DomainView.tsx Adopts appPath helpers for all internal links, adds interpreted name to parent query for smarter parent URL routing, and makes owner addresses clickable links
examples/enskit-react-example/src/AccountView.tsx Replaces hardcoded path strings with appPath helpers to preserve instance param in redirects and links
examples/enskit-react-example/src/SearchView.tsx Adopts appPath for domain links and uses instance-specific defaultSearchLabel as the search placeholder

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant InstanceSelector
    participant EnsnodeInstanceProvider
    participant localStorage
    participant HashRouter (URL)
    participant OmnigraphProvider
    participant Views (Layout / DomainView / etc.)

    User->>InstanceSelector: selects "V2 Sepolia"
    InstanceSelector->>EnsnodeInstanceProvider: setInstanceId("v2-sepolia")
    EnsnodeInstanceProvider->>EnsnodeInstanceProvider: setInstanceIdState("v2-sepolia")
    EnsnodeInstanceProvider->>localStorage: setItem(key, "v2-sepolia")
    EnsnodeInstanceProvider->>HashRouter (URL): setSearchParams({instance: "v2-sepolia"}, replace)
    HashRouter (URL)-->>EnsnodeInstanceProvider: searchParams changed → useEffect fires
    EnsnodeInstanceProvider->>EnsnodeInstanceProvider: resolveInstanceId → "v2-sepolia" (same, no re-render)
    EnsnodeInstanceProvider->>OmnigraphProvider: "new client + key=newUrl forces remount"
    OmnigraphProvider-->>Views (Layout / DomainView / etc.): fresh query context
    Views (Layout / DomainView / etc.)->>Views (Layout / DomainView / etc.): useAppPath() preserves ?instance=v2-sepolia in all Links
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant InstanceSelector
    participant EnsnodeInstanceProvider
    participant localStorage
    participant HashRouter (URL)
    participant OmnigraphProvider
    participant Views (Layout / DomainView / etc.)

    User->>InstanceSelector: selects "V2 Sepolia"
    InstanceSelector->>EnsnodeInstanceProvider: setInstanceId("v2-sepolia")
    EnsnodeInstanceProvider->>EnsnodeInstanceProvider: setInstanceIdState("v2-sepolia")
    EnsnodeInstanceProvider->>localStorage: setItem(key, "v2-sepolia")
    EnsnodeInstanceProvider->>HashRouter (URL): setSearchParams({instance: "v2-sepolia"}, replace)
    HashRouter (URL)-->>EnsnodeInstanceProvider: searchParams changed → useEffect fires
    EnsnodeInstanceProvider->>EnsnodeInstanceProvider: resolveInstanceId → "v2-sepolia" (same, no re-render)
    EnsnodeInstanceProvider->>OmnigraphProvider: "new client + key=newUrl forces remount"
    OmnigraphProvider-->>Views (Layout / DomainView / etc.): fresh query context
    Views (Layout / DomainView / etc.)->>Views (Layout / DomainView / etc.): useAppPath() preserves ?instance=v2-sepolia in all Links
Loading

Reviews (1): Last reviewed commit: "fix cicd" | Re-trigger Greptile

Comment thread examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx
Comment thread examples/enskit-react-example/src/instances.ts
@greptile-apps

greptile-apps Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds an alpha-instance selector to the enskit-react-example app, letting users switch between the Alpha Mainnet and V2 Sepolia ENSNode instances without reloading the page. The selected instance is persisted in both the URL query string (?instance=) and localStorage, and is propagated transparently through all in-app navigation links via the new useAppPath / withInstanceSearch utilities.

  • EnsnodeInstanceProvider replaces the old static OmnigraphProvider+client in ensnode.ts; it manages instance resolution (URL → localStorage → default), memoises the client, and re-keys OmnigraphProvider on URL change to flush cached queries.
  • instances.ts defines the two hosted instances with per-instance UI constants (defaultAddress, defaultDomainName, defaultSearchLabel), and app-paths.ts centralises all route-string construction so the ?instance= param is never accidentally dropped during navigation.
  • All views (DomainView, AccountView, SearchView, NamegraphView) are updated to consume the context client instead of the deleted singleton, with effect dependency arrays corrected to include client.

Confidence Score: 4/5

Safe to merge; changes are confined to the example app and introduce no regressions to the core library.

The refactor is well-structured and internally consistent. The two findings are both non-blocking quality suggestions: DEFAULT_ENSNODE_INSTANCE relies on array-index assignment without a guard, and useAppPath allocates a new function reference on every render. Neither causes incorrect behaviour today, but both could catch future contributors off-guard.

instances.ts (DEFAULT_ENSNODE_INSTANCE guard) and app-paths.ts (useAppPath memoization) are worth a second look, though neither is blocking.

Important Files Changed

Filename Overview
examples/enskit-react-example/src/EnsnodeInstanceProvider.tsx New context provider managing ENSNode instance selection, URL/localStorage persistence, and OmnigraphProvider lifecycle — well-structured with proper memoization and guarded localStorage access.
examples/enskit-react-example/src/instances.ts Defines the two ENSNode instances and the DEFAULT_ENSNODE_INSTANCE constant; the array-index assignment has a minor type-safety gap if the array is ever empty.
examples/enskit-react-example/src/app-paths.ts New path-builder utilities that propagate the instance search param across navigation; useAppPath returns an unstabilized function reference on every render.
examples/enskit-react-example/src/App.tsx Replaces static OmnigraphProvider with EnsnodeInstanceProvider, adds InstanceSelector to the Layout, and threads appPath through navigation links — changes are correct and consistent.
examples/enskit-react-example/src/client.ts New factory module that extracts client construction from the deleted ensnode.ts; simple and correct.
examples/enskit-react-example/src/NamegraphView.tsx Threads client from context through fetchRegistryPage and adds it to all effect dependency arrays; adds location-state-based back-to-parent-registry link.
examples/enskit-react-example/src/DomainView.tsx Updated all hard-coded path strings to use appPath helpers; adds clickable owner address link for subdomains; fetches interpreted field needed by parentDomainPath.
examples/enskit-react-example/src/AccountView.tsx Replaces hard-coded route strings with appPath helpers for instance-aware navigation; no logic changes.
examples/enskit-react-example/src/SearchView.tsx Threads appPath into search result links and pulls search placeholder from instance constants; minor, correct change.
docs/ensnode.io/src/lib/examples/stackblitz/interactive/loadEnskitExampleProject.test.ts Test updated to assert EnsnodeInstanceProvider presence in App.tsx instead of the removed OmnigraphProvider — correctly tracks the renamed provider.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[App / HashRouter] --> B[EnsnodeInstanceProvider]
    B --> C{resolveInstanceId}
    C -->|URL ?instance=| D[URLSearchParams]
    C -->|fallback| E[localStorage]
    C -->|fallback| F[DEFAULT_ENSNODE_INSTANCE]
    B --> G[EnsnodeInstanceContext.Provider]
    G --> H["OmnigraphProvider\n(key=ensnodeUrl)"]
    H --> I[Layout / Routes]
    I --> J[InstanceSelector\n select dropdown]
    I --> K[Views\nDomain / Account / Search / Namegraph]
    J -->|setInstanceId| L[Update state + localStorage + URL]
    L -->|searchParams change| B
    K -->|useAppPath| M["withInstanceSearch\n(propagates ?instance= param)"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[App / HashRouter] --> B[EnsnodeInstanceProvider]
    B --> C{resolveInstanceId}
    C -->|URL ?instance=| D[URLSearchParams]
    C -->|fallback| E[localStorage]
    C -->|fallback| F[DEFAULT_ENSNODE_INSTANCE]
    B --> G[EnsnodeInstanceContext.Provider]
    G --> H["OmnigraphProvider\n(key=ensnodeUrl)"]
    H --> I[Layout / Routes]
    I --> J[InstanceSelector\n select dropdown]
    I --> K[Views\nDomain / Account / Search / Namegraph]
    J -->|setInstanceId| L[Update state + localStorage + URL]
    L -->|searchParams change| B
    K -->|useAppPath| M["withInstanceSearch\n(propagates ?instance= param)"]
Loading

Reviews (2): Last reviewed commit: "fix cicd" | Re-trigger Greptile

Comment thread examples/enskit-react-example/src/instances.ts
Comment thread examples/enskit-react-example/src/app-paths.ts

@lightwalker-eth lightwalker-eth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sevenzing Thanks for updates. Please take the lead to merge when you're ready 👍

@sevenzing
sevenzing merged commit 755ce89 into main Jun 17, 2026
21 checks passed
@sevenzing
sevenzing deleted the ll/enskit-example-add-alpha-instance branch June 17, 2026 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants