Skip to content

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.

Terminal
pnpm add turnkey-wagmi-connector wagmi @wagmi/core viem @tanstack/react-query @turnkey/react-wallet-kit

Compatibility: 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.

app-providers.tsx
"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.

.env.local
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.

Shared Runtime
Connect once — the same Turnkey, Wagmi, Reown AppKit, and LI.FI state persists across all 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.

Wagmi Chain Switch + Sign
Switch chains and sign through the current Wagmi connector. If a third-party wallet is selected, Wagmi should keep using it even while Turnkey is logged out.
Chain: n/aconnect from shared runtime
Verify on Etherscan
Base Sepolia Transfer
Sends native ETH through the active Wagmi wallet on Base Sepolia (chain 84532). Switches network automatically when needed; the wallet needs enough Sepolia ETH for gas.

Connect a wallet from the shared runtime first.

Limitations

  • First embedded EVM account only
  • No account selector
  • No Solana support