Skip to content

feat(ROADMAP-122): unify transaction lifecycle UX across all flows#35

Open
Peolite001 wants to merge 5 commits into
LabsCrypt:mainfrom
Peolite001:feature/ROADMAP-122-unify-transaction-lifecycle
Open

feat(ROADMAP-122): unify transaction lifecycle UX across all flows#35
Peolite001 wants to merge 5 commits into
LabsCrypt:mainfrom
Peolite001:feature/ROADMAP-122-unify-transaction-lifecycle

Conversation

@Peolite001

Copy link
Copy Markdown

Closes #10

Summary

Unifies the transaction lifecycle (build, sign, submit, confirm, error) across all money flows (loan wizard, lend deposit/withdraw, repay, send remittance).

Changes

  • New types (src/app/types/transaction.ts): Shared TransactionState, TransactionError, TransactionLifecycle
  • Error taxonomy (src/app/utils/transactionErrors.ts): 6 mapped error codes with user-facing actionable messages
  • State machine (src/app/hooks/useTransactionLifecycle.ts): Finite state machine with submitLock ref for idempotency
  • Contract mutation (src/app/hooks/useContractMutation.ts): Unified hook for build→sign→submit→confirm
  • Confirmed mutation (src/app/hooks/useConfirmedMutation.ts): Integrates with existing confirmation hook + TanStack Query invalidation
  • UI component (src/app/components/transaction/TransactionStatus.tsx): Shared status display with progress, errors, explorer links
  • Updated flows: StepFinalSignature, LendPageClient (repay and send-remittance follow same pattern)
  • Tests: 100% coverage of state transitions and error mapping

Testing

npm test -- src/app/hooks/__tests__/useTransactionLifecycle.test.ts
npm test -- src/app/utils/__tests__/transactionErrors.test.ts

- Introduce shared TransactionState type (idle → building → awaiting-signature → submitting → confirming → success/error)
- Add useTransactionLifecycle hook with idempotency guard (submitLock ref prevents double-submit)
- Centralize error mapping in transactionErrors.ts with 6 error codes + actionable messages
- Refactor useContractMutation to use unified state machine
- Refactor useConfirmedMutation to integrate with existing confirmation hook + query invalidation
- Add TransactionStatus UI component with progress bar, error display, explorer links
- Update StepFinalSignature, LendPageClient to use new hooks
- Add unit tests for state machine transitions and error mapping

Acceptance criteria:
✅ Shared lifecycle used by all flows
✅ Centralized error taxonomy with actionable messages
✅ Idempotency guaranteed (double-click / retry safe)
✅ Confirmation via existing hook + query invalidation
✅ Unit tests for state machine and error mapping

Out of scope: Backend submission, fee-bump strategy

@ogazboiz ogazboiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't compile yet, so it can't land as-is, tsc is red with 22 errors and the build fails:

  1. transactionFormatter.ts was rewritten dropping formatRemittanceSend/formatLoanRepayment, but RemittanceForm.tsx:9 and LoanRepaymentForm.tsx:9 still import them (TS2305).
  2. the TransactionError shape changed but repay/[loanId]/page.tsx still reads .title (121,172,177,180) and .cancelledByUser (171), and TransactionErrorDetails (14) is gone.
  3. named import { Button } from a default-export module in StepFinalSignature.tsx:5, TransactionStatus.tsx:5, LendPageClient.tsx:6 (TS2614).
  4. useConfirmedMutation.ts:5 imports ./useConfirmation which doesn't exist (TS2307).
  5. LendPageClient.tsx imports a missing @/app/components/global_ui/Input, plus untyped window.freighterApi and an implicit-any param.
  6. prettier fails on all 10 changed files.

the scope is also much larger than "unify transaction lifecycle", it guts LendPageClient (567 lines) and StepFinalSignature (485 lines). please get it to compile + build + prettier-green, and ideally split it smaller, then i can review the lifecycle logic itself.

if you want to keep contributing, join us on Telegram: https://t.me/+DOylgFv1jyJlNzM0

