Submit your first sponsored smart account transaction
This Paymaster quickstart tutorial explains how to submit your first smart account transaction on Base Sepolia using Viem, with gas sponsorship from Coinbase Developer Platform. The example below sponsors an NFT mint, but can be updated to call your smart contract instead.
The example below uses Coinbase smart wallet, but any smart account will work.
a. Create a new private key with Foundry.
b. Install Foundry: curl -L https://foundry.paradigm.xyz | bash
c. Generate a new key pair: cast wallet new.
d. Update your config.js file with the private key and create the account.
Copy
Ask AI
//config.jsimport { createPublicClient, http } from 'viem'import { toCoinbaseSmartAccount } from 'viem/account-abstraction'import { baseSepolia } from 'viem/chains'import { privateKeyToAccount } from 'viem/accounts'// Your RPC url. Make sure you're using the right network (base vs base-sepolia)export const RPC_URL = "https://api.developer.coinbase.com/rpc/v1/base-sepolia/<your-rpc-token>"export const client = createPublicClient({ chain: baseSepolia, transport: http(RPC_URL),})// Creates a Coinbase smart wallet using an EOA signerconst owner = privateKeyToAccount('<your-private-key>')export const account = await toCoinbaseSmartAccount({ client, owners: [owner]})
5. Create the Bundler and Paymaster clients, submit transaction
Create a new file called index.js
Copy
Ask AI
//index.jsimport { http } from "viem";import { baseSepolia } from "viem/chains";import { createBundlerClient } from "viem/account-abstraction";import { account, client, RPC_URL } from "./config.js";import { abi } from "./example-app-abi.js";// Logs your deterministic public address generated by your private keyconsole.log(`Minting nft to ${account.address}`)// The bundler is a special node that gets your UserOperation on chainconst bundlerClient = createBundlerClient({ account, client, transport: http(RPC_URL), chain: baseSepolia,});// The call for your app. You will have change this depending on your dapp's abiconst nftContractAddress = "0x66519FCAee1Ed65bc9e0aCc25cCD900668D3eD49"const mintTo = { abi: abi, functionName: "mintTo", to: nftContractAddress, args: [account.address, 1],};const calls = [mintTo]// Pads the preVerificationGas (or any other gas limits you might want) to ensure your UserOperation lands onchainaccount.userOperation = { estimateGas: async (userOperation) => { const estimate = await bundlerClient.estimateUserOperationGas(userOperation); // adjust preVerification upward estimate.preVerificationGas = estimate.preVerificationGas * 2n; return estimate; },};// Sign and send the UserOperationtry { const userOpHash = await bundlerClient.sendUserOperation({ account, calls, paymaster: true }); const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: userOpHash, }); console.log("✅ Transaction successfully sponsored!"); console.log(`⛽ View sponsored UserOperation on blockscout: https://base-sepolia.blockscout.com/op/${receipt.userOpHash}`); console.log(`🔍 View NFT mint on basescan: https://sepolia.basescan.org/address/${account.address}`); process.exit()} catch (error) { console.log("Error sending transaction: ", error); process.exit(1)}
In your terminal you can run this script using the below command from the correct directory