Skip to content

feat: Refactor components#337

Open
LautaroPetaccio wants to merge 1 commit intomainfrom
feat/refactor-components
Open

feat: Refactor components#337
LautaroPetaccio wants to merge 1 commit intomainfrom
feat/refactor-components

Conversation

@LautaroPetaccio
Copy link
Copy Markdown
Collaborator

Why

The auth codebase had accumulated significant duplication across components, hooks, and utilities. Identical logic lived in multiple files — meaning bug fixes or behavior changes had to be applied in 2-3 places, with divergence risk on each. This PR consolidates repeated patterns into shared abstractions, reducing maintenance burden and making the codebase easier to reason about.

How

Duplicate hook file removal

src/shared/connection/hook.ts and hooks.ts were byte-for-byte identical implementations of useCurrentConnectionData. Deleted hook.ts and pointed the two consumers (useTrackReferral, useAuthFlow) at hooks.ts. The barrel index.ts already re-exported from hooks.ts, so all other consumers were unaffected.

Dead styled-component cleanup (Transfer.styled.ts)

Eight styled components (ButtonsContainer, CancelButton, ConfirmButton, LoadingContainer, LoadingText, ProgressContainer, ProgressSpinner, ProgressTrack) were defined in Transfer.styled.ts but never imported — each had been superseded by component-specific .styled.ts files. Removed them to eliminate confusion about which definition is canonical.

Auth client error parsing and recovery flow (src/shared/auth/utils.ts)

The HTTP and WebSocket auth clients contained identical error-mapping logic (string matching → typed error classes) and identical recovery validation (sender mismatch, expiration check, method-based analytics tracking, error reporting). Extracted four functions into utils.ts:

  • throwAuthServerError — maps error strings to RequestFulfilledError, RequestNotFoundError, ExpiredRequestError, IpValidationError, or generic Error
  • validateRecoverResponse — checks sender mismatch and expiration
  • trackRecoverMethod — fires the correct analytics event based on dcl_personal_sign vs eth_sendTransaction
  • handleRecoverError — reports to Sentry while excluding fulfilled requests (expected state)

Both httpClient.ts and wsClient.ts now call these instead of duplicating the logic. The WebSocket client's request() method already parsed the response inline, so throwAuthServerError replaced the if/else chain directly.

State parameter decoding (src/shared/utils/stateParameter.ts)

Three separate functions (extractRedirectToFromSearchParameters, extractReferrerFromSearchParameters, extractMobileDataFromState) all performed the same atob → JSON.parse → JSON.parse(customData) decoding on the OAuth state URL parameter. Extracted extractFromStateParameter<T>(searchParams, field) and extractMultipleFromStateParameter as generic utilities. The three call sites in locations.ts and mobile.ts now use these instead of inlining the decode logic.

Setup page shared hooks

SetupPage and AvatarSetupPage shared ~60% of their logic but implemented it independently. Extracted three hooks:

  • useRequestIdFromRedirect — both pages parsed the redirectTo query param with the same regex (/^\/?auth\/requests\/([a-zA-Z0-9-]+)$/) to extract a request ID. Now a single useMemo-based hook.
  • useSetupFormValidation(name, email, agree) — both pages validated username (empty, length, spaces, special chars), email (contains @), and terms checkbox with identical useMemo blocks. Now returns { nameError, emailError, agreeError }.
  • usePostSignupActions(referrer) — both pages duplicated referral tracking on init (POST) and deploy (PATCH), plus newsletter subscription with silent error handling. Now exposes trackReferralOnInit, trackReferralOnDeploy, and subscribeEmail.

Both pages were updated to use these hooks, removing ~80 lines of duplicated validation/tracking code.

Transfer view component consolidation

The three transfer view components (TransferConfirmView, TransferCanceledView, TransferCompletedView) all extracted the same derived state (isTip, recipientAvatar) and performed the same type assertions (transferData as MANATransferData / NFTTransferData) 15+ times across the three files.

Created useTransferViewData(props) which returns { isTip, recipientAvatar, tipData, giftData, transferData } — the hook narrows the discriminated union once, so view components access tipData!.sceneName instead of (transferData as MANATransferData).sceneName throughout.

Also consolidated TransferCanceledViewProps and TransferCompletedViewProps (which were identical types) into a shared BaseTransferViewProps, with TransferConfirmViewProps extending it with isLoading/onApprove/onDeny.

ConnectionOptions type consolidation

The ConnectionOptions type ({ primary, secondary?, extraOptions? }) was defined identically in useWalletOptions.ts, targetConfig.ts, and inline in Connection.types.ts. Moved the canonical definition to Connection.types.ts and updated the other two files to import it.

Page initialization hook (useRequireAuth)

Five+ pages repeated the same initialization pattern: destructure useCurrentConnectionData(), destructure useContext(FeatureFlagsContext), then guard with if (isConnecting || !initializedFlags) return. Created useRequireAuth() which combines both and returns { isReady, isAuthenticated, account, identity, provider, flags, variants, ... }. Applied to SetupPage and AvatarSetupPage — the other pages have more specialized initialization patterns that don't benefit as cleanly from the abstraction.

Shared error display components (src/components/shared/ErrorDisplay.styled.ts)

ErrorContainer, ErrorText, and WarningIcon were defined with identical styles in AvatarSetupPage.styled.ts and CharacterCounter.styled.ts. ErrorMessageIcon was separately defined in RecoverError.styled.ts. Consolidated all four into a single shared file. The consuming styled files now re-export from the shared source.

Shared gradient background constants (src/components/shared/GradientBackground.styled.ts)

LoginPage.styled.ts and MobileAuthPage.styled.ts both defined a &::before pseudo-element with identical positioning (position: fixed, width: 100%, height: 350%, top: -100%, transform: rotate(180deg)) and similar gradient values. Extracted the shared pseudo-element base and the four gradient variants (desktop linear, mobile linear, desktop radial, mobile radial) as named constants. Both pages now compose these instead of duplicating the positioning styles.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 8, 2026

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

Project Deployment Actions Updated (UTC)
auth Ready Ready Preview, Comment Mar 8, 2026 1:12am

Request Review

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.

1 participant