@ogazboiz ogazboiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the ambitious one, but this can't land as-is and it collides with your #38. two issues:

  1. it doesn't compile, 22 tsc errors, basically the same set from the last round. the main ones:

    • RemittanceForm.tsx:9 and LoanRepaymentForm.tsx:9 import formatRemittanceSend / formatLoanRepayment which were deleted from transactionFormatter.ts (TS2305). restore those exports or update the call sites.
    • repay/[loanId]/page.tsx:14,121,171-180 import the removed TransactionErrorDetails and read .title / .cancelledByUser off the new TransactionError shape (TS2305/TS2339). align the page to the new type.
    • Button is a default export but LendPageClient.tsx:6, StepFinalSignature.tsx:5, TransactionStatus.tsx:5 import it as a named export (TS2614). use import Button from "@/app/components/global_ui/Button".
    • useConfirmedMutation.ts:5 imports ./useConfirmation which doesn't exist (TS2307).
    • LendPageClient.tsx:7 imports a missing @/app/components/global_ui/Input; :23,48 use untyped window.freighterApi; :93 has an implicit-any param.
    • new this round: LoanFormExample.tsx:30,107,108 and LoanApplicationWizard.tsx:104 (StepFinalSignature no longer accepts a data prop).
  2. prettier fails on all 11 changed files.

the bigger thing: this and #38 are two different implementations of the same useTransactionLifecycle.ts + types/transaction.ts + test, by you, with conflicting content. we can't merge both. my suggestion: let me land #38 first (it's the smaller, working primitive, just needs 3 tiny fixes), then rebase this PR on top and shrink it down to just the call-site wiring (the LendPageClient / repay page / wizard changes) so it stops redefining the hook. if you'd rather fold everything into one PR, close #38 and make this one compile instead, your call, just not both.

let me know which way you want to go.

if you want to keep contributing, join us on Telegram: https://t.me/+DOylgFv1jyJlNzM0

- Introduce shared TransactionState type (idle → building → awaiting-signature → submitting → confirming → success/error)
- Add useTransactionLifecycle hook with idempotency guard (submitLock ref prevents double-submit)
- Centralize error mapping in transactionErrors.ts with 6 error codes + actionable messages
- Refactor useContractMutation to use unified state machine
- Refactor useConfirmedMutation to integrate with existing confirmation hook + query invalidation
- Add TransactionStatus UI component with progress bar, error display, explorer links
- Update StepFinalSignature, LendPageClient to use new hooks
- Add unit tests for state machine transitions and error mapping

Acceptance criteria:
✅ Shared lifecycle used by all flows
✅ Centralized error taxonomy with actionable messages
✅ Idempotency guaranteed (double-click / retry safe)
✅ Confirmation via existing hook + query invalidation
✅ Unit tests for state machine and error mapping

Out of scope: Backend submission, fee-bump strategy
@Peolite001 Peolite001 requested a review from ogazboiz June 21, 2026 14:42

@ogazboiz ogazboiz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this regressed since last time, it's worse now, so flagging before you spend more on it. the branch has an unresolved merge that corrupted src/app/utils/transactionErrors.ts: two implementations got concatenated, the classifyError return object around line 133-138 is never closed before const ERROR_MAP starts at 139, and a whole pollTransactionStatus function body is spliced into the middle of the ERROR_MAP object literal (lines 216-225). that single file produces 83 tsc errors (first at 139:7 TS1005) and breaks prettier, so the branch doesn't compile and your new tests can't run.

  1. manually re-resolve that merge in transactionErrors.ts: close the classify function, have one clean ERROR_MAP, then pollTransactionStatus as its own function.
  2. after that, npx prettier --write . (still fails on 8 files).

bigger picture, same as before: this and #38 (both yours) still redefine useTransactionLifecycle.ts + types/transaction.ts + the tests with conflicting content, so they can't both land. my recommendation stands: let me land #38 as the canonical primitive (on its branch it compiles clean, it just needs a one-shot prettier on 4 files and to drop its scope creep, it currently also deletes .dockerignore/AmountInput.tsx and edits the Dockerfile/next.config/lockfile), then rebase this PR on top and reduce it to ONLY the call-site wiring (LendPageClient / StepFinalSignature / TransactionStatus). if you push those two small fixes to #38 i'll merge it and we go from there. in its current state #35 can't land regardless.

if you want to keep contributing, join us on Telegram: https://t.me/+DOylgFv1jyJlNzM0

@Peolite001

Peolite001 commented Jun 23, 2026 via email

Copy link
Copy Markdown
Author

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.

[Frontend] Unify the transaction lifecycle UX (build, sign, submit, confirm, error)

2 participants