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

# Multi-chain sessions

> Authorize sessions for several chains with one account-owner signature.

A session key is enabled per chain. Build one session for each chain, then authorize them together so you can activate each session without another account-owner prompt.

Follow the [Custom signer quickstart](/wallets/custom-signer/quickstart) before using this guide. The examples assume you already have `rhinestone`, `rhinestoneAccount`, and the session owner account.

<Steps>
  <Step title="Create the sessions">
    Define every session before asking the account owner to sign. A session's chain is part of its authorization:

    Examples on this page use `@rhinestone/sdk`, where `rhinestone` is the `RhinestoneSDK` instance from [Create a session with a custom setup](/wallets/session-keys/custom-setup/create-a-session).

    ```ts theme={null}
    import { baseSepolia, optimismSepolia } from "viem/chains";

    const sessions = await Promise.all([
      rhinestone.createSession({
        chain: baseSepolia,
        owners: {
          type: "ecdsa",
          accounts: [sessionOwnerAccount],
        },
      }),
      rhinestone.createSession({
        chain: optimismSepolia,
        owners: {
          type: "ecdsa",
          accounts: [sessionOwnerAccount],
        },
      }),
    ]);
    ```

    Each session can use different owners and restrictions. Reusing the same session owner does not make the on-chain sessions interchangeable.
  </Step>

  <Step title="Sign once">
    Get the authorization details, then ask the account owner for one signature:

    ```ts theme={null}
    const sessionDetails = await rhinestoneAccount.getSessionDetails(sessions);
    const enableSignature =
      await rhinestoneAccount.signEnableSession(sessionDetails);
    ```

    `getSessionDetails` reads the required nonce on every session chain and builds one `MultiChainSession` typed-data message. Store the resolved `sessions`, `sessionDetails.hashesAndChainIds`, signature, and indexes together. Rebuilding or reordering the array changes which index enables which session.
  </Step>

  <Step title="Enable and use each session">
    Pass a per-chain session map when one transaction can touch several chains. `enableData` lets the first operation on a chain enable and use that chain's session in one flow:

    ```ts theme={null}
    const signers = {
      type: "session" as const,
      sessions: {
        [baseSepolia.id]: {
          session: sessions[0],
          enableData: {
            userSignature: enableSignature,
            hashesAndChainIds: sessionDetails.hashesAndChainIds,
            sessionToEnableIndex: 0,
          },
        },
        [optimismSepolia.id]: {
          session: sessions[1],
          enableData: {
            userSignature: enableSignature,
            hashesAndChainIds: sessionDetails.hashesAndChainIds,
            sessionToEnableIndex: 1,
          },
        },
      },
    };

    const prepared = await rhinestoneAccount.prepareTransaction({
      sourceChains: [baseSepolia],
      targetChain: optimismSepolia,
      calls,
      tokenRequests,
      signers,
    });
    const signed = await rhinestoneAccount.signTransaction(prepared);
    const result = await rhinestoneAccount.submitTransaction(signed);
    await rhinestoneAccount.waitForExecution(result);
    ```

    Configure a session for every EVM source chain and for the EVM destination where the account executes. The SDK fails before signing if a required chain has no session.
  </Step>
</Steps>

## Enable a session separately

Use the same signed details to enable one session in an account-owner transaction before the session is used:

```ts theme={null}
import { enableSession } from "@rhinestone/sdk/actions/smart-sessions";

const prepared = await rhinestoneAccount.prepareTransaction({
  chain: baseSepolia,
  calls: [
    enableSession(
      sessions[0],
      enableSignature,
      sessionDetails.hashesAndChainIds,
      0,
    ),
  ],
});
const signed = await rhinestoneAccount.signTransaction(prepared);
const result = await rhinestoneAccount.submitTransaction(signed);
await rhinestoneAccount.waitForExecution(result);
```

After a session is enabled, omit its `enableData`. Check first with `rhinestoneAccount.isSessionEnabled(session)` when your application does not track activation reliably.

## Constraints

* A session authorization is chain-specific even when its owner and permissions match another chain.
* Session keys cannot sign a chain-agnostic origin payload whose one signature must validate across several chains. Split that operation into per-chain intents.
* Accounts using the K1 validator cannot sign one multi-chain session authorization. Sign and enable one chain at a time.
* Keep the original session order. `sessionToEnableIndex` selects an entry in the signed `hashesAndChainIds` set.

<Note>
  Cross-chain permits restrict which assets a session may move between chains.
  They do not enable the session on those chains. Configure both features when
  you need both behaviors. See [Cross-chain
  permits](/wallets/session-keys/custom-setup/policies/cross-chain).
</Note>
