First of all, to interact with cosmos ecosystem you need a wallet. You can find possible wallets available here. Keplr wallet is the most widely used wallet and their API integration 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 template that already has typescript, eslint, prettier and chakra UI.
git clone https://github.com/strangelove-ventures/strangestarter.git cosmos-frontend
Install packages using pnpm
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.
// 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:
To use Keplr's API you can reference their API documentation. We need to manage the states, like if user already connected, create offlineSigner and other complex states.
Luckily Strangelove created a package called graz that abstracts the complexity of the Keplr API and wraps it into React hooks. From the documentation website 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
pnpm website install graz
Wrap our app with GrazProvider
and set default chain to cosmoshub or what ever you like
// 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
.
// 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()
.
// 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
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/
Top comments (2)
Great work!
A quick question. May I know how you calculate the downloads?
Hi.
If you scaffold blockchain using IgniteCLI, it provides Vue wallet frontend.
It also supports to generate Vuex stores so it is very easy to go forward.