feat: on-chain refunds, plan_changed event, webhook circuit breaker, … - #717
Conversation
…chart tz fix Implements four issues: - Contract: add admin-only refund_payment(meter_id, amount, recipient, reason). Caps the refund to what that address actually paid (net of prior refunds) via new PayerPaid/PayerRefunded tracking, decrements the meter balance and the admin's tracked provider revenue so refunded funds can't also be withdrawn, deactivates the meter if its balance hits zero, and emits a pmt_rfnd event carrying the reason for an audit trail. Adds set_refund_limit() to cap total refunds per rolling 24h window (0 = unlimited) to guard against balance-drainage bursts. - Contract: make_payment now emits a plan_chg event whenever a payment switches a meter's plan (e.g. Daily -> Weekly), so off-chain services can track plan migrations. - Backend: the webhook retry path already had the requested exponential backoff (1s/2s/4s/8s/16s, max 5 retries); added the circuit breaker from the issue's follow-up (open after 10 consecutive failures, pause 5 minutes) and enriched the failure log line with httpStatus/attemptedAt. - Frontend: UsageChart displayed raw UTC timestamps with no timezone indicator because dashboard/user/page.tsx pre-formatted them with toLocaleDateString() before they reached the chart, discarding time-of-day. Now the raw ISO timestamp is passed through and UsageChart formats ticks/tooltips in the viewer's local timezone with an explicit indicator (e.g. "9:00 AM" tick / "Aug 24, 9:00 AM GMT+3" tooltip). Tests: added contract tests for refund_payment and plan_chg, a new backend integration suite for the circuit breaker, and new frontend unit tests for the timezone formatters. Verified against real suites (Rust toolchain unavailable in this sandbox, so the contract change is reviewed but not locally compiled); pre-existing unrelated failures on main were confirmed via baseline comparison and are unchanged by this branch.
|
@Olakunle567 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! 🚀 |
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed correctness/documentation/test-stability issues in the newly added frontend time formatting and contract refund event documentation that should be addressed before merge.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Implements four cross-cutting enhancements spanning the Soroban contract, backend webhook delivery, and frontend dashboard to support on-chain refunds, plan-change analytics events, resilient webhook delivery, and correct local-time usage chart rendering.
Changes:
- Contracts: add admin-only
refund_paymentwith per-payer paid/refunded tracking + rolling 24h refund limit; emitplan_chgon plan switch duringmake_payment. - Backend: add per-URL webhook circuit breaker (open after 10 consecutive failures; cooldown 5 minutes) and enrich failure logs.
- Frontend: pass raw ISO timestamps through to
UsageChartand format ticks/tooltips in the viewer’s local timezone with an explicit timezone indicator; add unit tests for the formatters.
File summaries
| File | Description |
|---|---|
| frontend/src/components/UsageChart.tsx | Adds local-time tick/tooltip formatting helpers and wires them into Recharts X-axis + tooltip. |
| frontend/src/app/dashboard/user/page.tsx | Stops pre-formatting timestamps so the chart can render accurate local times. |
| frontend/src/tests/UsageChart.test.tsx | Adds unit tests for timestamp/date detection and local-time formatting behavior. |
| contracts/solar_grid/src/lib.rs | Adds refund functionality + refund window limiting, tracks payer payments/refunds, and emits plan_chg on plan switches. |
| backend/src/lib/webhookRegistry.ts | Implements an in-memory circuit breaker for webhook delivery and adds observability helpers for tests. |
| backend/tests/webhookRegistry.integration.test.ts | Adds integration coverage for circuit breaker open/close/reset behavior. |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@Olakunle567 resolve conflicts |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
this pr closes #697
this pr closes #698
this pr closes #699
this pr closes #700
Implements four issues:
Contract: add admin-only refund_payment(meter_id, amount, recipient, reason). Caps the refund to what that address actually paid (net of prior refunds) via new PayerPaid/PayerRefunded tracking, decrements the meter balance and the admin's tracked provider revenue so refunded funds can't also be withdrawn, deactivates the meter if its balance hits zero, and emits a pmt_rfnd event carrying the reason for an audit trail. Adds set_refund_limit() to cap total refunds per rolling 24h window (0 = unlimited) to guard against balance-drainage bursts.
Contract: make_payment now emits a plan_chg event whenever a payment switches a meter's plan (e.g. Daily -> Weekly), so off-chain services can track plan migrations.
Backend: the webhook retry path already had the requested exponential backoff (1s/2s/4s/8s/16s, max 5 retries); added the circuit breaker from the issue's follow-up (open after 10 consecutive failures, pause 5 minutes) and enriched the failure log line with httpStatus/attemptedAt.
Frontend: UsageChart displayed raw UTC timestamps with no timezone indicator because dashboard/user/page.tsx pre-formatted them with toLocaleDateString() before they reached the chart, discarding time-of-day. Now the raw ISO timestamp is passed through and UsageChart formats ticks/tooltips in the viewer's local timezone with an explicit indicator (e.g. "9:00 AM" tick / "Aug 24, 9:00 AM GMT+3" tooltip).
Tests: added contract tests for refund_payment and plan_chg, a new backend integration suite for the circuit breaker, and new frontend unit tests for the timezone formatters. Verified against real suites (Rust toolchain unavailable in this sandbox, so the contract change is reviewed but not locally compiled); pre-existing unrelated failures on main were confirmed via baseline comparison and are unchanged by this branch.
Summary
Related Issue
Closes #
Type of Change
Changes Made
How to Test
Checklist
cargo build/npm run build)tsc --noEmit)cargo fmt) and lint-clean (cargo clippy -- -D warnings)mainbranch and is rebased on the latest upstreamScreenshots (if applicable)