wagmi
Wagmi needs a connector that translates its connection lifecycle into EIP-1193 provider calls. Konekt supplies the provider; the connector from konekt-ui/wagmi adapts it to wagmi.
In this setup:
- wagmi’s viem HTTP transports handle public reads;
- the Konekt connector handles accounts, signatures, transactions, and chain switching;
konekt-ui/wagmican render the connect, account, and network controls.
This guide works with React 18 or 19, wagmi 2 or 3, and viem 2. The snippets use hook names that exist in both wagmi versions (useAccount, connect, disconnect, switchChain). Wagmi 3 also exports useConnection and mutate as newer aliases.
Install
Section titled “Install”pnpm add konekt konekt-ui viem wagmi @tanstack/react-query react react-domYou also need a WalletConnect project ID.
Add the Konekt connector
Section titled “Add the Konekt connector”konekt-ui/wagmi exports the connector: konekt(options) for wagmi configuration and abortPairing() for cancelling the current proposal. The konekt core package still has no wagmi dependency; the connector lives in the entry point that already declares wagmi as a peer.
import { konekt } from "konekt-ui/wagmi";If your app does not use konekt-ui, copy the connector implementation into your application instead — it is one self-contained file.
The connector:
- creates
Provider.init()lazily when wagmi first requests it; - configures EVM chains from the wagmi config;
- maps Konekt account, chain, and disconnect events into wagmi events;
- exposes
display_urithrough the connector’smessageevent; - opens the wallet URL from
request_sent; - aborts a pending proposal through
abortPairing().
Create the wagmi config
Section titled “Create the wagmi config”Register the connector next to injected browser wallets. Save this as src/web3.tsx:
import type { PropsWithChildren } from "react";import { QueryClient, QueryClientProvider } from "@tanstack/react-query";import { WagmiProvider, createConfig, http } from "wagmi";import { base, mainnet } from "wagmi/chains";import { injected } from "wagmi/connectors";import { konekt } from "konekt-ui/wagmi";
const projectId = "YOUR_PROJECT_ID";
export const konektOptions = { projectId, metadata: { name: "My app", description: "Connect to My app", url: "https://app.example.com", icons: ["https://app.example.com/icon.png"], },};
export const config = createConfig({ chains: [mainnet, base], connectors: [ injected(), konekt(konektOptions), ], transports: { [mainnet.id]: http("https://ethereum.example-rpc.com"), [base.id]: http("https://base.example-rpc.com"), },});
declare module "wagmi" { interface Register { config: typeof config; }}
const queryClient = new QueryClient();
export function Web3Provider({ children }: PropsWithChildren) { return ( <WagmiProvider config={config}> <QueryClientProvider client={queryClient}> {children} </QueryClientProvider> </WagmiProvider> );}Registering the connector does not open a relay socket. On mount, wagmi asks every connector whether it is already authorized, which makes this connector dynamically import Konekt and call Provider.init(). That restores a saved session, and it connects to the relay only when a saved session exists.
The wagmi transports are intentionally separate from Konekt’s optional EVM read transport. Wagmi sends public reads through its viem clients and sends wallet actions through the active connector.
Add the complete connect UI
Section titled “Add the complete connect UI”ConnectButton renders:
- a connect trigger;
- installed connectors and WalletConnect Explorer wallets;
- a WalletConnect pairing QR;
- connected account and balance details;
- network switching and disconnect controls.
import { abortPairing, ConnectButton } from "konekt-ui/wagmi";import "konekt-ui/styles.css";
export function WalletControls() { return <ConnectButton onDismiss={abortPairing} />;}The button reads the WalletConnect project ID from the registered Konekt connector, so there is nothing to configure twice. onDismiss matters because closing the modal should also abort the proposal owned by the connector. The modal itself removes its connector event listener; abortPairing() stops the underlying Konekt connection.
Use wagmi hooks
Section titled “Use wagmi hooks”Once connected, Konekt behaves like the app’s other wagmi connectors:
import { formatUnits, parseEther } from "viem";import { useAccount, useBalance, useDisconnect, useSendTransaction, useSwitchChain,} from "wagmi";import { base } from "wagmi/chains";
export function AccountActions() { const account = useAccount(); const balance = useBalance({ address: account.address }); const transaction = useSendTransaction(); const switching = useSwitchChain(); const disconnecting = useDisconnect();
if (!account.isConnected || !account.address) { return <p>No wallet connected.</p>; }
return ( <section> <p>{account.address}</p> <p> {balance.data ? `${formatUnits(balance.data.value, balance.data.decimals)} ${balance.data.symbol}` : "Loading balance…"} </p>
<button type="button" disabled={transaction.isPending} onClick={() => transaction.sendTransaction({ to: "0x000000000000000000000000000000000000dEaD", value: parseEther("0.001"), }) } > Send transaction </button>
<button type="button" disabled={switching.isPending} onClick={() => switching.switchChain({ chainId: base.id })} > Switch to Base </button>
<button type="button" disabled={disconnecting.isPending} onClick={() => disconnecting.disconnect()} > Disconnect </button> </section> );}The connector forwards the wallet actions to Konekt. Reads such as useBalance() continue to use the HTTP transport in the wagmi config.
Use your own trigger and modal
Section titled “Use your own trigger and modal”Use useWagmiPairing() when you want to keep your own connect button while reusing the wallet picker:
import { useState } from "react";import { WalletModal } from "konekt-ui";import { abortPairing, useWagmiPairing } from "konekt-ui/wagmi";
export function CustomWalletButton() { const [open, setOpen] = useState(false); const pairing = useWagmiPairing();
return ( <> <button type="button" onClick={() => setOpen(true)}> Choose a wallet </button> <WalletModal open={open} pairing={pairing} onDismiss={abortPairing} onClose={() => setOpen(false)} /> </> );}Static and lazy connector registration
Section titled “Static and lazy connector registration”Static registration in createConfig() is the recommended path, and the one this guide uses. Because the connector imports Konekt lazily inside getProvider(), registration costs one dynamic import during wagmi’s reconnect and no relay socket unless a saved session exists.
That import still happens for a visitor who never connects a wallet. If you need Konekt entirely absent until someone opens the wallet picker, pass getWalletConnect to ConnectButton or useWagmiPairing() and create the connector on demand:
import { useCallback, useRef } from "react";import type { Connector } from "wagmi";import { useConfig } from "wagmi";import { abortPairing, ConnectButton, konekt } from "konekt-ui/wagmi";import { konektOptions } from "./web3";
export function WalletControls() { const config = useConfig(); const connector = useRef<Connector>(undefined);
const getWalletConnect = useCallback(async () => { // `_internal` is wagmi's private API. Registering a connector after // createConfig() has no public equivalent. connector.current ??= config._internal.connectors.setup(konekt(konektOptions)); return connector.current; }, [config]);
return ( <ConnectButton projectId={konektOptions.projectId} getWalletConnect={getWalletConnect} onDismiss={abortPairing} /> );}The projectId prop is needed only on this path: with no Konekt connector registered until pairing starts, the wallet picker has nowhere else to read the ID from.
This is the trade-off the repository’s example app demonstrates. Weigh it deliberately: config._internal is not part of wagmi’s public API and can change in a minor release. Prefer static registration unless the initial-chunk saving matters for your app, and pin your wagmi version if you adopt this pattern.
To keep the provider and modal out of the initial page chunk in other ways, follow the lazy-loading patterns and measured bundle sizes.
Troubleshooting
Section titled “Troubleshooting”“No WalletConnect connector is registered”
Section titled ““No WalletConnect connector is registered””Import konekt from konekt-ui/wagmi and add konekt(konektOptions) to createConfig({ connectors }). The connector’s id or type must be "konekt".
The QR closes but pairing continues
Section titled “The QR closes but pairing continues”Pass onDismiss={abortPairing} to ConnectButton or WalletModal.
Reads work but signatures do not
Section titled “Reads work but signatures do not”Wagmi HTTP transports handle reads without a wallet. Confirm that the Konekt connector is active and that the user approved a session before sending wallet actions.
A chain is missing
Section titled “A chain is missing”Add it to the wagmi chains array and provide its HTTP transport. The connector derives its proposed EVM chains from that config.