Repo context. accensa-app is the off-chain half of Accensa — the merchant back-office for x402 sellers on Stellar. Three workspace packages matter: apps/web (Next.js dashboard and the indexer at src/app/api/sync), packages/sdk (@accensa/sdk), and apps/demo-merchant. The Soroban contracts live in accensa-contracts.
🟢 Unblocked. Small, self-contained fix in one component.
Problem
components/refund-panel.tsx reads wallet status exactly once, in an effect with an empty dependency array:
useEffect(() => {
let live = true;
void readStatus().then((status) => {
if (live) setMerchant(status.kind === 'connected' ? status.address : null);
});
return () => { live = false; };
}, []);
If no wallet is connected at that moment, merchant stays null and the panel renders "Connect a Stellar wallet to issue refunds" permanently. A merchant who reads that message, connects Freighter, and comes back finds the same message — the panel never re-checks.
The only way out is to close the modal and reopen it, which is not signposted anywhere. The message tells the user exactly what to do and then ignores them doing it.
What to build
Re-read wallet status when it can have changed.
- Re-check on a trigger the user controls at minimum — a "Check again" affordance next to the connect prompt is the smallest honest fix.
- Prefer reacting to the wallet itself if practical. Look at what
lib/freighter.ts exposes; if connection state can be observed rather than polled, that is the better answer. Do not add a polling loop against the extension without saying why in the PR.
- Keep the existing
live guard. The unmount-safety pattern is correct and should survive the change.
Out of scope: initiating the wallet connection from inside the refund panel. Connecting is the login flow's job.
Acceptance criteria
Contact & Support
Problem
components/refund-panel.tsxreads wallet status exactly once, in an effect with an empty dependency array:If no wallet is connected at that moment,
merchantstaysnulland the panel renders "Connect a Stellar wallet to issue refunds" permanently. A merchant who reads that message, connects Freighter, and comes back finds the same message — the panel never re-checks.The only way out is to close the modal and reopen it, which is not signposted anywhere. The message tells the user exactly what to do and then ignores them doing it.
What to build
Re-read wallet status when it can have changed.
lib/freighter.tsexposes; if connection state can be observed rather than polled, that is the better answer. Do not add a polling loop against the extension without saying why in the PR.liveguard. The unmount-safety pattern is correct and should survive the change.Out of scope: initiating the wallet connection from inside the refund panel. Connecting is the login flow's job.
Acceptance criteria
pnpm lintpasses inapps/web.pnpm testpasses, including new tests covering this change.pnpm buildsucceeds forapps/web.Closes #<this issue>.Contact & Support
SUPPORT.md— contribution help, Wave process, and the full list of channels