Skip to content

# FRONTEND-14: Typed, Discriminated-Union Transaction State Machine in useTransaction #441

Description

@orunganiekan

Points: 200
Labels: frontend, typescript, hooks, state-management

Background

useTransaction tracks status with a plain "idle" | "pending" | "success" | "failed" string and separate hash / error fields.

Consumers must manually cross-reference these fields to determine the full state, making it easy to render stale error messages alongside a new pending status. On the Dashboard, both cancelTx and ppuTx use this hook independently with no shared reset logic.

Task

Refactor useTransaction to use a discriminated-union state type:

type TxState =
  | { status: "idle" }
  | { status: "pending" }
  | { status: "success"; hash: string }
  | { status: "failed"; error: string };

Expose state: TxState alongside the existing spread fields for backward compatibility during migration.

Add a reset() function that returns the machine to:

{ status: "idle" }

Update Dashboard.tsx to call reset() when a modal is dismissed so stale error/hash state does not bleed into the next action.

Keep POLL_INTERVAL_MS and POLL_TIMEOUT_MS configurable via optional constructor arguments.

Key Files

  • frontend/src/hooks/useTransaction.ts
  • frontend/src/components/Dashboard.tsx
  • frontend/src/__tests__/useTransaction.test.ts (new)

Acceptance Criteria

  • state.status === "success" is the only state where state.hash is accessible without a type-cast; TypeScript must enforce this at compile time (npm run typecheck passes).
  • reset() transitions from any state back to idle.
  • Dashboard calls reset() on ConfirmModal cancel and on DailyLimitModal close.
  • Existing status, hash, error fields remain on the return type (derived from state) so no other consumer breaks.
  • Tests cover all four state transitions and the reset() path.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions