OpenZeppelin / OpenZeppelin/openzeppelin-ui

feat(renderer): form-level ENS address preview mode (rich vs simple) for TransactionForm

Open
#197 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

cla: allowlist enhancement
Dominant language
TypeScript
Stars
7
Forks
3
Avg merge
20h 20m
Merged PRs (30d)
26

Description

Summary

Add a form-level setting so TransactionForm / DynamicFormField can render blockchain-address fields with either:

Mode UX Default when omitted
rich Pattern A: AddressFieldWithResolvedPreview + ResolvedAddressFieldPreviewWithNameResolution + parent useWatch
simple Bare AddressField with inline “Resolved to 0x…” announcer (current behavior) yes (backward compat)

Today fieldRegistry maps blockchain-addressAddressField only. Rich preview exists elsewhere (Address Book AddAliasDialog, basic-react-app demos) but is not available to TransactionForm consumers (ui-builder form preview, exported apps, direct integrators).

Downstream tracking: OpenZeppelin/ui-builder#403 (Phase 2 — builder toggle, export schema, tests).


Motivation

  • Single implementation path in @openzeppelin/ui-renderer keeps builder preview, exported apps, and any TransactionForm consumer aligned
  • Integrators can opt into rich ENS UX without custom field wrappers
  • Omitted setting preserves behavior for existing serialized form schemas

Design principles

Capability-led, not ecosystem-specific. Gate behavior on EcosystemRuntime.nameResolution (resolveName / resolveAddress per NameResolutionCapability in @openzeppelin/ui-types). Do not branch on networkConfig.ecosystem === 'evm'.

When nameResolution is absent, both modes degrade to plain address input (existing useRuntimeNameResolverEMPTY_RESOLVER behavior).


Proposed API

@openzeppelin/ui-types
export type EnsAddressPreviewMode = 'rich' | 'simple';

// On CommonFormProperties and/or RenderFormSchema:
ensAddressPreview?: EnsAddressPreviewMode;

Prefer a first-class schema field over metadata for export stability and discoverability.

@openzeppelin/ui-renderer
RenderFormSchema.ensAddressPreview
    ↓
TransactionForm (read schema, provide context)
    ↓
DynamicFormField (blockchain-address)
    ├─ 'rich'  → BlockchainAddressDynamicField (Pattern A)
    └─ 'simple' → AddressField (current)

Thread mode through recursive DynamicFormField calls so nested object/array/map address fields inherit the form-level setting.

Default: ensAddressPreview omitted → 'simple'.


Implementation tasks

ui-types
  • Add EnsAddressPreviewMode type
  • Add optional ensAddressPreview to CommonFormProperties / RenderFormSchema
  • Export from package public API
ui-renderer
  • Create BlockchainAddressDynamicField (or equivalent) implementing Pattern A:
    • useWatchpreviewAddress
    • rich: AddressFieldWithResolvedPreview + ResolvedAddressFieldPreviewWithNameResolution
    • simple: AddressField
    • networkId from adapter / useAdapter() (existing patterns)
  • Add React context (or prop threading) from TransactionFormDynamicFormField for ensAddressPreview
  • Update fieldRegistry / DynamicFormField switch for blockchain-address
  • Graceful degradation when nameResolution missing (no throws)
  • rich without resolveAddress: forward resolution still works; preview card may be address-only
Tests
  • TransactionForm renders rich preview when ensAddressPreview: 'rich'
  • Default / omitted → simple announcer (snapshot or behavioral)
  • Nested blockchain-address fields inherit mode
  • Runtime without nameResolution → plain address field in both modes
  • Existing tests unaffected (default remains simple)
Docs / examples (optional but recommended)
  • Note in TransactionForm / form schema docs
  • Extend AddressFieldDemo or add minimal example showing schema flag

Acceptance criteria

  • ensAddressPreview: 'rich' on RenderFormSchema renders Pattern A below all blockchain-address fields in TransactionForm
  • Omitted or 'simple' matches current AddressField announcer behavior
  • No ecosystem === 'evm' conditionals introduced
  • Nested fields inherit form-level mode
  • Published package versions documented for ui-builder floor bump

References

Canonical Pattern A:

  • examples/basic-react-app/src/components/AddressFieldDemo.tsx
  • examples/basic-react-app/src/components/ENSResolutionDemo.tsx
  • packages/renderer/src/components/AddressBookWidget/AddAliasDialog.tsx
  • packages/renderer/src/components/ResolvedAddressFieldPreviewWithNameResolution.tsx
  • packages/components/src/components/AddressFieldWithResolvedPreview.tsx (verify path)

Current simple path:

  • packages/renderer/src/components/fieldRegistry.ts'blockchain-address': AddressField
  • packages/renderer/src/components/TransactionForm.tsx
  • packages/renderer/src/components/DynamicFormField.tsx

Name resolution hooks:

  • packages/react/src/hooks/nameResolution/useRuntimeNameResolver.ts

Downstream:

  • OpenZeppelin/ui-builder#403 — builder UI, BuilderFormConfig, export @@FORM_SCHEMA_JSON@@
  • OpenZeppelin/ui-builder#401 — ENS rollout (runtime creation options, dependency floors)

Open questions

  1. Should rich require resolveAddress, or is forward-only + address card acceptable when reverse is missing?
  2. Export BlockchainAddressDynamicField from @openzeppelin/ui-renderer public API so ui-builder can dedupe BlockchainAddressFieldWithRichPreview?
  3. Context vs explicit prop drilling for nested DynamicFormField — prefer context to avoid signature churn on every recursive call?

Release notes (draft)

Feature: RenderFormSchema.ensAddressPreview ('rich' | 'simple') controls ENS feedback UX for blockchain-address fields in TransactionForm. Default omitted → 'simple' (no breaking change).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/renderer/src/components/TransactionForm.tsx, DynamicFormField.tsx, and fieldRegistry.ts, then compare the rich-preview patterns in the listed examples and renderer components. Trace recursive fields and name-resolution hooks, run the existing TransactionForm tests, and verify that rich, simple/default, nested, and missing-capability cases meet the acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.