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

# Smart Wallet SDK to Gasless SDK Migration (ERC4337)

> Migrate from @gelatonetwork/smartwallet to @gelatocloud/gasless with Kernel smart accounts and EIP-7702

<Warning>
  Gelato is **deprecating the Smart Wallet SDK** (`@gelatonetwork/smartwallet`) in favor of the new **Gasless SDK** (`@gelatocloud/gasless`). The old `prepareCalls` and `sendPreparedCalls` methods will no longer be available. Migrate to the Gasless SDK which supports Kernel smart accounts with EIP-7702 using ZeroDev SDK.
</Warning>

## What's Being Deprecated?

The following patterns from the Smart Wallet SDK will no longer be supported:

* `@gelatonetwork/smartwallet` package
* `@gelatonetwork/smartwallet/accounts` (kernel)
* `createGelatoSmartWalletClient` function
* `prepareCalls` and `sendPreparedCalls` methods

```typescript theme={null}
// DEPRECATED - Will no longer work
import {
  createGelatoSmartWalletClient,
  sponsored,
} from "@gelatonetwork/smartwallet";
import { kernel } from "@gelatonetwork/smartwallet/accounts";

const account = await kernel({
  owner: owner,
  client: publicClient,
  eip7702: true,
});

const swc = await createGelatoSmartWalletClient(client, {
  apiKey: API_KEY,
});

const preparedCalls = await swc.prepareCalls({
  payment: sponsored(),
  calls: [{ to, data, value: 0n }],
});

const response = await swc.sendPreparedCalls({ preparedCalls });
```

## Migration Overview

| Old (Smart Wallet SDK)                                | New (Gasless SDK + ZeroDev)                   |
| ----------------------------------------------------- | --------------------------------------------- |
| `@gelatonetwork/smartwallet`                          | `@gelatocloud/gasless` + `@zerodev/sdk`       |
| `kernel()` from `@gelatonetwork/smartwallet/accounts` | `createKernelAccount()` from `@zerodev/sdk`   |
| `createGelatoSmartWalletClient()`                     | `createGelatoBundlerClient()`                 |
| `prepareCalls()` + `sendPreparedCalls()`              | `sendUserOperation()`                         |
| Event-based status (`response.on('success')`)         | Await-based (`waitForUserOperationReceipt()`) |

## Migration Steps

