Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Getting Started

What is JAW?

The JAW SDK is a TypeScript library for building identity-first smart accounts on EVM chains: passkey-authenticated, programmable, and extensible through delegated permissions.

Smart wallets are blockchain accounts controlled by smart contracts instead of private keys. This enables powerful features like:

  • Gasless transactions - Users don't need ETH to pay for gas
  • Batch operations - Execute multiple actions in a single transaction
  • Programmable permissions - Grant limited access to third parties

Passkeys replace seed phrases and passwords with biometric authentication (Face ID, fingerprint, or device PIN). Your users get:

  • No seed phrases to lose or steal
  • Phishing-resistant authentication
  • Cross-device sync via iCloud/Google

Installation

npm
npm install @jaw.id/wagmi wagmi @tanstack/react-query

Quick Start

1. Configure Wagmi

Create your wagmi config with the JAW connector:

// config.ts
import { createConfig, http } from 'wagmi';
import { mainnet, base } from 'wagmi/chains';
import { jaw } from '@jaw.id/wagmi';
 
export const config = createConfig({
  chains: [mainnet, base],
  connectors: [
    jaw({
      apiKey: 'your-api-key',
      appName: 'My DApp',
      appLogoUrl: 'https://my-dapp.com/logo.png',
    }),
  ],
  transports: {
    [mainnet.id]: http(),
    [base.id]: http(),
  },
});

2. Set Up Providers

Wrap your app with the required providers:

// App.tsx
import { WagmiProvider } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { config } from './config';
 
const queryClient = new QueryClient();
 
function App({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    </WagmiProvider>
  );
}

3. Connect & Interact

import { useAccount, useSendTransaction } from 'wagmi';
import { useConnect, useDisconnect } from '@jaw.id/wagmi';
import { parseEther } from 'viem';
import { config } from './config';
 
function WalletButton() {
  const { address, isConnected } = useAccount();
  const { mutate: connect, isPending } = useConnect();
  const { mutate: disconnect } = useDisconnect();
  const { sendTransaction } = useSendTransaction();
 
  if (isConnected) {
    return (
      <div>
        <p>Connected: {address}</p>
        <button onClick={() => sendTransaction({
          to: '0x...',
          value: parseEther('0.01')
        })}>
          Send ETH
        </button>
        <button onClick={() => disconnect({})}>
          Disconnect
        </button>
      </div>
    );
  }
 
  return (
    <button
      onClick={() => connect({ connector: config.connectors[0] })}
      disabled={isPending}
    >
      {isPending ? 'Connecting...' : 'Connect Wallet'}
    </button>
  );
}

When users click "Connect Wallet", a popup appears for passkey authentication.

Using the Provider Directly

For non-React applications or advanced use cases, you can use the provider API directly:

import { JAW } from '@jaw.id/core';
 
const jaw = JAW.create({
  apiKey: 'your-api-key',
  appName: 'My DApp',
});
 
// EIP-1193 compatible provider
const accounts = await jaw.provider.request({
  method: 'wallet_connect',
});

See the Provider API Reference for all available methods.

Next Steps