Skip to main content

Prerequisites

  • A Cavos App ID from the Dashboard
  • A React or Next.js application

Installation

npm install @cavos/react starknet

Setup

1. Configure the Provider

Wrap your application with CavosProvider:
// app/layout.tsx or _app.tsx
import { CavosProvider } from '@cavos/react';

export default function RootLayout({ children }) {
  return (
    <CavosProvider
      config={{
        appId: 'your-app-id',
        network: 'sepolia', // or 'mainnet'
      }}
    >
      {children}
    </CavosProvider>
  );
}

2. Login and Create Session

Users authenticate once and a session is created automatically:
'use client';
import { useCavos, useSession } from '@cavos/react';

// Define what the session can do
const SESSION_POLICY = {
  allowedMethods: [
    { contractAddress: '0x...your-contract', selector: 'transfer' },
    { contractAddress: '0x...your-contract', selector: 'approve' },
  ],
  expiresAt: Date.now() + 60 * 60 * 1000, // 1 hour
};

export function LoginButton() {
  const { login, isAuthenticated, address, isLoading } = useCavos();
  const { createSession, hasActiveSession } = useSession();

  const handleLogin = async () => {
    // 1. Authenticate user
    await login('google');
    
    // 2. Create session (user signs once here)
    await createSession(SESSION_POLICY);
    
    // ✓ Private key is now cleared from memory
    // ✓ All future transactions use session key
  };

  if (isLoading) return <button disabled>Loading...</button>;

  if (isAuthenticated && address) {
    return (
      <div>
        <p>Connected: {address.slice(0, 6)}...{address.slice(-4)}</p>
        <p>Session: {hasActiveSession ? '✅ Active' : '❌ Inactive'}</p>
      </div>
    );
  }

  return (
    <button onClick={handleLogin}>
      Login with Google
    </button>
  );
}

3. Execute Transactions (No Signature Required)

After session creation, all transactions are signed automatically:
import { useCavos, useSession } from '@cavos/react';

function TransferButton() {
  const { execute } = useCavos();
  const { hasActiveSession } = useSession();

  const handleTransfer = async () => {
    // No wallet popup! Session key signs automatically
    const txHash = await execute({
      contractAddress: '0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
      entrypoint: 'transfer',
      calldata: [recipientAddress, amount, '0'],
    });
    console.log('Transaction:', txHash);
  };

  return (
    <button onClick={handleTransfer} disabled={!hasActiveSession}>
      {hasActiveSession ? 'Send (Signature-Free)' : 'Create Session First'}
    </button>
  );
}

The Flow

Next Steps