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

Quickstart

Integrate smart accounts with passkey authentication in minutes. Your users get seedless wallets that support batched transactions, stablecoin gas payments, and optional gas sponsorship - all through a familiar Web3 interface.

What you'll build:
  • Issue Accounts - Users create accounts with passkeys, no seed phrases
  • Passkey Auth - Secure, passwordless WebAuthn authentication
  • Send & Receive - Standard transaction support with gas sponsorship
  • Batch Transactions - Multiple operations in a single approval

1. Integration Path

Pick your integration method:

ApproachBest For
WagmiReact apps already using wagmi connectors. Instant integration with familiar hooks.
Core SDKCustom implementations, non-React apps, or when you need direct control over account creation and signing.

2. Install the SDK

Wagmi:
npm
npm install @jaw.id/wagmi wagmi viem @tanstack/react-query
Core SDK:
npm
npm install @jaw.id/core viem

3. Create API Key

Create an API key to authenticate your application's SDK requests for account deployment, identity operations, and transaction routing.

Get your API key at dashboard.jaw.id

4. Configure the SDK

Initialize JAW with your API key, app details, and default chain. The appName and appLogoUrl appear in user-facing interfaces during authentication. The defaultChainId specifies the primary chain for account operations. You can override this per operation by passing a chainId parameter, or by using wallet_switchEthereumChain.

Wagmi
// 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 App',
      appLogoUrl: 'https://myapp.com/logo.png',
      defaultChainId: 1, // Ethereum mainnet
    }),
  ],
  transports: {
    [mainnet.id]: http(),
    [base.id]: http(),
  },
});

5. Connect and Display Account

Add wallet connection to your app. Users authenticate with passkeys and see their account details.

Wagmi
import { useAccount } from 'wagmi';
import { useConnect, useDisconnect } from '@jaw.id/wagmi';
import { config } from './config';
 
function ConnectButton() {
  const { address, isConnected } = useAccount();
  const { mutate: connect, isPending } = useConnect();
  const { mutate: disconnect } = useDisconnect();
 
  if (isConnected) {
    return (
      <div>
        <p>Connected: {address}</p>
        <button onClick={() => disconnect({})}>
          Disconnect
        </button>
      </div>
    );
  }
 
  return (
    <button
      onClick={() => connect({ connector: config.connectors[0] })}
      disabled={isPending}
    >
      {isPending ? 'Connecting...' : 'Connect Wallet'}
    </button>
  );
}

6. Send Transactions

Send single and batched transactions by providing recipient addresses and amounts. The SDK manages gas estimation, routing, and confirmation. Batched calls bundle multiple actions into one approval for better UX.

Wagmi
import { useSendCalls } from 'wagmi';
import { parseEther, encodeFunctionData } from 'viem';
 
function SendTransaction() {
  const { sendCalls, isPending } = useSendCalls();
 
  // Single transaction
  const handleSend = () => {
    sendCalls({
      calls: [{
        to: '0xRecipientAddress...',
        value: parseEther('0.01'),
      }],
    });
  };
 
  // Batch multiple transactions
  const handleBatchSend = () => {
    sendCalls({
      calls: [
        { to: '0xAlice...', value: parseEther('0.01') },
        { to: '0xBob...', value: parseEther('0.02') },
      ],
    });
  };
 
  return (
    <div>
      <button onClick={handleSend} disabled={isPending}>
        Send ETH
      </button>
      <button onClick={handleBatchSend} disabled={isPending}>
        Batch Send
      </button>
    </div>
  );
}

7. Disconnect Account

Disconnect the wallet from JAW to end the session.

Wagmi
import { useDisconnect } from '@jaw.id/wagmi';
 
function DisconnectButton() {
  const { mutate: disconnect } = useDisconnect();
 
  return (
    <button onClick={() => disconnect({})}>
      Disconnect
    </button>
  );
}

Next Steps

Now that you have the basics working, explore these features:

Related