Send a Transaction
Sending a transaction from a Smart Account looks very similar to using viem or ethers, but under the hood, you are sending a UserOperation to a Bundler, which then forwards it to the EntryPoint contract.
sendTransaction
Section titled “sendTransaction”If you are using @0xgasless/smart-account, the sendTransaction method handles the UserOperation lifecycle for you.
import { encodeFunctionData, parseAbi } from "viem";
// 1. Prepare your call data.const nftContract = "0xYourNFTContractAddress";const abi = parseAbi(["function safeMint(address to)"]);const data = encodeFunctionData({ abi, functionName: "safeMint", args: [smartAccountAddress],});
// 2. Send the transactionconst userOpResponse = await smartAccount.sendTransaction({ to: nftContract, value: 0n, // Value in wei. 0n for most contract calls. data: data, // Encoded function data.});
// 3. Wait for the transaction to be mined on-chainconst receipt = await userOpResponse.wait();console.log("Transaction mined:", receipt.receipt.transactionHash);What happens during sendTransaction?
Section titled “What happens during sendTransaction?”- The SDK fetches the next available
noncefor your Smart Account. - It requests gas estimates from the Bundler for the
UserOperation. - If a Paymaster is configured, it requests a signature from the Paymaster to sponsor the gas.
- It prompts your connected Signer (e.g., the Embedded Wallet iframe, or your local key) to sign the final
UserOperationhash. - It submits the signed
UserOperationto the Bundler.
Waiting for Confirmation
Section titled “Waiting for Confirmation”The UserOperation is not an Ethereum transaction immediately — it sits in the Bundler’s mempool until the Bundler submits a batch.
You have two ways to track it:
Wait for the UserOperation Hash (Fast)
Section titled “Wait for the UserOperation Hash (Fast)”If you only need to know that the Bundler accepted the operation:
const { transactionHash } = await userOpResponse.waitForTxHash();console.log("Pending UserOp Hash:", transactionHash);Wait for the On-Chain Receipt (Slower, but final)
Section titled “Wait for the On-Chain Receipt (Slower, but final)”If you need to know the exact block it was mined in and that the Ethereum network confirmed it:
const receipt = await userOpResponse.wait();if (receipt.success === 'true') { console.log("Success! Tx hash:", receipt.receipt.transactionHash);}Error Handling
Section titled “Error Handling”If the transaction fails (e.g., the contract reverts, the bundler rejects it, or the user declines the signature), sendTransaction will throw an error.
Always wrap calls in a try/catch block:
try { const response = await smartAccount.sendTransaction({...});} catch (error) { console.error("UserOperation failed to send:", error.message);}