Skip to content

App shell, flexible withdraw, locked plan form, upgrade - #469

Merged
nayt9 merged 1 commit into
stowp:mainfrom
Diyaq:handsoff/issues-110-116-118-467-5d64ac
Oct 18, 2026
Merged

nayt9 merged 1 commit into
stowp:mainfrom
Diyaq:handsoff/issues-110-116-118-467-5d64ac

Conversation

@Diyaq

@Diyaq Diyaq commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

#110 — Authenticated app shell/layout

  • New frontend/src/components/app/Sidebar.tsx: the main app navigation (Dashboard, Goals, Locked savings, Groups, Deposit & withdraw, Referrals, Settings). It marks the current section with aria-current="page" and has a Sign out button.
  • frontend/src/app/(app)/layout.tsx now wraps every (app) screen in a shell:
    • On desktop, the sidebar is a sticky column.
    • On mobile, it opens as a drawer from a menu button in the topbar.
    • The topbar shows the signed-in email and an AddressBadge for the wallet.
  • The existing auth guard is kept. Signed-out visitors are now redirected to /login?returnTo=<current path>, which the login page already reads, so they land back where they started.
  • Tests:
    • layout.test.tsx now expects the returnTo redirect and checks that several guarded routes (/dashboard, /savings/locked/new, /settings) redirect when logged out. It also checks that the shell (sidebar, banner, main) wraps the content when signed in.
    • New Sidebar.test.tsx covers the links, the active state and sign out.

#116 — Withdraw modal (flexible)

  • New frontend/src/hooks/useWithdraw.ts:
    • validateWithdrawAmount(amount, balance) blocks empty, non-numeric, zero, over-precise (more than 7 decimals) and over-balance amounts. This mirrors the vault's InsufficientBalance check.
    • useWithdraw() sends POST /api/savings/flexible/withdraw with { owner, amount }. The amount is in stroops and each request carries an Idempotency-Key, following the same pattern as useLockedTopUp. Status moves through idle, pending, success and error.
  • New frontend/src/components/savings/WithdrawModal.tsx:
    • Shows the available balance, with a "Max" button that fills the exact balance using string arithmetic (no float rounding).
    • Validates the amount inline, then shows a confirmation step.
    • Shows pending (button disabled, so no double submit), success (with the new balance) and error states.
    • Focus trap, Escape and backdrop close work the same way as DepositModal.
  • The dashboard gets a Withdraw quick action. It is capped at the flexible balance from the summary and refetches the summary after a successful withdrawal, so the balance cards update.
  • Tests: new WithdrawModal.test.tsx. It checks that over-balance and empty amounts are blocked without calling the API, the confirmation step, the pending state, the error state, and that success shows the updated balance and calls onWithdrawn with it.

#118 — Locked savings create screen

  • New frontend/src/hooks/useCreateLockedPlan.ts:
    • validateUnlockDate rejects a missing date, an invalid date, and any date that is not in the future, including today. This mirrors the contract's InvalidUnlockTime.
    • useCreateLockedPlan() sends POST /api/savings/locked with { owner, amount (stroops), unlock_at (ISO) } and an Idempotency-Key.
  • New frontend/src/components/savings/LockedPlanForm.tsx:
    • Takes an amount and an unlock date. The date input's min is tomorrow.
    • Shows a confirmation step that warns the funds can't be withdrawn early, and re-checks the date before sending.
    • Shows pending, success and error states. The success state has a "View plan" button.
  • New page frontend/src/app/(app)/savings/locked/new/page.tsx. It uses the session address as the plan owner and goes to /savings/locked/[id] after the plan is created.
  • Tests:
    • LockedPlanForm.test.tsx checks that past dates and today are rejected without an API call, that required fields are enforced, that valid input submits the right payload after confirmation, and the pending and error states.
    • The page test covers navigation to the new plan.

Note: the backend doesn't expose the flexible-withdraw or locked-create routes yet. The hooks call the paths that match the existing /api/savings/locked/:id/top-up convention.

#467 — Upgrade safety checklist

  • New contracts/UPGRADE_CHECKLIST.md, written for Soroban. Each section has checkboxes and concrete steps to verify them:
    • Storage layout compatibility: DataKey variants and payloads, the fields of stored structs, storage durability, id counters, TTLs, and how to run migrations. Verification is a testnet rehearsal: write state with the old Wasm, upgrade, and read it back.
    • Function selector collision: Soroban dispatches by exported name, so the checks cover renamed or removed entrypoints, changed arguments or return types, reused names, Error codes being renumbered, and event schema changes. Verification diffs the two Wasms with stellar contract inspect.
    • Initialization validation: the AlreadyInitialized guard stays in place, no new public re-initializer is added, new config values have safe defaults, and admin / token keep their values after the upgrade.
    • Rollout: check the Wasm hash, rehearse on testnet, watch the upgraded event and the indexer, and keep a rollback plan.
  • The upgrade entry in contracts/savings-vault/README.md now links to the checklist.

Closes #110
Closes #116
Closes #118
Closes #467

@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@Diyaq Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@vercel

vercel Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
stow Error Error Oct 17, 2026 10:03pm UTC

@nayt9
nayt9 merged commit 0342559 into stowp:main Oct 18, 2026
1 of 10 checks passed

This branch had an error being deployed

1 failed deployment
Preview — cfafb0c4 Deployed Oct 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants