# Bundler API - Using SDK

> Use the @account-kit/infra SDK to interact with Alchemy's ERC-4337 bundler for advanced UserOperation management, including gas fee estimation and sending.

> For the complete documentation index, see [llms.txt](/docs/llms.txt).

<Info>**Required SDK version**: ^v4.59.1</Info>

## Manage UserOperations with `@account-kit/infra`

The `@account-kit/infra` library enables direct interaction with Alchemy's ERC-4337 bundler for advanced UserOperation management. The `alchemyFeeEstimator` function leverages underlying APIs, including `rundler_maxPriorityFeePerGas` and `eth_estimateUserOperation`, to estimate gas fees for UserOperations. Below are examples demonstrating how to estimate and send a UserOperation and how to retrieve a UserOperation by its hash using low-level Bundler APIs.

<CodeBlocks>

```ts title="config.ts"
import { alchemy, sepolia } from "@account-kit/infra";

const YOUR_API_KEY = "<YOUR_API_KEY>";
export const YOUR_PRIVATE_KEY = "<YOUR_PRIVATE_KEY>";
export const chain = sepolia;

export const transport = alchemy({
  apiKey: YOUR_API_KEY,
});
```

```ts title="estimateAndSendUserOperation.ts"
import { alchemyFeeEstimator } from "@account-kit/infra";
import { createModularAccountV2Client } from "@account-kit/smart-contracts";
import { LocalAccountSigner } from "@aa-sdk/core";
import { entryPoint07Address } from "viem/account-abstraction";
import {
  chain,
  transport
  YOUR_PRIVATE_KEY,
} from "./config.ts";

export async function estimateAndSendUserOperation() {
  const client = await createModularAccountV2Client({
    signer: LocalAccountSigner.privateKeyToAccountSigner(YOUR_PRIVATE_KEY),
    chain,
    transport,
    feeEstimator: alchemyFeeEstimator(transport),
  });

  try {
    let uo = await client.buildUserOperation({
      uo: {
        data: "0x",
        target: "0x0000000000000000000000000000000000000000",
      },
    });
    const uoWithSig = await client.signUserOperation({ uoStruct: uo });
    const sendResult = await client.sendRawUserOperation(
      uoWithSig,
      entryPoint07Address,
    );
    await client.waitForUserOperationTransaction({
      hash: sendResult,
      retries: {
        intervalMs: 100,
        maxRetries: 600,
        multiplier: 0,
      },
    });
    const receipt = await client.getUserOperationReceipt(sendResult);
    console.log("UserOperation receipt:", receipt);
  } catch (error) {
    console.error("Error processing UserOperation:", error);
  }
}
```

```ts title="getUserOperationByHash.ts"
import { createAlchemyPublicRpcClient } from "@account-kit/infra";
import { chain, transport } from "./config.ts";
import type { Hash } from "viem";

export async function getUserOperationByHash(uoHash: Hash) {
  const client = createAlchemyPublicRpcClient({
    chain,
    transport,
  });
  try {
    let userOp = await client.getUserOperationByHash(uoHash);
    console.log("User Operation: ", userOp);
  } catch (error) {
    console.error("Error processing UserOperation:", error);
  }
}
```

</CodeBlocks>

<Info>
  Make sure that your environment is set with the correct `ALCHEMY_API_KEY` and
  `PRIVATE_KEY`. These examples assume familiarity with ERC-4337 and proper
  configuration of the EntryPoint contract (`entryPoint07Address`).
</Info>