# Integrate with web3 libraries

Openfort's `wallet` object is fully compatible with popular libraries for interfacing wallets, including [ethers](#ethers), [viem](#viem), and [wagmi](#wagmi).

Read below to learn how to 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](https://docs.ethers.org/v5/api/providers/provider/), which can be used to take read-only actions with the wallet, and a [signer](https://docs.ethers.org/v5/api/signer/), which can be used to take write actions (signatures and transactions).

:::code-group
```tsx [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 openfort.embeddedWallet.getEthereumProvider();
const web3Provider = new ethers.providers.Web3Provider(provider);
```

```ts [openfortConfig.ts]
import { Openfort } from '@openfort/openfort-js';

const openfort = new Openfort({
  baseConfiguration: {
    publishableKey: "YOUR_OPENFORT_PUBLISHABLE_KEY",
  },
  shieldConfiguration: {
    shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
  },
});

export default openfort;
```
:::

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

```tsx
const signer = web3Provider.getSigner();
```

You can then use the [provider](https://docs.ethers.org/v5/api/providers/provider/) and [signer](https://docs.ethers.org/v5/api/signer/) to get information about the wallet or request signatures and transactions.

### Ethers v6

:::code-group
```tsx [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 openfort.embeddedWallet.getEthereumProvider();
const ethersProvider = new ethers.BrowserProvider(provider);
const signer = await ethersProvider.getSigner();
```

```ts [openfortConfig.ts]
import { Openfort } from '@openfort/openfort-js';

const openfort = new Openfort({
  baseConfiguration: {
    publishableKey: "YOUR_OPENFORT_PUBLISHABLE_KEY",
  },
  shieldConfiguration: {
    shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
  },
});

export default openfort;
```
:::

***

## Viem

Viem represents connected wallets as a [wallet client](https://viem.sh/docs/clients/wallet) object, which you can use to get information about the current wallet or 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`:

```tsx
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:

:::code-group
```tsx [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 openfort.embeddedWallet.getEthereumProvider();
const walletClient = createWalletClient({
  chain: sepolia,
  transport: custom(provider),
});
```

```ts [openfortConfig.ts]
import { Openfort } from '@openfort/openfort-js';

const openfort = new Openfort({
  baseConfiguration: {
    publishableKey: "YOUR_OPENFORT_PUBLISHABLE_KEY",
  },
  shieldConfiguration: {
    shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
  },
});

export default openfort;
```
:::

You can then use the [wallet client](https://viem.sh/docs/clients/wallet) to get information about the wallet or request signatures and transactions.

***

## Wagmi

[Wagmi](https://wagmi.sh/) 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](https://wagmi.sh/), and you can use wagmi's React hooks to interface with external and embedded wallets from Openfort. Follow the steps below.**

:::tip
Check out the [wagmi starter repo](https://github.com/openfort-xyz/openfort-js/tree/main/examples/apps/wallet-libraries/next-wagmi) and the [wagmi live demo](https://wagmi.openfort.io).
:::

### 1. Install dependencies

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

:::code-group
```sh [npm]
npm i wagmi @tanstack/react-query @openfort/openfort-js
```

```sh [yarn]
yarn add wagmi @tanstack/react-query @openfort/openfort-js
```

```sh [pnpm]
pnpm add wagmi @tanstack/react-query @openfort/openfort-js
```
:::

### 2. Set up TanStack Query

To start, set up your app with the [TanStack Query's React Provider](https://tanstack.com/query/v5/docs/framework/react/overview). Wagmi uses TanStack Query under the hood to power its data fetching and caching of wallet and blockchain data.

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

Next, create a new instance of the [`QueryClient`](https://tanstack.com/query/v4/docs/reference/QueryClient):

```tsx
const queryClient = new QueryClient();
```

Then, wrap your app's components with the [`QueryClientProvider`](https://tanstack.com/query/latest/docs/framework/react/reference/QueryClientProvider). This must be rendered inside the `WagmiProvider` component.

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

For the [`client`](https://tanstack.com/query/latest/docs/framework/react/reference/QueryClientProvider) property of the `QueryClientProvider`, pass the [`queryClient`](https://tanstack.com/query/v4/docs/reference/QueryClient) instance you created.

### 3. Set up Wagmi

To build your `wagmi` config, import the `createConfig` method. Next, import your app's required chains from [`viem/chains`](https://viem.sh/docs/development/chains/introduction.html) and the [`http`](https://wagmi.sh/core/api/transports/http#http) transport from `wagmi`.

```tsx wagmi.tsx
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

Create a custom connector for Openfort. Create a new file `openfortConnector.ts`:

```tsx main.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.embeddedWallet.getEmbeddedState();
    openfortInstance.embeddedWallet.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 select Openfort, you are redirected to the authentication page that you implement. You can find an example of the authentication page in the [Openfort documentation](https://github.com/openfort-xyz/openfort-js/blob/main/examples/apps/wallet-libraries/vite-wagmi/src/components/Authenticate.tsx).

```tsx Connect.tsx
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:

:::code-group
```tsx [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.embeddedWallet.getEmbeddedState();
    openfortInstance.embeddedWallet.getEthereumProvider(); // EIP-6963
  }, [openfortInstance]);

  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <Connect />
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```

```tsx [main.tsx]
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import './index.css';
import { Openfort } from '@openfort/openfort-js';
import {RouterProvider, createBrowserRouter} from 'react-router-dom';
import Authenticate from './components/Authenticate.tsx';

const OPENFORT_PUBLISHABLE_KEY = 'pk_test_505bc088-905e-5a43-b60b-4c37ed1f887a';
const SHIELD_PUBLISHABLE_KEY = 'a4b75269-65e7-49c4-a600-6b5d9d6eec66';

export const openfortInstance = new Openfort({
  baseConfiguration: {
    publishableKey: OPENFORT_PUBLISHABLE_KEY,
  },
  shieldConfiguration: {
    shieldPublishableKey: SHIELD_PUBLISHABLE_KEY,
  },
});

const router = createBrowserRouter([
  {
    path: '/',
    element: <App />,
  },
  {
    path: '/authentication',
    element: <Authenticate openfortInstance={openfortInstance} />,
  },
]);

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);
```

```tsx [wagmi.tsx]
import {http, createConfig} from 'wagmi';
import {sepolia} from 'wagmi/chains';
import {injected} from 'wagmi/connectors';

export const config = createConfig({
  chains: [sepolia],
  connectors: [injected()],
  transports: {
    [sepolia.id]: http(),
  },
});
```

```tsx [Connect.tsx]
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>
  );
}
```
:::

You have 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:

```tsx
import {useAccount} from 'wagmi';

export default function WalletAddress() {
  const {address} = useAccount();
  return <p>Wallet address: {address}</p>;
}
```

### Demo app with wagmi

Review the app's source code for an end-to-end implementation of Openfort with wagmi:

* **[Wagmi template](https://github.com/openfort-xyz/openfort-js/tree/main/examples/apps/wallet-libraries/vite-wagmi)** - Using Openfort accounts with wagmi.
