turnkey-wagmi-connector
A Turnkey-backed Wagmi connector that makes the embedded Turnkey EVM wallet look like a normal Wagmi wallet. Connect once, bridge the session, and reuse the connection in LI.FI, Reown AppKit, or any Wagmi-aware tool.
Install
The package expects these peers in the consuming app.
pnpm add turnkey-wagmi-connector wagmi @wagmi/core viem @tanstack/react-query @turnkey/react-wallet-kitCompatibility: wagmi ≥2.19.5 <4 · viem 2.x · react≥18
Provider Setup
Wrap your app with the Turnkey session provider, the Wagmi provider, and the bridge. The bridge auto-connects the Turnkey wallet after auth and refreshes sessions before expiry.
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider, createConfig, http } from "wagmi";
import { base, mainnet } from "viem/chains";
import {
TurnkeySessionProvider,
TurnkeyWagmiBridge,
createTurnkeyConnector,
} from "turnkey-wagmi-connector";
const chains = [mainnet, base] as const;
const turnkeyConnector = createTurnkeyConnector({
chains,
walletLabel: "Turnkey Session",
});
const wagmiConfig = createConfig({
chains,
connectors: [turnkeyConnector],
transports: {
[mainnet.id]: http(),
[base.id]: http(),
},
});
const queryClient = new QueryClient();
const turnkeyConfig = {
apiBaseUrl: "https://api.turnkey.com",
organizationId: process.env.NEXT_PUBLIC_TURNKEY_ORGANIZATION_ID!,
authProxyConfigId: process.env.NEXT_PUBLIC_TURNKEY_AUTH_PROXY_CONFIG_ID!,
auth: {
autoRefreshSession: false,
methods: { emailOtpAuthEnabled: true },
methodOrder: ["email"],
},
};
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
<TurnkeySessionProvider turnkeyConfig={turnkeyConfig}>
<WagmiProvider config={wagmiConfig}>
<TurnkeyWagmiBridge />
{children}
</WagmiProvider>
</TurnkeySessionProvider>
</QueryClientProvider>
);
}This demo app additionally wraps Reown AppKit and uses @reown/appkit-adapter-wagmi for external wallet switching. See src/components/providers.tsx and src/lib/app-config.ts for the full setup.
Creating the connector is a one-liner:
import { createTurnkeyConnector } from "turnkey-wagmi-connector";
import { mainnet, base, arbitrum } from "viem/chains";
const turnkeyConnector = createTurnkeyConnector({
chains: [mainnet, base, arbitrum],
walletLabel: "Turnkey Embedded",
});Environment Variables
Configure these in .env.local (or your deployment platform). Turnkey org and auth-proxy are required; RPC URLs prevent falling back to public endpoints.
NEXT_PUBLIC_TURNKEY_ORGANIZATION_ID=...
NEXT_PUBLIC_TURNKEY_AUTH_PROXY_CONFIG_ID=...
NEXT_PUBLIC_REOWN_PROJECT_ID=...
NEXT_PUBLIC_BASE_RPC_URL=...
NEXT_PUBLIC_ARBITRUM_RPC_URL=...
NEXT_PUBLIC_OPTIMISM_RPC_URL=...Exports & API
Everything the package exposes publicly.
createTurnkeyConnector
Creates a Wagmi connector backed by the embedded Turnkey EVM wallet. Pass your chains and an optional label.
TurnkeySessionProvider
Wraps @turnkey/react-wallet-kit and syncs Turnkey auth, session, and wallet state into the package runtime.
TurnkeyWagmiBridge
Render once per Wagmi config. Auto-connects after Turnkey auth, refreshes sessions, and disconnects Wagmi connectors when the session expires.
useTurnkeySessionGate
Returns auth state, session validity, reconnect status, connectTurnkey(), refreshSession(), disconnectAll(), and the embedded account.
useTurnkeyChainSwitch
Chain switching that works across both Wagmi 2 and Wagmi 3 with the Turnkey connector.
useTurnkeyWalletActions
Direct Turnkey-backed signing and transaction submission via @turnkey/viem, bypassing generic wallet-provider semantics.
Typical hook usage:
import { useTurnkeySessionGate } from "turnkey-wagmi-connector";
function MyComponent() {
const { authState, isSessionValid, connectTurnkey, disconnectAll } =
useTurnkeySessionGate();
if (!isSessionValid) {
return <button onClick={() => connectTurnkey()}>Connect</button>;
}
return <p>Session active — {authState}</p>;
}Common Pitfalls
Duplicate provider packages
Your app and the package must share the same React provider instances. If you see errors like 'useConfig must be used within WagmiProvider', you have duplicate wagmi or @turnkey/react-wallet-kit.
Turnkey auth is the source of truth
Do not treat Wagmi persistence as Turnkey session validity. Turnkey expiry should disable embedded Turnkey flows, but it should not forcibly disconnect an active third-party wallet.
External wallet switching
An external wallet can become the active Wagmi connector and remain usable while Turnkey is logged out. Only Turnkey-backed actions should be session-gated.
SSR and monorepos
Pay attention to shared peer dependencies, dynamic routes requiring client-only wallet providers, and transpilePackages if consuming the workspace source.
Live: Shared Runtime
Connect here once. The same Turnkey, Wagmi, and Reown AppKit state persists across all live sections below.
- Auth state
- unauthenticated
- Session valid
- no
- Connector
- none
- Wallet mode
- none
- Chain
- n/a
- Active address
- not connected
- Embedded address
- not resolved
- Balance
- n/a
- Expires in
- n/a
- Expires at
- n/a
Live: LI.FI Widget
Proves the published connector drives Wagmi correctly inside the LI.FI widget. Connect via the shared runtime above. Use the sandbox for chain-switch and message signing.
Connect a wallet from the shared runtime first.
Live: Sandbox
Wagmi chain switch, message signing, and a Base Sepolia native ETH send using whichever wallet is connected in the shared runtime.
Connect a wallet from the shared runtime first.
Limitations
- First embedded EVM account only
- No account selector
- No Solana support