> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chipipay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Keys

> Enable frictionless transactions without requiring user approval for every action

## What Are Session Keys?

Session keys are temporary keypairs that let your app execute transactions on behalf of a user without requiring their private key for every action. Instead of prompting users to sign each transaction, you register a session key on-chain with specific permissions (time limit, call limit, allowed functions) and then use it silently.

This enables **gasless, popup-free UX** for gaming, DeFi automation, social apps, and subscriptions.

<Info>
  Session keys only work with **CHIPI wallets** (SNIP-9 compatible). They are not supported on READY wallets.
</Info>

## When to Use Session Keys

| Use Case            | Why Sessions Help                                 |
| ------------------- | ------------------------------------------------- |
| **Gaming**          | Players make moves without wallet popups          |
| **DeFi automation** | Yield optimizers execute strategies automatically |
| **Social dApps**    | Post, like, comment without friction              |
| **Subscriptions**   | Recurring payments without manual approval        |
| **Airdrops**        | Zero-friction claiming                            |

## How It Works

```
1. Create    → Generate a session keypair locally (client-side only)
2. Register  → Register the session on the CHIPI wallet contract (one-time, requires owner signature)
3. Execute   → Use the session key to sign transactions (no owner key needed)
4. Monitor   → Check remaining calls and expiration
5. Revoke    → Revoke the session on logout or expiration
```

The SDK handles the signature format difference automatically:

* **Owner signature**: `[r, s]` (2 elements)
* **Session signature**: `[sessionPubKey, r, s, validUntil]` (4 elements)

## Frontend Implementation

### 1. Create a Session Key

```typescript theme={null}
import { useCreateSessionKey } from "@chipi-stack/nextjs";

function StartSession() {
  const { createSessionKeyAsync, isLoading } = useCreateSessionKey();

  const handleStart = async () => {
    const session = await createSessionKeyAsync({
      encryptKey: userPin,
      durationSeconds: 3600, // 1 hour
    });

    // Store in client-side storage only (NEVER in your database)
    localStorage.setItem("chipiSession", JSON.stringify(session));
  };
}
```

### 2. Register On-Chain

```typescript theme={null}
import { useAddSessionKeyToContract } from "@chipi-stack/nextjs";

function RegisterSession() {
  const { addSessionKeyToContractAsync } = useAddSessionKeyToContract();

  const handleRegister = async () => {
    const session = JSON.parse(localStorage.getItem("chipiSession")!);
    const bearerToken = await getBearerToken();

    await addSessionKeyToContractAsync({
      params: {
        encryptKey: userPin,
        wallet: { publicKey: wallet.publicKey, encryptedPrivateKey: wallet.encryptedPrivateKey, walletType: "CHIPI" },
        sessionConfig: {
          sessionPublicKey: session.publicKey,
          validUntil: session.validUntil,
          maxCalls: 100,
          allowedEntrypoints: [], // empty = all functions allowed
        },
      },
      bearerToken,
    });
  };
}
```

### 3. Execute Transactions

```typescript theme={null}
import { useExecuteWithSession } from "@chipi-stack/nextjs";

const USDC = "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb";

function TransferWithSession() {
  const { executeWithSessionAsync, isLoading } = useExecuteWithSession();

  const handleTransfer = async (recipient: string, amount: string) => {
    const session = JSON.parse(localStorage.getItem("chipiSession")!);
    const bearerToken = await getBearerToken();

    const txHash = await executeWithSessionAsync({
      params: {
        encryptKey: userPin,
        wallet: { publicKey: wallet.publicKey, encryptedPrivateKey: wallet.encryptedPrivateKey, walletType: "CHIPI" },
        session,
        calls: [{
          contractAddress: USDC,
          entrypoint: "transfer",
          calldata: [recipient, amount, "0x0"],
        }],
      },
      bearerToken,
    });
  };
}
```

### 4. Check Session Status

```typescript theme={null}
import { useGetSessionData } from "@chipi-stack/nextjs";

function SessionStatus() {
  const { data: sessionData } = useGetSessionData({
    walletAddress: wallet.publicKey,
    sessionPublicKey: session.publicKey,
  });

  if (sessionData?.isActive) {
    return <p>{sessionData.remainingCalls} calls remaining</p>;
  }
  return <p>Session expired or revoked</p>;
}
```

### 5. Revoke on Logout

```typescript theme={null}
import { useRevokeSessionKey } from "@chipi-stack/nextjs";

function LogoutButton() {
  const { revokeSessionKeyAsync } = useRevokeSessionKey();

  const handleLogout = async () => {
    const session = JSON.parse(localStorage.getItem("chipiSession")!);

    try {
      await revokeSessionKeyAsync({
        params: {
          encryptKey: userPin,
          wallet: { publicKey: wallet.publicKey, encryptedPrivateKey: wallet.encryptedPrivateKey, walletType: "CHIPI" },
          sessionPublicKey: session.publicKey,
        },
        bearerToken: await getBearerToken(),
      });
    } catch {
      // Continue with logout even if revoke fails
    }

    localStorage.removeItem("chipiSession");
    await authProvider.signOut();
  };
}
```

## Session Configuration

| Parameter            | Type      | Description                                             |
| -------------------- | --------- | ------------------------------------------------------- |
| `sessionPublicKey`   | string    | Public key from `createSessionKey()`                    |
| `validUntil`         | number    | Unix timestamp (seconds) when session expires           |
| `maxCalls`           | number    | Maximum transactions allowed (decrements with each use) |
| `allowedEntrypoints` | string\[] | Whitelisted function selectors. Empty = all allowed     |

### Restricting Permissions

For security, whitelist specific entrypoints:

```typescript theme={null}
sessionConfig: {
  sessionPublicKey: session.publicKey,
  validUntil: session.validUntil,
  maxCalls: 10,
  allowedEntrypoints: [
    "0x83afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e", // transfer
    "0x219209e083275171774dab1df80982e9df2096516f06319c5c6d71ae0a8480c", // approve
  ],
}
```

## Security Best Practices

<Danger>
  **Never store session keys in your backend database.** This defeats self-custodial security. Store only in client-side secure storage.
</Danger>

| Platform         | Recommended Storage                |
| ---------------- | ---------------------------------- |
| **Web**          | `localStorage` or `sessionStorage` |
| **iOS**          | Secure Enclave / Keychain          |
| **Android**      | Android Keystore                   |
| **React Native** | `expo-secure-store`                |

1. **Always revoke on logout** - Never leave active sessions
2. **Set short durations** - 1-6 hours, not days
3. **Limit maxCalls** - Set realistic limits based on expected usage
4. **Whitelist entrypoints** - Restrict to only the functions your app needs
5. **Monitor remaining calls** - Create new sessions before exhaustion

## Related

* [Session Hooks Reference](/sdk/nextjs/hooks/use-create-session-key) - Individual hook API docs
* [Backend Sessions Quickstart](/sdk/backend/sessions-quickstart) - Server-side implementation
* [Backend Sessions Methods](/sdk/backend/methods/sessions) - Detailed backend API

<Tip>
  Need help? Join our [Telegram Community](https://t.me/+e2qjHEOwImkyZDVh) for support.
</Tip>
