Skip to content

Split the transaction modal's copy out of the component and map contract errors by name #415

Closed

Description

@luchobonatti

User story / Problem statement

Currently, app/src/components/vault/TransactionModal.tsx is 1,739 lines, but the modal component itself is about 120 (:1617-1739 on main; the file is 2,158 lines on feedback). The rest is copy written by hand per action:

  • 13 *ContractErrorReason functions (:185-398) that switch on raw contract error numbers (6007, 6039, 304…). The generated clients already export these codes with their names (VaultError in app-lib/clients/async_vault, e.g. 6007: {message:"InvalidAmount"}), straight from the contract's #[contracterror] enum.
  • 15 describe*Status functions (:460-1003) that each repeat the same six-case switch over TransactionStatus (idle, preparing, awaiting-signature, submitted, confirmed, failed); only the strings differ.
  • About 400 lines of admin copy and a dispatcher (:1004-1508).

This is a problem because adding an action means copying about 40 lines of switch, and a renumbered contract error leaves the UI showing the wrong message without any test noticing.

Expected outcome

Each action's copy is a small object, one generic function turns a TransactionStatus into heading and body, and contract errors are matched by their generated name instead of their number. The modal file holds the modal; the copy lives in its own files, grouped by investor, cycle and admin actions. What the user sees does not change.

Acceptance criteria

  • Contract errors reach the UI by name (InvalidAmount), resolved at runtime from the contract spec the generated clients already carry (spec.errorCases()), across the vault, share token and identity verifier. No numeric error code appears in app code or in a hand-written table.
  • A single describeStatus handles the six TransactionStatus cases for every action; per-action copy is data, not a switch.
  • The copy lives outside TransactionModal.tsx, split by investor, cycle and admin actions.
  • TransactionModal.tsx is under 300 lines.
  • Every heading, body and error message the user sees is unchanged: TransactionModal.test.tsx passes without edits to its assertions.
  • ADMIN_VERBS, ShareLink and the exported modal action types keep their current exports for SignPage, sign.ts and the admin sections.

Alternatives considered

  • Leave it as is: every new action keeps growing the file by about 40 lines.
  • An i18n library for the copy: no translation need today; it adds a dependency for what plain objects do.

Technical notes

  • app-lib/clients is generated and gitignored, and npm run test in CI swaps every client for the stub in vitest.clients.ts. Importing a generated error map would be undefined there, so the name is resolved from the client's spec where the code is parsed today (parseErrorCode in app-lib/readContract.ts), and failures carry the name instead of the number. Tests build failures by name and need no clients.
  • A nested call can fail with another contract's code (the vault surfaces the share token's 304), so resolution looks across the specs of every contract involved.
  • TransactionFailure is shared by every transaction hook; changing it from a code to a name touches those hooks and their tests.
  • The total line count drops (estimate ~1,740 → ~900 across four files) but the copy text itself stays; the gain is that the structure stops repeating.
  • UI copy only: no contract, hook or transaction-flow changes.

Activity

  1. luchobonatti commented on Nov 3, 2026

    @luchobonatti
    MemberAuthor

    Closed by #427, merged into feedback.

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