Skip to content

Integrating with Web3 Libraries

Openfort's wallet object is fully compatible with popular libraries for interfacing wallets, including ethers, viem, and wagmi.

Read below to learn how to best integrate Openfort alongside these libraries.

Ethers

Call the wallet's getEthereumProvider method to get a provider:

Ethers v5

Ethers represents connected wallets as a provider, which can be used to take read-only actions with the wallet, and a signer, which can be used to take write actions (signatures and transactions).

client.tsx
import openfort from "./openfortConfig"
// This example assumes you have already checked that Openfort 'embeddedState' is 
// `ready` and the user is `authenticated`
const provider = openfort.embeddedWallet.getEthereumProvider();
const web3Provider = new ethers.providers.Web3Provider(provider);

Then, call the provider's getSigner method to get the corresponding signer:

const signer = web3Provider.getSigner();

You can then use the provider and signer to get information about the wallet or request signatures and transactions.

Ethers v6

client.tsx
import openfort from "./openfortConfig"
// This example assumes you have already checked that Openfort 'embeddedState' is 
// `ready` and the user is `authenticated`
const provider = openfort.embeddedWallet.getEthereumProvider();
const ethersProvider = new ethers.BrowserProvider(provider);
const signer = ethersProvider.getSigner();

Viem

Viem represents connected wallets as a wallet client object, which you can use to get information about the current wallet or the request signatures and transactions.

To get a viem wallet client for a user's connected wallet, first import your desired network from the viem/chains package and import the createWalletClient method and custom transport from viem:

import {createWalletClient, custom} from 'viem';
// Replace `sepolia` with your desired network
import {sepolia} from 'viem/chains';

Lastly, get the wallet's EIP1193 provider using the wallet's getEthereumProvider method and pass it to viem's createWalletClient method like so:

client.tsx
import openfort from "./openfortConfig"
// This example assumes you have already checked that Openfort 'embeddedState' is 
// `ready` and the user is `authenticated`
const provider = await wallet.getEthereumProvider();
const walletClient = createWalletClient({
  chain: sepolia,
  transport: custom(provider),

You can then use the wallet client to get information about the wallet or request signatures and transactions.


Wagmi

Wagmi is a set of React hooks for interfacing with Ethereum wallets, allowing you read wallet state, request signatures or transactions, and take read and write actions on the blockchain.

Openfort is fully compatible with wagmi, and you can use wagmi's React hooks to interface with external and embedded wallets from Openfort. Just follow the steps below!

1. Install dependencies

Install the latest versions of wagmi, @tanstack/react-query and @openfort/openfort-js:

npm
npm i wagmi @tanstack/react-query @openfort/openfort-js

2. Setup TanStack Query

To start, set up your app with the TanStack Query's React Provider. Wagmi uses TanStack Query under the hood to power its data fetching and caching of wallet and blockchain data.

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

Next, create a new instance of the QueryClient:

const queryClient = new QueryClient();

Then, wrap your app's components with the QueryClientProvider. This must be rendered inside the WagmiProvider component.

<WagmiProvider config={config}>
  <QueryClientProvider client={queryClient}>
    <Connect />
  </QueryClientProvider>
</WagmiProvider>

For the client property of the QueryClientProvider, pass the queryClient instance you created.

3. Setup Wagmi

To build your wagmi config, import the createConfig method. Next, import your app's required chains from viem/chains and the http transport from wagmi.

import { createConfig, http } from 'wagmi';
import { sepolia } from 'wagmi/chains';
import { injected } from 'wagmi/connectors';
 
export const config = createConfig({
  chains: [sepolia],
  connectors: [injected()],
  transports: {
    [sepolia.id]: http(),
  },
});

4. Create Openfort Connector

You'll need to create a custom connector for Openfort. Create a new file openfortConnector.ts:

import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
import {WagmiProvider} from 'wagmi';
 
import {Connect} from './components/Connect';
import {config} from './wagmi';
import {useEffect} from 'react';
import {openfortInstance} from './main';
 
const queryClient = new QueryClient();
 
export default function App() {
  useEffect(() => {
    if (!openfortInstance) return;
    openfortInstance.getEmbeddedState();
    openfortInstance.getEthereumProvider(); // EIP-6963
  }, [openfortInstance]);
 
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <Connect />
      </QueryClientProvider>
    </WagmiProvider>
  );
}

5. Connector list

Create a new file Connect.tsx to list the available connectors and handle the connection. When you press on Openfort, then you will be redirected to the authentication page that you should implement. You can find an example of the authentication page in the Openfort documentation.

import * as React from 'react';
import {useNavigate} from 'react-router-dom';
import {Connector, useChainId, useConnect} from 'wagmi';
 
export function ConnectorsList() {
  const chainId = useChainId();
  const {connectors, connect, error} = useConnect();
  const navigate = useNavigate();
  const [activeConnector, setActiveConnector] =
    React.useState<Connector | null>(null);
 
  React.useEffect(() => {
    if (
      error &&
      activeConnector?.name === 'Openfort' &&
      error.message ===
        'Unauthorized - must be authenticated and configured with a signer'
    ) {
      navigate('/authentication');
    }
  }, [error, activeConnector, navigate]);
 
  const handleConnect = (connector: Connector) => {
    setActiveConnector(connector);
    connect({connector, chainId});
  };
 
  return (
    <div>
      <div className="buttons">
        {connectors
          .filter((connector) => !connector.name.includes('Injected'))
          .map((connector) => (
            <ConnectorButton
              key={connector.uid}
              connector={connector}
              onClick={() => handleConnect(connector)}
            />
          ))}
      </div>
      {error && <div className="error">Error: {error.message}</div>}
    </div>
  );
}
 
function ConnectorButton({
  connector,
  onClick,
}: {
  connector: Connector;
  onClick: () => void;
}) {
  const [ready, setReady] = React.useState(false);
  React.useEffect(() => {
    (async () => {
      const provider = await connector.getProvider();
      setReady(!!provider);
    })();
  }, [connector, setReady]);
 
  return (
    <button
      className="button"
      disabled={!ready}
      onClick={onClick}
      type="button"
    >
      {connector.name}
    </button>
  );
}

6. Complete example

Altogether, this should look like:

app.tsx
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
import {WagmiProvider} from 'wagmi';
 
import {Connect} from './components/Connect';
import {config} from './wagmi';
import {useEffect} from 'react';
import {openfortInstance} from './main';
 
const queryClient = new QueryClient();
 
export default function App() {
  useEffect(() => {
    if (!openfortInstance) return;
    openfortInstance.getEmbeddedState();
    openfortInstance.getEthereumProvider(); // EIP-6963
  }, [openfortInstance]);
 
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <Connect />
      </QueryClientProvider>
    </WagmiProvider>
  );
}
That's it! You've successfully integrated Openfort alongside wagmi in your app! 🎉

7. Use wagmi throughout your app

Once you've completed the setup above, you can use wagmi's React hooks throughout your app to interface with wallets and take read and write actions on the blockchain.

To use wagmi hooks, like useAccount, in your components, import the hook directly from wagmi and call it as usual:

import {useAccount} from 'wagmi';
 
export default const WalletAddress = () => {
  const {address} = useAccount();
  return <p>Wallet address: {address}</p>;
}

Demo app with WAGMI

Feel free to take a look at the app's source code to see an end-to-end implementation of Openfort with wagmi: