# Testing with BuildBear Sandboxes

:::warning
BuildBear has announced that it is entering hibernation mode, so new sandboxes may not be available. To test locally, use [Prool](/guides/how-to/testing/prool) or [Docker](/guides/how-to/testing/docker) instead.
:::

This guide introduces how to setup a BuildBear Sandbox with for testing the Alto bundler and a mock paymaster. We will be using viem and permissionless to interact with the sandbox enviornment.

## Overview

BuildBear provides on-demand, isolated test environments that clone existing blockchain networks. These environments are perfect for testing account abstraction implementations as they:

* Provide a persistent, dedicated testnet environment
* Support EIP-4337 and all necessary AA infrastructure
* Allow you to fork from existing networks (Ethereum, Arbitrum, Optimism, etc.)
* Unlocked faucets for testing
* Offer an explorer interface for easy debugging

## Steps

::::steps
### Creating and setting up a BuildBear Sandbox

1. Go to [buildbear.io](https://www.buildbear.io) and sign up for an account if you don't have one already.

2. Create a new Sandbox by clicking "Create a Sandbox" and selecting the network you want to fork (e.g., Ethereum Mainnet, Sepolia, etc.).

3. Navigate to the Plugin tab on your sandbox dashboard and install the Pimlico Plugin. Ensure the plugin appears as installed in the marketplace or Installed tab.

4. Go to your Buildbear sandbox dashboard and locate the RPC URL. Copy the RPC URL, which also serves as the Pimlico Client API endpoint. It should look something like the below.
   * BuildBear Sandbox RPC URL: `https://rpc.buildbear.io/<YOUR-SANDBOX-ID>`
   * Pimlico Client API: `https://rpc.buildbear.io/<YOUR-SANDBOX-ID>`

5. Once your Sandbox is created, you'll get access to:
   * RPC URL
   * Chain ID
   * Explorer URL
   * Faucet to fund your test accounts

### Setup the clients

```ts [Setup Clients]
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { defineChain, createPublicClient, http } from "viem";
import { entryPoint07Address } from "viem/account-abstraction";

const buildbearSandboxUrl = "https://rpc.buildbear.io/<YOUR-SANDBOX-ID>";

const BBSandboxNetwork = defineChain({
  id: 23177, // IMPORTANT : replace this with your sandbox's chain id
  name: "BuildBear x Base Sandbox", // name your network
  nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 }, // native currency of forked network
  rpcUrls: {
    default: {
      http: [buildbearSandboxUrl],
    },
  },
  blockExplorers: {
    default: {
      name: "BuildBear x Base Scan", // block explorer for network
      url: "https://explorer.buildbear.io/<YOUR-SANDBOX-ID>",
      apiUrl: "https://api.buildbear.io/<YOUR-SANDBOX-ID>/api",
    },
  },
});

// Create a new Public Client with Sandbox URL
export const publicClient = createPublicClient({
  chain: BBSandboxNetwork,
  transport: http(buildbearSandboxUrl), //@>>> Put in BuildBear rpc
});

// Create a pimlico client in the context of Sandbox
const pimlicoClient = createPimlicoClient({
  transport: http(buildbearSandboxUrl),
  entryPoint: {
    address: entryPoint07Address,
    version: "0.7",
  },
});
```

### Setup the Smart Account Client

```ts [Setup Clients]
import { createSmartAccountClient } from "permissionless";
import { privateKeyToAccount } from "viem/accounts";
import { toSafeSmartAccount } from "permissionless/accounts";

// Get signer for private key
const signer = privateKeyToAccount(privateKey);

// Create a Safe Smart Account from our signer
const account = await toSafeSmartAccount({
  client: publicClient,
  owners: [signer],
  entryPoint: {
    address: entryPoint07Address,
    version: "0.7",
  }, // global entrypoint
  version: "1.4.1",
});

// Create a client for smart account
const smartAccountClient = createSmartAccountClient({
  account,
  chain: BBSandboxNetwork,
  paymaster: pimlicoClient, // optional, can be removed if paymaster isn't used
  bundlerTransport: http(buildbearSandboxUrl), //sending the tx to BuildBear Sandbox
  userOperation: {
    estimateFeesPerGas: async () => {
      return (await pimlicoClient.getUserOperationGasPrice()).fast;
    },
  },
});
```

### Funding your smart account (Optional)

If you want to fund your smart account with native currency or ERC-20 tokens, you can use the following curl commands:

Funding native currency:

```
curl -X POST https://rpc.buildbear.io/<YOUR-SANDBOX-ID>  \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "buildbear_nativeFaucet",
    "params": [{
      "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
      "balance": "100"
    }]
  }'
```

Funding ERC-20 tokens:

```
curl -X POST https://rpc.buildbear.io/<YOUR-SANDBOX-ID> \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "buildbear_ERC20Faucet",
    "params": [{
      "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
      "balance": "100",
      "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
    }]
  }'
```

### Sending a userOperation

:::code-group
```ts [Verifying Paymaster]
import { parseAbi, parseEther, getAddress } from "viem";

let txHash = await smartAccountClient.sendUserOperation({
    account,
    calls: [
      {
        to: getAddress("0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063"), //Payment token for gas
        abi: parseAbi(["function approve(address,uint)"]),
        functionName: "approve",
        args: ["0x0000000000000039cd5e8ae05257ce51c473ddd1", parseEther("1")], // approve spend of 1 DAI to Paymaster's address
      },
      {
        to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
        value: parseEther("1"),
      },
    ],
  });

let result = await smartAccountClient.waitForUserOperationReceipt({
  hash: txHash,
});

console.log(
  `User operation included: https://explorer.buildbear.io/uzair/tx/${result.receipt.transactionHash}`
);
```

```ts [ERC-20 Paymaster]
txHash = await smartAccountClient.sendUserOperation({
    account,
    calls: [
      {
        to: getAddress("0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063"), //Payment token for gas
        abi: parseAbi(["function approve(address,uint)"]),
        functionName: "approve",
        args: ["0x0000000000000039cd5e8ae05257ce51c473ddd1", parseEther("1")], // approve spend of 1 DAI to Paymaster's address
      },
      {
        to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
        value: parseEther("1"),
      },
    ],
      paymasterContext: {
        token: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", // DAI
      },
  });

result = await smartAccountClient.waitForUserOperationReceipt({
  hash: txHash,
});

console.log(
  `User operation included: https://explorer.buildbear.io/<YOUR-SANDBOX-ID>/tx/${result.receipt.transactionHash}`
);
```
:::

:::info
paymaster top-ups are taken care of by the sandbox and you do need to worry about topping up the paymaster ever
:::
::::
