Files
billing/lib/wallet-ready.tsx
zeekay a3dbeb6845 fix(billing): contain crypto-tab crash + show claimed starter credit
BUG 1 — the crypto/wallet flow crashed the whole app on refresh with
"DialogClose must be used within Dialog" (a Radix dialog error surfaced
via @hanzo/ui, thrown when the wallet connector rendered before its
provider mounted — the same race class as the earlier
WagmiProviderNotFoundError). Two robust, in-app guards:

- Gate the Crypto payment tab on a new useWalletReady() context that is
  true ONLY inside the mounted WagmiProvider/RainbowKitProvider subtree
  (lib/wallet-ready.tsx, set by wallet-providers.tsx). Replaces the
  effect-based getWalletConfig() probe that could win the race against
  the still-lazy provider, so the connector never renders unprovided.
- Wrap the crypto tab (payment-manager) and the top-up page's crypto +
  HUSD tabs in a reusable client ErrorBoundary
  (lib/components/error-boundary.tsx), so any wallet-lib hiccup degrades
  to an honest inline message instead of a whole-page "Something went
  wrong".

BUG 2 — a claimed $5 starter credit showed as un-claimed (the "Claim $5
Starter Credit" button persisted). Commerce records the starter credit
as a Deposit transaction tagged "starter-credit" (deliberately NOT a
credit-grant), so getCreditGrants() is empty and billing-shell
synthesizes a grant from the transaction — but named it after the
transaction's freeform notes ("Welcome credit: $100.00 USD ..."), which
don't contain "starter". The credits UI keys "claimed" off
name.includes('starter'), so it never matched. Name the synthesized
grant "Starter Credit" (the starter-credit tag is the source of truth)
and carry the real on-chain expiry, so the claimed credit shows with its
real balance.
2026-07-01 13:25:52 -07:00

27 lines
1.1 KiB
TypeScript

'use client'
import * as React from 'react'
/**
* Signals whether the wagmi + RainbowKit providers are actually MOUNTED.
*
* This is intentionally a tiny, dependency-free module (no wagmi/RainbowKit
* imports) so it can be consumed by the crypto UI WITHOUT eagerly pulling the
* heavy wallet bundle — `wallet-providers.tsx` is React.lazy'd, and importing a
* named export from it would defeat that. `wallet-providers.tsx` sets this to
* `true` only inside the mounted `WagmiProvider`/`RainbowKitProvider` subtree.
*
* Consumers (e.g. the Crypto payment tab) gate their wagmi hooks / RainbowKit
* `ConnectButton` on this so they never render before the provider exists — the
* race that surfaced as `WagmiProviderNotFoundError` / a stray `DialogClose`
* crash on a refresh of the crypto flow.
*/
const WalletReadyContext = React.createContext(false)
export const WalletReadyProvider = WalletReadyContext.Provider
/** True only when the wagmi + RainbowKit providers are mounted above the caller. */
export function useWalletReady(): boolean {
return React.useContext(WalletReadyContext)
}