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).
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
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:
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 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:
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>
);
}
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:
- Wagmi template - Using Openfort accounts with wagmi.