Testing with BuildBear Sandboxes
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
Creating and setting up a BuildBear Sandbox
-
Go to buildbear.io and sign up for an account if you don't have one already.
-
Create a new Sandbox by clicking "Create a Sandbox" and selecting the network you want to fork (e.g., Ethereum Mainnet, Sepolia, etc.).
-
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.
-
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>
- BuildBear Sandbox RPC URL:
-
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
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
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
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}`
);
More detailed examples and instructions can be found on BuildBear's docs