Getting Started
This guide will walk you through setting up graz
in your React application, from installation to your first wallet connection.
What You'll Build
By the end of this guide, you'll have a React app that can:
- Connect to Cosmos wallets (Keplr, Leap, etc.)
- Display user account information
- Query balances
- Handle multi-chain connections
Prerequisites
- React
>=17
- Using function components and hooks - Node.js
>=14
- For package management - Basic knowledge of React and TypeScript
Step 1: Installation
Install graz
and its peer dependencies:
- npm
- yarn
- pnpm
# Install graz
npm install graz
# Install peer dependencies
npm install @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @cosmjs/stargate @cosmjs/encoding @tanstack/react-query
# Install graz
yarn add graz
# Install peer dependencies
yarn add @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @cosmjs/stargate @cosmjs/encoding @tanstack/react-query
# Install graz
pnpm add graz
# Install peer dependencies
pnpm add @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @cosmjs/stargate @cosmjs/encoding @tanstack/react-query
We keep CosmJS and React Query as peer dependencies to avoid version conflicts and reduce bundle size. This gives you control over which versions to use.
Step 2: Configure Chain Information
Create a chain configuration file. You can use the chain registry or define your own:
import { ChainInfo } from "@keplr-wallet/types";
export const cosmoshub: ChainInfo = {
chainId: "cosmoshub-4",
chainName: "Cosmos Hub",
rpc: "https://rpc.cosmos.network",
rest: "https://lcd.cosmos.network",
bip44: {
coinType: 118,
},
bech32Config: {
bech32PrefixAccAddr: "cosmos",
bech32PrefixAccPub: "cosmospub",
bech32PrefixValAddr: "cosmosvaloper",
bech32PrefixValPub: "cosmosvaloperpub",
bech32PrefixConsAddr: "cosmosvalcons",
bech32PrefixConsPub: "cosmosvalconspub",
},
currencies: [
{
coinDenom: "ATOM",
coinMinimalDenom: "uatom",
coinDecimals: 6,
},
],
feeCurrencies: [
{
coinDenom: "ATOM",
coinMinimalDenom: "uatom",
coinDecimals: 6,
gasPriceStep: {
low: 0.01,
average: 0.025,
high: 0.03,
},
},
],
stakeCurrency: {
coinDenom: "ATOM",
coinMinimalDenom: "uatom",
coinDecimals: 6,
},
};
Use the graz CLI to quickly generate chain configurations from the chain registry.
Step 3: Set Up Providers
Wrap your application with both QueryClientProvider
and GrazProvider
:
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { GrazProvider } from "graz";
import { cosmoshub } from "./config/chains";
// Create a query client instance
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<GrazProvider
grazOptions={{
chains: [cosmoshub],
}}
>
<YourApp />
</GrazProvider>
</QueryClientProvider>
);
}
Provider Options
Configure graz
behavior through grazOptions
:
<GrazProvider
grazOptions={{
chains: [cosmoshub, osmosis],
chainsConfig: {
"cosmoshub-4": {
gas: { price: "0.025", denom: "uatom" },
rpcHeaders: { "X-Custom-Header": "value" },
},
},
defaultWalletType: WalletType.KEPLR,
}}
>
Step 4: Build Your First Component
Create a wallet connection component using graz hooks:
import { useAccount, useConnect, useDisconnect } from "graz";
export function WalletConnect() {
const { connect, status } = useConnect();
const { data: accounts, isConnected } = useAccount({
chainId: ["cosmoshub-4"],
});
const { disconnect } = useDisconnect();
// Extract the account for Cosmos Hub
const account = accounts?.["cosmoshub-4"];
const handleConnect = () => {
if (isConnected) {
disconnect();
} else {
connect({ chainId: ["cosmoshub-4"] });
}
};
return (
<div>
<h2>Wallet Status</h2>
{account ? (
<div>
<p>Connected to: {account.bech32Address}</p>
<p>Name: {account.name}</p>
<button onClick={handleConnect}>Disconnect</button>
</div>
) : (
<div>
<p>Status: {status}</p>
<button onClick={handleConnect}>Connect Wallet</button>
</div>
)}
</div>
);
}
Step 5: Query Balances
Add balance queries to your component:
import { useAccount, useBalance } from "graz";
export function BalanceDisplay() {
const { data: accounts } = useAccount({ chainId: ["cosmoshub-4"] });
const account = accounts?.["cosmoshub-4"];
const { data: balance, isLoading } = useBalance({
chainId: "cosmoshub-4",
bech32Address: account?.bech32Address || "",
denom: "uatom",
enabled: Boolean(account?.bech32Address),
});
if (!account) return <p>Please connect your wallet</p>;
return (
<div>
<h3>Your Balance</h3>
{isLoading ? (
<p>Loading...</p>
) : (
<p>
{(Number(balance?.amount) / 1_000_000).toFixed(6)} ATOM
</p>
)}
</div>
);
}
Multi-Chain Applications
Connect to multiple chains simultaneously:
import { useAccount, useConnect, useBalance } from "graz";
export function MultiChainWallet() {
const { connect } = useConnect();
const { data: accounts } = useAccount({
chainId: ["cosmoshub-4", "osmosis-1"],
});
const cosmosAccount = accounts?.["cosmoshub-4"];
const osmosisAccount = accounts?.["osmosis-1"];
const { data: cosmosBalance } = useBalance({
chainId: "cosmoshub-4",
bech32Address: cosmosAccount?.bech32Address || "",
denom: "uatom",
enabled: Boolean(cosmosAccount?.bech32Address),
});
const { data: osmosisBalance } = useBalance({
chainId: "osmosis-1",
bech32Address: osmosisAccount?.bech32Address || "",
denom: "uosmo",
enabled: Boolean(osmosisAccount?.bech32Address),
});
const handleConnect = () => {
connect({ chainId: ["cosmoshub-4", "osmosis-1"] });
};
return (
<div>
<button onClick={handleConnect}>Connect Multi-Chain</button>
<div>
<h3>Cosmos Hub</h3>
<p>Address: {cosmosAccount?.bech32Address}</p>
<p>Balance: {cosmosBalance?.amount} uatom</p>
</div>
<div>
<h3>Osmosis</h3>
<p>Address: {osmosisAccount?.bech32Address}</p>
<p>Balance: {osmosisBalance?.amount} uosmo</p>
</div>
</div>
);
}
Next Steps
Now that you have a working setup, explore more features:
Learn Core Concepts
- 📖 Multi-Chain Guide - Work with multiple chains
- 🔗 Wallet Connect Guide - WalletConnect integration
- 🎯 Specific Wallet Guide - Target specific wallets
Explore Hooks
- 🪝 useAccount - Account information
- 💰 useBalance - Query balances
- 📤 useSendTokens - Send transactions
- 📜 useExecuteContract - Smart contract interactions
Advanced Topics
- ⚙️ Generate Chain Info - CLI tool for chain configs
- 🔧 Provider Configuration - Advanced provider options
- 📋 Migration Guide - Upgrade from older versions
Common Patterns
Handle Loading States
function Component() {
const { data: accounts, isLoading, isConnecting } = useAccount({
chainId: ["cosmoshub-4"],
});
if (isLoading || isConnecting) return <Spinner />;
if (!accounts) return <ConnectPrompt />;
return <YourComponent account={accounts["cosmoshub-4"]} />;
}
Error Handling
function Component() {
const { connect } = useConnect({
onError: (error) => {
console.error("Connection failed:", error);
toast.error("Failed to connect wallet");
},
onSuccess: (data) => {
console.log("Connected:", data.accounts);
toast.success("Wallet connected!");
},
});
return <button onClick={() => connect({ chainId: ["cosmoshub-4"] })}>Connect</button>;
}
Refetch Data
function Component() {
const { data: accounts } = useAccount({ chainId: ["cosmoshub-4"] });
const account = accounts?.["cosmoshub-4"];
const { data: balance, refetch } = useBalance({
chainId: "cosmoshub-4",
bech32Address: account?.bech32Address || "",
denom: "uatom",
enabled: Boolean(account?.bech32Address),
});
return (
<div>
<p>Balance: {balance?.amount}</p>
<button onClick={() => refetch()}>Refresh</button>
</div>
);
}
Troubleshooting
Wallet Not Detected
Make sure users have the wallet extension installed:
import { useCheckWallet, WalletType } from "graz";
function Component() {
const { data: isKeplrInstalled } = useCheckWallet(WalletType.KEPLR);
if (!isKeplrInstalled) {
return (
<a href="https://www.keplr.app/" target="_blank">
Install Keplr Wallet
</a>
);
}
return <ConnectButton />;
}
Chain Not Configured
If a chain isn't in the wallet, use useSuggestChain
:
import { useSuggestChainAndConnect } from "graz";
function Component() {
const { suggestAndConnect } = useSuggestChainAndConnect();
const handleConnect = () => {
suggestAndConnect({
chainInfo: myCustomChain,
walletType: WalletType.KEPLR,
});
};
return <button onClick={handleConnect}>Connect</button>;
}