How to connect your frontend to Cosmos blockchain
Tags: javascript, react, web3, dapp
Published: 2022-09-27 17:32:09

First of all, to interact with cosmos ecosystem you need a wallet. You can find possible wallets available [here](https://cosmos.network/ecosystem/wallets). [Keplr wallet](https://keplr.app/) is the most widely used wallet and their [API integration](https://docs.keplr.app/) is easy to use and is well-typed.

Install Keplr wallet extension to your browser and create an account if you haven't already registered. 

Let's bootstrap a website using [strangelove's starter](https://github.com/strangelove-ventures/strangestarter) template that already has typescript, eslint, prettier and chakra UI.

```shell
git clone https://github.com/strangelove-ventures/strangestarter.git cosmos-frontend
```

Install packages using `pnpm`

```shell
cd ./cosmos-frontend
pnpm install
pnpm dev
```

Okay now after we have our repo bootstrapped, let’s create a simple UI for connecting to a wallet and a dashboard.

```tsx 
// website/pages/index.tsx
import { Box, Button, Center, HStack, Stack, Tag, TagLabel, TagLeftIcon, Text } from "@chakra-ui/react";

export default function HomePage() {
  return (
    <Center minH="100vh">
      <Stack bgColor="whiteAlpha.100" boxShadow="md" maxW="md" p={4} rounded="md" spacing={4} w="full">
        <HStack>
          <Tag>
            <TagLeftIcon as={Box} bgColor="red.500" boxSize={3} rounded="full" />
            <TagLabel>Disconnected</TagLabel>
          </Tag>
        </HStack>
        <Text>
          Active chain id: <b>Chain</b>
        </Text>
        <Text>
          Name: <b>Kiki</b>
        </Text>
        <Text noOfLines={1} wordBreak="break-all">
          Address: <b>...</b>
        </Text>
        <HStack align="end" pt={4}>
          <Button>Connect Wallet</Button>
        </HStack>
      </Stack>
    </Center>
  );
}
```
You'll have something like this:

![preview](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdgjs5nnan5zv80343y7.png)

To use Keplr's API you can reference their [API documentation](https://docs.keplr.app/). We need to manage the states, like if user already connected, create offlineSigner and other complex states.

Luckily Strangelove created a package called [graz](https://github.com/strangelove-ventures/graz) that abstracts the complexity of the Keplr API and wraps it into React hooks. From the [documentation website](https://graz.strange.love/) it has features like:

- 🪝 20+ hooks for interfacing with wallets, clients, signers, etc. (connecting, view balances, send tokens, etc.)
- 💳 Multiple wallet supports (Keplr & Leap wallet)
- ⚙️ Generate mainnet & testnet `ChainInfo`
- 📚 Built-in caching, request deduplication, and all the good stuff from @tanstack/react-query and zustand
- 🔄 Auto refresh on wallet and network change
- 👏 Fully typed and tree-shakeable

So let's install `graz` to our project

```shell
pnpm website install graz
```

Wrap our app with `GrazProvider` and set default chain to cosmoshub or what ever you like

```diff
// website/pages/_app.tsx
import { ChakraProvider } from "@chakra-ui/react";
import type { AppProps } from "next/app";
import { theme } from "styles/theme";
import { Layout } from "ui/layout";
+ import { GrazProvider, mainnetChains } from "graz";

export default function CustomApp({ Component, pageProps }: AppProps) {
  return (
    <ChakraProvider resetCSS theme={theme}>
+     <GrazProvider
+       grazOptions={{
+         defaultChain: mainnetChains.cosmoshub,
+       }}
+     >
        <Layout>
          <Component {...pageProps} />
        </Layout>
+     </GrazProvider>
    </ChakraProvider>
  );
}
```

### Connect and disconnect

`graz` provides a mutation hook that we can use to connect and disconnect so you don't need to maintain the logic of these functions, simply use `useConnect()` and `useDisconnect()` to have connecting functionality. 

To check if the user is already connected or not `graz` has a hook called `useAccount()`. One of the return objects is `isConnected`.

```tsx
// website/pages/index.tsx
import { Box, Button, Center, HStack, Stack, Tag, TagLabel, TagLeftIcon, Text } from "@chakra-ui/react";
import { useAccount, useConnect, useDisconnect } from "graz";

export default function HomePage() {
  const { isConnected } = useAccount();
  const { connect } = useConnect();
  const { disconnect } = useDisconnect();

  return (
    <Center minH="100vh">
      <Stack bgColor="whiteAlpha.100" boxShadow="md" maxW="md" p={4} rounded="md" spacing={4} w="full">
        <HStack>
          <Tag>
            <TagLeftIcon as={Box} bgColor={isConnected ? "green.500" : "red.500"} boxSize={3} rounded="full" />
            <TagLabel>{isConnected ? "Connected" : "Disconnected"}</TagLabel>
          </Tag>
        </HStack>
        <Text>
          Active chain id: <b>Chain</b>
        </Text>
        <Text>
          Name: <b>Kiki</b>
        </Text>
        <Text noOfLines={1} wordBreak="break-all">
          Address: <b>...</b>
        </Text>
        <HStack align="end" pt={4}>
          <Button onClick={() => (isConnected ? disconnect() : connect())}>
            {isConnected ? "Disconnect" : "Connect Wallet"}
          </Button>
        </HStack>
      </Stack>
    </Center>
  );
}
``` 

### Show connected information

After we have connection functionality, we should display the connection information. We can get the connected account information from `useAccount()` and the current active chain from `useActiveChain()`.

```tsx
// website/pages/index.tsx
import { Box, Button, Center, HStack, Stack, Tag, TagLabel, TagLeftIcon, Text } from "@chakra-ui/react";
import { useAccount, useActiveChain, useConnect, useDisconnect } from "graz";

export default function HomePage() {
  const { isConnected, data: account } = useAccount();
  const { connect } = useConnect();
  const { disconnect } = useDisconnect();
  const activeChain = useActiveChain();

  return (
    <Center minH="100vh">
      <Stack bgColor="whiteAlpha.100" boxShadow="md" maxW="md" p={4} rounded="md" spacing={4} w="full">
        <HStack>
          <Tag>
            <TagLeftIcon as={Box} bgColor={isConnected ? "green.500" : "red.500"} boxSize={3} rounded="full" />
            <TagLabel>{isConnected ? "Connected" : "Disconnected"}</TagLabel>
          </Tag>
        </HStack>
        <Text>
          Active chain id: <b>{activeChain?.chainId}</b>
        </Text>
        <Text>
          Name: <b>{account?.name}</b>
        </Text>
        <Text noOfLines={1} wordBreak="break-all">
          Address: <b>{account?.bech32Address}</b>
        </Text>
        <HStack align="end" pt={4}>
          <Button onClick={() => (isConnected ? disconnect() : connect())}>
            {isConnected ? "Disconnect" : "Connect Wallet"}
          </Button>
        </HStack>
      </Stack>
    </Center>
  );
}
```

Congratulations now your app is connected to the cosmos ecosystem

{% embed https://www.loom.com/embed/f6206d7202e24c42b29740039793fcd8 %}

When you `connect` with graz's `useConnect()` it automatically generates `offlineSigners`, `Clients`, `SigningClients`. You can get the details from `useOfflineSigners()`, `useClients()` and `useSigningClients()` if you want to interact with those things.

graz has many useful hooks such as useBalances() to view balances, `useSendTokens()` to send tokens, `useBalanceStaked()` to see how many tokens are staked, and many more! You can see it on the documentation https://graz.strange.love

Source code: https://github.com/codingki/cosmos-frontend
Preview: https://cosmos-frontend-graz.vercel.app/