<Steps>
  <Step title="Update Dependencies">
    Remove the old SDK and install the new packages:

    ```bash theme={null}
    # Remove old SDK
    npm uninstall @gelatonetwork/smartwallet

    # Install new SDKs
    npm install @gelatocloud/gasless @zerodev/sdk viem
    ```
  </Step>

  <Step title="Update Imports">
    **Before (Smart Wallet SDK):**

    ```typescript theme={null}
    import {
      createGelatoSmartWalletClient,
      type GelatoTaskStatus,
      sponsored,
    } from "@gelatonetwork/smartwallet";
    import { kernel } from "@gelatonetwork/smartwallet/accounts";
    ```

    **After (Gasless SDK + ZeroDev):**

    ```typescript theme={null}
    import { createGelatoBundlerClient } from "@gelatocloud/gasless";
    import { createKernelAccount } from "@zerodev/sdk";
    import { KERNEL_V3_3 } from "@zerodev/sdk/constants";
    import { entryPoint07Address } from "viem/account-abstraction";
    ```
  </Step>

  <Step title="Update Account Creation">
    **Before (Smart Wallet SDK):**

    ```typescript theme={null}
    import { kernel } from "@gelatonetwork/smartwallet/accounts";

    const account = await kernel({
      owner: owner,
      client: publicClient,
      eip7702: true,
    });
    ```

    **After (ZeroDev SDK with EIP-7702):**

    ```typescript theme={null}
    import { createKernelAccount } from "@zerodev/sdk";
    import { KERNEL_V3_3 } from "@zerodev/sdk/constants";
    import { entryPoint07Address } from "viem/account-abstraction";

    const account = await createKernelAccount(client, {
      entryPoint: {
        address: entryPoint07Address,
        version: "0.7",
      },
      kernelVersion: KERNEL_V3_3,
      eip7702Account: owner,
    });
    ```
  </Step>

  <Step title="Update Client Initialization">
    **Before (Smart Wallet SDK):**

    ```typescript theme={null}
    const client = createWalletClient({
      account,
      chain: chain,
      transport: http(),
    });

    const swc = await createGelatoSmartWalletClient(client, {
      apiKey: API_KEY,
    });
    ```

    **After (Gasless SDK Bundler Client):**

    ```typescript theme={null}
    const bundler = await createGelatoBundlerClient({
      account,
      apiKey: GELATO_API_KEY,
      client,
    });
    ```
  </Step>

  <Step title="Update Transaction Sending">
    **Before (prepareCalls + sendPreparedCalls with events):**

    ```typescript theme={null}
    const preparedCalls = await swc.prepareCalls({
      payment: sponsored(),
      calls: [
        {
          to: CONTRACT_ADDRESS,
          data: callData,
          value: 0n,
        },
      ],
    });

    const response = await swc.sendPreparedCalls({
      preparedCalls,
    });

    console.log(`Your Gelato id is: ${response.id}`);

    // Event-based status handling
    response.on("success", (status: GelatoTaskStatus) => {
      console.log(`Transaction hash: ${status.transactionHash}`);
    });
    response.on("error", (error: Error) => {
      console.error(`Transaction failed: ${error.message}`);
    });
    ```

    **After (sendUserOperation with EIP-7702 authorization):**

    ```typescript theme={null}
    // Get EIP-7702 authorization if needed (first transaction only)
    const authorization = await account.eip7702Authorization?.();

    // Send the user operation
    const hash = await bundler.sendUserOperation({
      calls: [
        {
          to: CONTRACT_ADDRESS,
          data: callData,
        },
      ],
      authorization,
    });

    console.log(`User operation hash: ${hash}`);

    // Wait for receipt
    const { receipt } = await bundler.waitForUserOperationReceipt({ hash });
    console.log(`Transaction hash: ${receipt.transactionHash}`);
    ```
  </Step>

  <Step title="Update Batching Transactions">
    Batching works similarly - just pass multiple calls:

    **Before:**

    ```typescript theme={null}
    const preparedCalls = await swc.prepareCalls({
      payment: sponsored(),
      calls: [
        { to: token1, data: approveData, value: 0n },
        { to: swap, data: swapData, value: 0n },
        { to: token2, data: transferData, value: 0n }
      ],
    });
    const response = await swc.sendPreparedCalls({ preparedCalls });
    ```

    **After:**

    ```typescript theme={null}
    const hash = await bundler.sendUserOperation({
      calls: [
        { to: token1, data: approveData },
        { to: swap, data: swapData },
        { to: token2, data: transferData }
      ],
      authorization,
    });

    const { receipt } = await bundler.waitForUserOperationReceipt({ hash });
    ```
  </Step>
</Steps>

## Key Differences

### Architecture

| Aspect              | Smart Wallet SDK                     | Gasless SDK + ZeroDev                       |
| ------------------- | ------------------------------------ | ------------------------------------------- |
| **Account Setup**   | `kernel({ eip7702: true })`          | `createKernelAccount({ eip7702Account })`   |
| **Client**          | `createGelatoSmartWalletClient`      | `createGelatoBundlerClient`                 |
| **Sending**         | `prepareCalls` + `sendPreparedCalls` | `sendUserOperation`                         |
| **Status Handling** | Event-based (`.on('success')`)       | Await-based (`waitForUserOperationReceipt`) |
| **EIP-7702 Auth**   | Automatic                            | Explicit via `eip7702Authorization()`       |

### EIP-7702 Authorization

The new SDK requires explicit handling of EIP-7702 authorization for the first transaction:

```typescript theme={null}
// ZeroDev SDK automatically checks if EOA needs authorization
const authorization = await account.eip7702Authorization?.();

// Pass authorization with the user operation (only needed once)
const hash = await bundler.sendUserOperation({
  calls: [...],
  authorization, // undefined if already delegated
});
```

### Status Handling

**Before (Event-based):**

```typescript theme={null}
response.on("success", (status: GelatoTaskStatus) => {
  console.log(`Hash: ${status.transactionHash}`);
});
response.on("error", (error: Error) => {
  console.error(`Failed: ${error.message}`);
});
```

**After (Await-based):**

```typescript theme={null}
const hash = await bundler.sendUserOperation({ calls, authorization });
const { receipt } = await bundler.waitForUserOperationReceipt({ hash });
console.log(`Hash: ${receipt.transactionHash}`);
```

### Payment Methods

The new SDK no longer requires explicitly passing `sponsored()` — transactions are sponsored by default:

```typescript theme={null}
const bundler = await createGelatoBundlerClient({
  account,
  apiKey: GELATO_API_KEY,
  client,
});
```

## Complete Migration Example

