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-js2. 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.