Skip to main content

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:

# Install graz
npm install graz

# Install peer dependencies
npm install @cosmjs/cosmwasm-stargate @cosmjs/proto-signing @cosmjs/stargate @cosmjs/encoding @tanstack/react-query
Why peer dependencies?

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:

config/chains.ts
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,
},
};
Quick Chain Info

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:

App.tsx
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:

components/WalletConnect.tsx
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:

components/BalanceDisplay.tsx
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:

components/MultiChainWallet.tsx
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

Explore Hooks

Advanced Topics

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>;
}

Need Help?