<Tabs>
  <Tab title="Before (Smart Wallet SDK)">
    ```typescript theme={null}
    import {
      createGelatoSmartWalletClient,
      type GelatoTaskStatus,
      sponsored,
    } from "@gelatonetwork/smartwallet";
    import {
      http,
      type Hex,
      createWalletClient,
      createPublicClient,
    } from "viem";
    import { privateKeyToAccount } from "viem/accounts";
    import { kernel } from "@gelatonetwork/smartwallet/accounts";
    import { baseSepolia } from "viem/chains";

    const API_KEY = process.env.GELATO_API_KEY as string;
    const privateKey = process.env.PRIVATE_KEY as Hex;
    const owner = privateKeyToAccount(privateKey);

    const publicClient = createPublicClient({
      chain: baseSepolia,
      transport: http(),
    });

    (async () => {
      // Create Kernel account with EIP-7702
      const account = await kernel({
        owner: owner,
        client: publicClient,
        eip7702: true,
      });

      console.log("Account address:", account.address);

      const client = createWalletClient({
        account,
        chain: baseSepolia,
        transport: http(),
      });

      const swc = await createGelatoSmartWalletClient(client, {
        apiKey: API_KEY,
      });

      // Prepare calls
      const preparedCalls = await swc.prepareCalls({
        payment: sponsored(),
        calls: [{
          to: "0xEEeBe2F778AA186e88dCf2FEb8f8231565769C27",
          data: "0xd09de08a", // increment()
          value: 0n,
        }],
      });

      // Send prepared calls
      const response = await swc.sendPreparedCalls({ preparedCalls });

      console.log(`Gelato ID: ${response.id}`);

      // Event-based status handling
      response.on("success", (status: GelatoTaskStatus) => {
        console.log(`Transaction hash: ${status.transactionHash}`);
        process.exit(0);
      });
      response.on("error", (error: Error) => {
        console.error(`Failed: ${error.message}`);
        process.exit(1);
      });
    })();
    ```
  </Tab>

  <Tab title="After (Gasless SDK + ZeroDev)">
    ```typescript theme={null}
    import { createGelatoBundlerClient } from "@gelatocloud/gasless";
    import { createKernelAccount } from "@zerodev/sdk";
    import { KERNEL_V3_3 } from "@zerodev/sdk/constants";
    import { createPublicClient, type Hex, http } from "viem";
    import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
    import { baseSepolia } from "viem/chains";
    import { entryPoint07Address } from "viem/account-abstraction";

    const GELATO_API_KEY = process.env.GELATO_API_KEY as string;
    const PRIVATE_KEY = process.env.PRIVATE_KEY as Hex;

    (async () => {
      const owner = privateKeyToAccount(
        (PRIVATE_KEY ?? generatePrivateKey()) as Hex
      );

      console.log("EOA address:", owner.address);

      const client = createPublicClient({
        chain: baseSepolia,
        transport: http(),
      });

      // Create EIP-7702 Kernel Smart Account using ZeroDev SDK
      const account = await createKernelAccount(client, {
        entryPoint: {
          address: entryPoint07Address,
          version: "0.7",
        },
        kernelVersion: KERNEL_V3_3,
        eip7702Account: owner,
      });

      console.log("Kernel Smart Account (EIP-7702):", account.address);
      console.log("EIP-7702 enabled:", account.address === owner.address);

      // Create Gelato Bundler Client
      const bundler = await createGelatoBundlerClient({
        account,
        apiKey: GELATO_API_KEY,
        client,
      });

      // Get EIP-7702 authorization if needed (first transaction only)
      const authorization = await account.eip7702Authorization?.();

      if (authorization) {
        console.log("EOA needs authorization (not delegated yet)");
      } else {
        console.log("EOA already delegated to Kernel implementation");
      }

      console.log("Sending UserOperation...");

      // Send the user operation
      const hash = await bundler.sendUserOperation({
        calls: [{
          to: "0xEEeBe2F778AA186e88dCf2FEb8f8231565769C27",
          data: "0xd09de08a", // increment()
        }],
        authorization,
      });

      console.log(`User operation hash: ${hash}`);

      // Wait for receipt
      const { receipt } = await bundler.waitForUserOperationReceipt({ hash });

      console.log(`Transaction hash: ${receipt.transactionHash}`);
    })();
    ```
  </Tab>
</Tabs>

## Need Help?

If you have questions about migrating from the Smart Wallet SDK, please reach out through [GitHub](https://github.com/gelatodigital).
