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

# Parallel transactions

> Use ERC-7579 two-dimensional nonces to send independent UserOperations concurrently.

A regular EOA has a single nonce, so transactions strictly serialize. ERC-7579 smart accounts have a **two-dimensional nonce**: a `nonceKey` (the lane) and a `nonce` (the position inside that lane). Different lanes are independent, so you can send UserOperations on different lanes in parallel.

<Note>
  Source: [`StartaleGroup/scs-aa-sdk`](https://github.com/StartaleGroup/scs-aa-sdk).
</Note>

## When to use parallel lanes

| Use case                                                               | Why a lane helps                                                                            |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Independent flows that should not block each other (e.g. claim + swap) | A revert or delay on lane A does not block lane B.                                          |
| Multiple worker processes signing for the same account                 | Each worker owns a distinct lane, so they can submit concurrently without nonce collisions. |
| High-throughput dapps batching on behalf of many users                 | One lane per user keeps their UserOperations independent.                                   |

## Mental model

```mermaid theme={null}
flowchart LR
  subgraph Lane1["nonceKey 1"]
    A1[UO 0] --> A2[UO 1] --> A3[UO 2]
  end
  subgraph Lane2["nonceKey 2"]
    B1[UO 0] --> B2[UO 1]
  end
  subgraph Lane3["nonceKey 3"]
    C1[UO 0]
  end
```

Within a lane, UserOperations are still ordered. Across lanes, they are independent.

## Read a lane nonce

```ts theme={null}
const nonceLane1 = await smartAccountClient.account.getNonce({ key: 1n })
const nonceLane2 = await smartAccountClient.account.getNonce({ key: 2n })
```

| Symbol                      | Source                 | Role                                                                                              |
| --------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------- |
| `account.getNonce({ key })` | `@startale-scs/aa-sdk` | Reads the next available nonce for the given lane. `key` is a `bigint`; `0n` is the default lane. |

## Send two UserOperations in parallel

Pass each lane's nonce when calling `sendUserOperation`. Do **not** await the calls back to back; fire them together so the bundler sees both at once.

```ts theme={null}
const [hash1, hash2] = await Promise.all([
  smartAccountClient.sendUserOperation({
    calls: [{ to: target, data: callA, value: 0n }],
    nonce: nonceLane1,
  }),
  smartAccountClient.sendUserOperation({
    calls: [{ to: target, data: callB, value: 0n }],
    nonce: nonceLane2,
  }),
])

const [receipt1, receipt2] = await Promise.all([
  smartAccountClient.waitForUserOperationReceipt({ hash: hash1 }),
  smartAccountClient.waitForUserOperationReceipt({ hash: hash2 }),
])
```

<Tip>
  If you fire many UserOperations on a single lane, the bundler will queue them strictly in order; one stuck UserOp blocks the rest of the lane. Use lanes whenever ordering between two flows does not matter.
</Tip>

## Pick lane keys deliberately

The `key` is a `uint192` packed into the nonce, which leaves plenty of room for application-defined schemes:

| Strategy                                      | Example                                           |
| --------------------------------------------- | ------------------------------------------------- |
| Stable lane per worker                        | `key = workerId`                                  |
| Stable lane per user inside a service account | `key = hash(userId) >> 64`                        |
| One lane per business flow                    | `key = 1n` for swaps, `key = 2n` for claims, etc. |

The lane key is opaque to the EntryPoint; pick whatever scheme keeps your flows from colliding.

## Caveats

* Lanes are **per smart account**. Two different smart accounts already have independent nonces; you only need lanes within a single account.
* Lane state lives onchain. Bumping `key` does not cost gas, but the first UserOp on a brand-new lane still pays whatever gas the EntryPoint charges for storage initialisation.
* The paymaster does not care about lanes; sponsored and ERC-20 paymaster flows work the same way on any lane.

## Next steps

<CardGroup cols={2}>
  <Card title="Contract interactions" icon="layer-group" href="/aa-sdk/tutorials/contract-interactions">
    Combine batched calls inside a single UserOperation with parallel UserOperations across lanes.
  </Card>

  <Card title="Smart sessions" icon="key-skeleton" href="/aa-sdk/tutorials/smart-sessions">
    Run scoped session UserOperations on dedicated lanes.
  </Card>

  <Card title="Sponsored paymaster" icon="gas-pump" href="/aa-sdk/tutorials/sponsored-tx">
    Sponsor every UserOperation across all lanes.
  </Card>

  <Card title="EIP-7702" icon="cpu" href="/aa-sdk/eip7702">
    Use lane nonces on a delegated EOA-as-smart-account.
  </Card>
</CardGroup>
