@foundryprotocol/0gkit-wallet-react
React + wagmi v2 wallet integration for 0G:
ZeroGWalletProvider,useWallet,useConnect,useSwitchNetwork, andadaptWagmi.
What it does
Wraps wagmi v2 (injected + WalletConnect connectors) behind
a 0G-aware provider and three hooks. Every hook returns a Signer — the same
interface the 0G primitives accept — so you can pass useWallet().signer
directly to new Storage({ signer }) without any adapter code.
When to use it
- A Next.js / React app where the user connects their browser wallet (MetaMask, Rainbow, WalletConnect, etc.) and signs storage uploads or attestations.
- Anywhere you need a reactive
isConnected/addressalongside a 0G-typedSigner.
Where to use it
Client components only. All exports carry "use client" at the top of their
module — they use React hooks internally and cannot be imported in React Server
Components. The provider must live in a client component somewhere above the
tree; hooks only work below it.
Install
npm install @foundryprotocol/0gkit-wallet-react @foundryprotocol/0gkit-core
# Peer dependencies — must be installed separately:
npm install react viem wagmi @tanstack/react-query
API reference
ZeroGWalletProvider
interface ZeroGWalletConfig {
network: "galileo" | "aristotle" | "local";
connectors?: Array<"injected" | "walletConnect">; // default ["injected"]
walletConnectProjectId?: string; // required when "walletConnect" is listed
}
function ZeroGWalletProvider(props: {
config: ZeroGWalletConfig;
children: ReactNode;
queryClient?: QueryClient; // optional — a fresh one is created if omitted
}): JSX.Element;
Sets up a WagmiProvider + QueryClientProvider for the chosen 0G network.
The chain RPC is preset per network (galileo → https://evmrpc-testnet.0g.ai,
aristotle → https://evmrpc.0g.ai, local → http://127.0.0.1:8545).
useWallet()
interface UseWalletResult {
address: `0x${string}` | undefined;
isConnected: boolean;
signer: Signer | null; // null when no wallet is connected
disconnect: () => void;
}
function useWallet(): UseWalletResult;
The primary hook. Returns the connected address, connection state, a
Signer wrapping the wagmi account (ready to pass to 0G primitives), and a
disconnect callback.
useConnect()
interface UseConnectResult {
connect: (connectorId?: string) => Promise<unknown>;
connectors: readonly Connector[];
isPending: boolean;
error: Error | null;
reset: () => void;
}
function useConnect(): UseConnectResult;
Calls connect(connectorId) to trigger the connection flow for a specific
connector ("injected", "walletConnect", or a wagmi connector id). With
no argument, picks the first registered connector.
useSwitchNetwork()
interface UseSwitchNetworkResult {
switchNetwork: (chainId: number) => Promise<Chain>;
isPending: boolean;
error: Error | null;
}
function useSwitchNetwork(): UseSwitchNetworkResult;
Asks the wallet to switch to chainId. Useful when the user is on the wrong
network (e.g. they are on mainnet Ethereum but the app is on Galileo).
adaptWagmi(adapter) — low-level escape hatch
interface WagmiAccountAdapter {
address: `0x${string}` | undefined;
signMessageAsync: (args: { message: string }) => Promise<`0x${string}`>;
signTypedDataAsync: (args: SignTypedDataArgs) => Promise<`0x${string}`>;
sendTransactionAsync: (tx: SignableTx) => Promise<`0x${string}`>;
}
function adaptWagmi(adapter: WagmiAccountAdapter): Signer | null;
Converts raw wagmi hook results into a Signer. useWallet uses this
internally. Call it directly only when you need to compose your own wagmi setup
and want to reuse the Signer contract.
Examples
Root layout — add the provider
// app/layout.tsx (or pages/_app.tsx)
"use client";
import { ZeroGWalletProvider } from "@foundryprotocol/0gkit-wallet-react";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ZeroGWalletProvider config={{ network: "galileo" }}>
{children}
</ZeroGWalletProvider>
</body>
</html>
);
}
Next.js App Router:
RootLayoutis a Server Component by default. If you add"use client"to it you lose RSC streaming for the whole tree. Instead, extract the provider into its own file:
// app/providers.tsx
"use client";
import { ZeroGWalletProvider } from "@foundryprotocol/0gkit-wallet-react";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ZeroGWalletProvider config={{ network: "galileo" }}>
{children}
</ZeroGWalletProvider>
);
}
// app/layout.tsx — stays a Server Component
import { Providers } from "./providers";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
useWallet — read address and sign
"use client";
import { useWallet } from "@foundryprotocol/0gkit-wallet-react";
import { Storage } from "@foundryprotocol/0gkit-storage";
export function UploadButton({ data }: { data: Uint8Array }) {
const { address, isConnected, signer } = useWallet();
async function handleUpload() {
if (!signer) return;
// signer is a Signer — pass it directly to any 0G primitive
const storage = new Storage({ network: "galileo", signer });
const { root } = await storage.upload(data);
console.log("uploaded:", root);
}
if (!isConnected) return <p>Connect your wallet first.</p>;
return <button onClick={handleUpload}>Upload from {address}</button>;
}
useConnect — connect button
"use client";
import { useConnect } from "@foundryprotocol/0gkit-wallet-react";
export function ConnectButton() {
const { connect, connectors, isPending, error } = useConnect();
return (
<>
{connectors.map((c) => (
<button key={c.id} onClick={() => connect(c.id)} disabled={isPending}>
{isPending ? "Connecting…" : `Connect ${c.name}`}
</button>
))}
{error && <p style={{ color: "red" }}>{error.message}</p>}
</>
);
}
useSwitchNetwork — wrong-network banner
"use client";
import { useSwitchNetwork } from "@foundryprotocol/0gkit-wallet-react";
import { useChainId } from "wagmi";
const GALILEO_CHAIN_ID = 16602;
export function WrongNetworkBanner() {
const chainId = useChainId();
const { switchNetwork, isPending } = useSwitchNetwork();
if (chainId === GALILEO_CHAIN_ID) return null;
return (
<div>
Wrong network — please switch to 0G Galileo.
<button onClick={() => switchNetwork(GALILEO_CHAIN_ID)} disabled={isPending}>
Switch
</button>
</div>
);
}
RSC note
The "use client" boundary is baked into every module of this package.
Importing any export from @foundryprotocol/0gkit-wallet-react in a React
Server Component will cause a build error. Keep all wallet UI in client
components, and fetch data server-side (e.g. new Storage({ signer: await fromEnv() }))
from server actions or API routes using
@foundryprotocol/0gkit-wallet.
Related
wallet (Node loaders — use in server actions / scripts) ·
storage · compute ·
core (the Signer interface)
Exports
type UseConnectResulttype UseSwitchNetworkResulttype UseWalletResulttype WagmiAccountAdaptertype ZeroGConnectorIdtype ZeroGNetworktype ZeroGWalletConfig