Skip to content

Show maintenance windows in the dashboard and pause transfers - #1398

Merged
ebma merged 6 commits into
stagingfrom
feat/dashboard-maintenance-mode
Oct 5, 2026
Merged

ebma merged 6 commits into
stagingfrom
feat/dashboard-maintenance-mode

Conversation

@ebma

@ebma ebma commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Why

The dashboard never read /v1/maintenance/status. During a scheduled maintenance window the API rejects quote creation and ramp register/update/start with a 503 (rejectDuringActiveMaintenance), so dashboard senders only found out through failing requests. The widget shows a banner and disables its submit buttons in that case; the dashboard now does the same. This is a companion to #1396, which restores the widget's banner.

Change

  • MaintenanceService.getStatus and a useActiveMaintenance() hook built on React Query. The hook refetches every 5 minutes and when the tab regains focus, and returns the active window or null. React Query shares the request across all components that use the hook.

  • MaintenanceBanner in the app shell's sticky header, using the existing bg-warning token. It shows the operator's title and message plus the window's end time, on every authenticated page.

  • These buttons are disabled while a window is active: offramp Send ≈ …, onramp Continue to payment, and I have made the payment (which calls /ramp/start).

  • Follow-ups from the /vortex-review pass:

    • The status refetches just after an active window's end_datetime (pure maintenanceRefetchInterval), so actions unlock about 15 s after the API does instead of up to 5 minutes later.
    • Open payment instructions explain that confirming is paused. If the window outlasts the ramp's 15-minute start deadline, the details are hidden, so nobody pays into a ramp that can no longer start.
    • signUserTransactions re-checks the status right before the wallet signs an offramp. A window that opened since the last poll stops the transfer before funds move; if the check itself fails, the API guard still applies.
  • Product and testing docs updated (docs/product-dashboard.md, docs/operations-testing.md).

  • While a window is active, quote errors on the pay-in, pay-out and Get-a-quote pages say "Quotes are paused for scheduled maintenance. Try again once it ends." instead of the generic "try another amount or token" text. Quote requests still go out; the API rejects them.

Tests

  • e2e/maintenance.spec.ts covers four cases: an active window disables onramp Continue to payment, a window that starts while payment instructions are open disables I have made the payment once the tab regains focus, an active window disables offramp Send, and quote errors on all three quote pages show the maintenance message when the API answers with its maintenance 503. Each case fails without its change.
  • Bun unit tests (PR-blocking): useActiveMaintenance.test.ts (refetch interval around a window's end) and transfer.actors.test.ts (pre-signing check: active window stops before the wallet, inactive or failed check proceeds). The actors test fails without the check.
  • Two e2e cases open a window while payment instructions are showing: one ending before the ramp expires (notice shown, confirm disabled) and one outlasting it (details hidden). Both fail without the component change.
  • The e2e mock backend serves an inactive window by default, so every existing spec's unmatchedRequests check keeps passing.

Verification

  • apps/dashboard: bun run typecheck clean, bun run test 169/169, full Playwright suite 78/78
  • Biome clean
  • The mid-flow e2e case was flaky at first: the status refetch fired when the instructions mounted could still be in flight with the old answer. I reproduced it 3/3 by delaying the mock response by 1.5 s, and the spec now retries the tab-focus refetch. It passes with the delay in place.

ebma added 2 commits October 5, 2026 10:51
The dashboard never read /v1/maintenance/status, so senders only learned about a window from 503s on quote and ramp calls. The e2e mock serves an inactive window by default so every spec's unmatched-request check keeps passing.
The API rejects quote creation and ramp register/update/start during a window, so starting a transfer or confirming an onramp payment then can only fail. Disable those buttons while the banner is up, matching the widget.
@netlify

netlify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for vrtx-dashboard ready!

Name Link
🔨 Latest commit fe2df7b
🔍 Latest deploy log https://app.netlify.com/projects/vrtx-dashboard/deploys/6ac373ce39c7790008c5a1fa
😎 Deploy Preview https://deploy-preview-1398--vrtx-dashboard.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for vortexfi canceled.

Name Link
🔨 Latest commit fe2df7b
🔍 Latest deploy log https://app.netlify.com/projects/vortexfi/deploys/6ac373cef65b6000083e8452

@netlify

netlify Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for vortex-sandbox ready!

Name Link
🔨 Latest commit fe2df7b
🔍 Latest deploy log https://app.netlify.com/projects/vortex-sandbox/deploys/6ac373ce39c7790008c5a1f8
😎 Deploy Preview https://deploy-preview-1398--vortex-sandbox.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

ebma added 4 commits October 5, 2026 11:13
The generic quote errors told senders to try another amount or token, which cannot help while the API's maintenance guard rejects every quote.
The API stops rejecting at end_datetime, but the dashboard kept the banner and disabled actions until the next 5-minute poll.
A window opening between the last poll and the wallet broadcast 503s the final /ramp/update after funds moved, with no retry for offramps. Re-check the status right before signing so the transfer fails while nothing has left the wallet.
…nance

Only the confirm button was disabled, so senders could still pay into a ramp whose 15-minute start deadline passes before the window ends. Explain the pause, and hide the details when the window outlasts the ramp.
@ebma
ebma merged commit 8c8d2a7 into staging Oct 5, 2026
7 of 8 checks passed
@ebma
ebma deleted the feat/dashboard-maintenance-mode branch October 5, 2026 10:32
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