React
Transactions with Owl Wallet

Using The Owl Wallet

In this tutorial, you will create a basic React app that lets you connect to an Owl Protocol wallet and send a gasless transaction with a smart account using the Owl Protocol ERC4337 (opens in a new tab) Account Abstraction API, Wagmi (opens in a new tab) hooks and a RainbowKit (opens in a new tab) wallet connector.

Clone The Repo

We have created the Owl Protocol tutorials-react repository (opens in a new tab) to get you started quickly.

git clone https://github.com/owlprotocol/tutorials-react.git owlprotocol-tutorials-react
cd owlprotocol-tutorials-react

Now, let's install the dependencies (we recommend using pnpm (opens in a new tab))

npm install

Then, copy the example environment variables. You do not need to change these.

cp .env.example .env

The main file we will be working with is App.tsx. Let's run vite to make sure everything is working

npm run dev

Create A Project On The Owl Dashboard

Owl Wallets are tied to a project. Head to the Owl Dashboard (opens in a new tab) to create a project. Note that you can also use the default one created for you. Then, take note of the project id.

Initialize The Owl Provider

Initialize the Owl Provider in App.tsx to enable the Owl Wallet and gasless transactions.

Note that this is already done for you in the starter repository.

This provider is used to interact with our API.

Make sure to also import @owlprotocol/ui-components/style.css. This CSS file styles Owl UI components.

import { OwlProvider } from "@owlprotocol/ui-components";
 
import "./App.css";
import "@owlprotocol/ui-components/style.css";
 
export const App = () => {
    return (
        <>
            <h1>Owl React Tutorials</h1>
 
            <OwlProvider>{/* Add tutorial snippets below */}</OwlProvider>
        </>
    );
};

Create The Owl Wallet Test Component

In this step, we will initialize wrappers to create blockchain interactions.

We first set the Owl project id, from the environment variable VITE_PROJECT_ID. Make sure to set your project id inside of a .env file.

We will connect to the Hedwig Testnet chain, which has chain id 150150.

We start by fetching data about that chain by making a tRPC call to the Owl API.

We then set up two providers:

  • WagmiProvider: enables hooks for blockchain interactions such as sending transactions
import { trpc } from "@owlprotocol/core-trpc/react-query";
import { Chain, http } from "viem";
import { createConfig, WagmiProvider } from "wagmi";
 
const projectId = import.meta.env.VITE_PROJECT_ID;
 
if (!projectId || projectId === "PROJECT_ID")
    throw new Error("VITE_PROJECT_ID must be defined!");
 
export const TransactionsOwlWalletTest = () => {
    const [hedwigTestnetChain] = trpc.network.get.useSuspenseQuery({
        chainId: 150150,
    });
 
    const chains = [hedwigTestnetChain] as readonly [Chain];
 
    const config = createConfig({
        chains,
        transports: {
            [hedwigTestnetChain.id]: http(hedwigTestnetChain.rpcDefault),
        },
    });
 
    return (
        <WagmiProvider config={config}>
            {/* We will be writing this component next */}
            <TransactionsOwlWalletTestInner />
        </WagmiProvider>
    );
};

Create The Owl Wallet Test Inner Component

We now create the inner component, which consists of the RainbowKit button to connect a wallet, and a button to send a transaction. We also add the useOwlSimpleSmartAccount hook. This automatically overrides the basic Owl wallet the users connects with to use a smart wallet.

Notice that when you send a transaction, the transaction hash will be displayed under. The data attribute of useSendTransaction gets populated once the transaction has successfully been sent.

import { trpc } from "@owlprotocol/core-trpc/react-query";
import {
    OwlConnectButton,
    useOwlSimpleSmartAccount,
} from "@owlprotocol/ui-components";
import { Chain, http, zeroAddress } from "viem";
import {
    createConfig,
    useConnectors,
    useSendTransaction,
    WagmiProvider,
} from "wagmi";
 
const projectId = import.meta.env.VITE_PROJECT_ID;
 
if (!projectId || projectId === "PROJECT_ID")
    throw new Error("VITE_PROJECT_ID must be defined!");
 
export const TransactionsOwlWalletTestInner = () => {
    const { sendTransaction, data: txHash } = useSendTransaction();
 
    const connectors = useConnectors();
 
    useOwlSimpleSmartAccount();
 
    return (
        <>
            <button
                onClick={() =>
                    sendTransaction({
                        to: zeroAddress,
                        value: 0n,
                        data: "0x",
                    })
                }
            >
                Send test transaction
            </button>
            <br />
            <br />
            {!!txHash && <p>Transaction Hash: {txHash}</p>}
            <button onClick={() => connectors.forEach((c) => c.disconnect())}>
                Disconnect All
            </button>
            <br />
            <br />
            <OwlConnectButton projectId={projectId} />
        </>
    );
};
 
export const TransactionsOwlWalletTest = () => {
    // ...
};

Add The Transactions Owl Wallet Test Component To The App

Back in App.tsx, import and add the TransactionsOwlWalletTest.

import { OwlProvider } from "@owlprotocol/ui-components";
import { TransactionsOwlWalletTest } from "./tutorials/transactions-owl-wallet.jsx";
 
import "./App.css";
import "@owlprotocol/ui-components/style.css";
 
export const App = () => {
    return (
        <>
            <h1>Owl React Tutorials</h1>
 
            <OwlProvider>
                {/* Add tutorial snippets below */}
                <TransactionsOwlWalletTest />
            </OwlProvider>
        </>
    );
};

And voilà! Run pnpm dev again if needed, and check out your first app with a gasless transaction. Make sure to connect your wallet, and then click on Send Test Transaction.

To see the final component, go to our GitHub (opens in a new tab).