Skip to content

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

Description

@pasevin

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:


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).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions