SVG Definitions

Passkey Session Key

Create a passkey-backed session key for an ECDSA smart account

Passkey session keys let you authorize temporary access using WebAuthn credentials instead of an ECDSA private key. This is useful when you want users to approve scoped permissions with a device prompt (Face ID/Touch ID) instead of managing another key. The primary account remains ECDSA, while the session key is passkey-based.

If you need multichain support with a single approval, prefer ECDSA smart accounts with ECDSA session keys. That combination supports multi-chain signing via a single signature and is the recommended path for production use.


Import

import { createAccountClient } from "@namera-ai/sdk/account";
import { toWebAuthnKey, WebAuthnMode } from "@namera-ai/sdk/passkey";
import { createSessionKey, createSessionKeyClient } from "@namera-ai/sdk/session-key";

Usage

To create a passkey session key for an ECDSA smart account, you:

  1. Create your ECDSA smart account client.
  2. Register or login a passkey to get a WebAuthn key.
  3. Create a passkey session key with policies.
  4. Build a session key client from the serialized account.
index.ts
import { createAccountClient } from "@namera-ai/sdk/account";
import { toWebAuthnKey, WebAuthnMode } from "@namera-ai/sdk/passkey";
import { createSessionKey, createSessionKeyClient } from "@namera-ai/sdk/session-key";
import { http } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";
import { publicClient } from "./clients";

const signer = privateKeyToAccount(generatePrivateKey());

const accountClient = await createAccountClient({
  type: "ecdsa",
  signer,
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  chain: mainnet,
  client: publicClient,
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
});

const webAuthnSessionKey = await toWebAuthnKey({
  mode: WebAuthnMode.Register, // or WebAuthnMode.Login
  passkeyName: "passkey name",
  passkeyServerHeaders: {},
  passkeyServerUrl: "YOUR_PASSKEY_SERVER_URL",
});

const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [
    // Policies for this session key
  ],
  signer,
  webAuthnSessionKey,
});

const serializedAccount = sessionKey.serializedAccounts[0]
  ?.serializedAccount as string;

const sessionKeyClient = await createSessionKeyClient({
  type: "passkey",
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  chain: mainnet,
  client: publicClient,
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  serializedAccount,
  webAuthnKey: webAuthnSessionKey,
});

// Use sessionKeyClient to send UserOps with the passkey session key.

Examples

Create a passkey session key with a paymaster, then build a session key client.

index.ts
import { createAccountClient } from "@namera-ai/sdk/account";
import { toWebAuthnKey, WebAuthnMode } from "@namera-ai/sdk/passkey";
import {
  createSessionKey,
  createSessionKeyClient,
} from "@namera-ai/sdk/session-key";
import { createPublicClient, http } from "viem";
import { createPaymasterClient } from "viem/account-abstraction";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

export const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const paymaster = createPaymasterClient({
  transport: http("ZERO_DEV_PAYMASTER_URL"),
});

const signer = privateKeyToAccount(generatePrivateKey());

const client = await createAccountClient({
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  chain: mainnet,
  client: publicClient,
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  paymaster,
  signer,
  type: "ecdsa",
});

const webAuthnSessionKey = await toWebAuthnKey({
  mode: WebAuthnMode.Register,
  passkeyName: "passkey name",
  passkeyServerHeaders: {},
  passkeyServerUrl: "YOUR_PASSKEY_SERVER_URL",
});

const sessionKey = await createSessionKey({
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [
    // Policies for this session key
  ],
  signer,
  type: "passkey",
  webAuthnSessionKey,
});

const serializedAccount = sessionKey.serializedAccounts[0]
  ?.serializedAccount as string;

const sessionKeyClient = await createSessionKeyClient({
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  chain: mainnet,
  client: publicClient,
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  serializedAccount,
  type: "passkey",
  webAuthnKey: webAuthnSessionKey,
});

// Use this to get the session key to send transactions.

The Bundler URL above is a public endpoint. Please do not use it in production as you will likely be rate-limited. Consider using Pimlico's Bundler, Biconomy's Bundler, or another Bundler service.


Multichain note

Passkey session keys do not support multi-chain signing. If you want the same session key across multiple chains, you must approve once per chain (N prompts for N chains). For a single approval across many chains, use an ECDSA session key with an ECDSA smart account.


Policies

Policies define the conditions under which a session key can sign UserOps. See Policies for detailed policy builders and examples.


Parameters

type

  • Value: "passkey"
index.ts
const sessionKey = await createSessionKey({
  type: "passkey", 
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [],
  signer,
  webAuthnSessionKey,
});

accountType

  • Value: "ecdsa"
index.ts
const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa", 
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [],
  signer,
  webAuthnSessionKey,
});

webAuthnSessionKey

  • Type: WebAuthnKey
index.ts
const webAuthnSessionKey = await toWebAuthnKey({
  mode: WebAuthnMode.Register,
  passkeyName: "passkey name",
  passkeyServerHeaders: {},
  passkeyServerUrl: "YOUR_PASSKEY_SERVER_URL",
});

const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [],
  signer,
  webAuthnSessionKey, 
});

clients

  • Type: Client[]
index.ts
const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient], 
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [],
  signer,
  webAuthnSessionKey,
});

signer

  • Type: Signer
index.ts
const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [],
  signer, 
  webAuthnSessionKey,
});

policies

index.ts
const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [/* ... */], 
  signer,
  webAuthnSessionKey,
});

entrypointVersion

  • Type: EntrypointVersion => "0.6" | "0.7" | "0.8" | "0.9"
index.ts
import { EntryPointVersion } from "viem/account-abstraction"; 
type EntryPointVersion = "0.6" | "0.7" | "0.8" | "0.9"
const = await createSessionKey({ : "passkey", : "ecdsa", : [publicClient], : "0.7", : "0.3.2", : [], , , });

kernelVersion

  • Type: KernelVersion => "0.0.2" | "0.2.2" | "0.2.3" | "0.2.4" | "0.3.1" | "0.3.2" | "0.3.3"

Note: Kernel 0.2.x supports only Entrypoint 0.6. For Kernel 0.3.x, you can use Entrypoint 0.7 or 0.8.

index.ts
const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2", 
  policies: [],
  signer,
  webAuthnSessionKey,
});

index

index.ts
const sessionKey = await createSessionKey({
  type: "passkey",
  accountType: "ecdsa",
  clients: [publicClient],
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  policies: [],
  signer,
  webAuthnSessionKey,
  index: 0n, 
});

serializedAccount

  • Type: string
index.ts
const serializedAccount = sessionKey.serializedAccounts[0]
  ?.serializedAccount as string;

const sessionKeyClient = await createSessionKeyClient({
  type: "passkey",
  client: publicClient,
  chain: mainnet,
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  serializedAccount, 
  webAuthnKey: webAuthnSessionKey,
});

webAuthnKey

  • Type: WebAuthnKey
  • Use the same WebAuthn key you created for the session key.
index.ts
const sessionKeyClient = await createSessionKeyClient({
  type: "passkey",
  client: publicClient,
  chain: mainnet,
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  serializedAccount,
  webAuthnKey: webAuthnSessionKey, 
});

client

  • Type: Client<HttpTransport, Chain, JsonRpcAccount | LocalAccount | undefined>
index.ts
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";

export const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
});

bundlerTransport

  • Type: Transport
index.ts
const sessionKeyClient = await createSessionKeyClient({
  type: "passkey",
  client: publicClient,
  chain: mainnet,
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  serializedAccount,
  webAuthnKey: webAuthnSessionKey,
});

chain

  • Type: Chain
index.ts
import { mainnet } from "viem/chains";

paymaster

  • Type: PaymasterClient
index.ts
import { createPaymasterClient } from "viem/account-abstraction"; 
import { createSessionKeyClient } from "@namera-ai/sdk/session-key";

const paymaster = createPaymasterClient({ 
  transport: http("ZERO_DEV_PAYMASTER_URL"), 
}); 

const sessionKeyClient = await createSessionKeyClient({
  type: "passkey",
  client: publicClient,
  chain: mainnet,
  bundlerTransport: http("https://public.pimlico.io/v2/1/rpc"), // Public Pimlico RPC
  entrypointVersion: "0.7",
  kernelVersion: "0.3.2",
  serializedAccount,
  webAuthnKey: webAuthnSessionKey,
  paymaster: paymasterClient, 
});