mirror of
https://github.com/hanzoai/billing.git
synced 2026-10-30 18:46:54 +00:00
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.
52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
'use client'
|
|
|
|
import * as React from 'react'
|
|
import { WagmiProvider } from 'wagmi'
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
import { RainbowKitProvider, darkTheme } from '@rainbow-me/rainbowkit'
|
|
import '@rainbow-me/rainbowkit/styles.css'
|
|
|
|
import { getWalletConfig } from './wallet-config'
|
|
import { WalletReadyProvider } from './wallet-ready'
|
|
|
|
const queryClient = new QueryClient()
|
|
|
|
export default function WalletProviders({ children }: { children: React.ReactNode }) {
|
|
// Resolve the wallet config lazily. The exported `walletConfig` constant is
|
|
// permanently null (eager init was disabled to avoid RPC CORS on load), so
|
|
// using it here meant WagmiProvider never mounted even when a WalletConnect
|
|
// projectId WAS configured — and any wagmi hook (CryptoForm) then threw
|
|
// `WagmiProviderNotFoundError`. getWalletConfig() builds the config when a
|
|
// projectId is present and returns null otherwise.
|
|
const walletConfig = getWalletConfig()
|
|
|
|
// No projectId → skip wallet providers and render children directly. The
|
|
// crypto payment UI is gated on the same check, so nothing calls wagmi hooks.
|
|
if (!walletConfig) {
|
|
return (
|
|
<QueryClientProvider client={queryClient}>
|
|
{children}
|
|
</QueryClientProvider>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<WagmiProvider config={walletConfig}>
|
|
<QueryClientProvider client={queryClient}>
|
|
<RainbowKitProvider
|
|
theme={darkTheme({
|
|
accentColor: '#ffffff',
|
|
accentColorForeground: '#0a0a0f',
|
|
borderRadius: 'medium',
|
|
overlayBlur: 'small',
|
|
})}
|
|
>
|
|
{/* Signal to the crypto UI that wagmi hooks / ConnectButton are safe to
|
|
render — they mount ONLY inside this provider subtree. */}
|
|
<WalletReadyProvider value={true}>{children}</WalletReadyProvider>
|
|
</RainbowKitProvider>
|
|
</QueryClientProvider>
|
|
</WagmiProvider>
|
|
)
|
|
}
|