Providers
Wallet Apps & Providers
Pimlico

Sponsoring Transactions With Pimlico

Pimlico (opens in a new tab) is an Account Abstraction infrastructure provider that enables developers to easily integrate smart accounts and gasless transactions into their Sei applications. This guide will walk you through creating a smart account and sending your first gasless transaction on Sei Testnet using Pimlico's infrastructure.

Getting Started

Dependencies

To integrate Pimlico into your Sei application, you'll need to install the following dependencies:

pnpm install permissionless viem dotenv

permissionless.js is a AA SDK that works with any account, paymaster, or bundler implementation - no vendor lock-in.

Setting up Pimlico Dashboard

Before starting the integration:

  1. Visit the Pimlico dashboard (opens in a new tab)
  2. Create an account and generate an API key
  3. Store your API key in a .env file:
PIMLICO_API_KEY='pim_xxxxxxxxxxxxxxxxxxxxxx'

Configuring Pimlico Client

First, let's set up the necessary clients and configurations.

import { createSmartAccountClient } from "permissionless";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { createPublicClient, http, Hex } from "viem";
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
import { seiTestnet } from "viem/chains";
import { toSimpleSmartAccount } from "permissionless/accounts";
import { writeFileSync } from "fs";
import "dotenv/config";
 
// Load environment variables
dotenv.config()
const apiKey = process.env.PIMLICO_API_KEY
if (!apiKey) throw new Error("Missing PIMLICO_API_KEY")
 
// Generate or load private key
const privateKey = process.env.PRIVATE_KEY ?? (() => {
    const pk = generatePrivateKey()
    writeFileSync(".env", `PRIVATE_KEY=${pk}`)
    return pk
})()
 
// Create public client
export const publicClient = createPublicClient({
    chain: seiTestnet,
    transport: http("https://evm-rpc-testnet.sei-apis.com")
})
 
// Create Pimlico client
const pimlicoUrl = `https://api.pimlico.io/v2/${seiTestnet.id}/rpc?apikey=${apiKey}`
 
export const pimlicoClient = createPimlicoClient({
    chain: seiTestnet,
    transport: http(pimlicoUrl),
})

Creating a Smart Account

Now let's create a simple smart account instance. This account will be controlled by a single EOA signer:

import { toSimpleSmartAccount } from 'permissionless/accounts'
 
const account = await toSimpleSmartAccount({
    client: publicClient,
    owner: privateKeyToAccount(privateKey as Hex),
})
 
console.log(`Smart account address: ${account.address}`)

For a full list of all supported smart account types in permissionless.js see here (opens in a new tab)

Setting up the Smart Account Client

To interact with the smart account, we need to create a SmartAccountClient:

import { createSmartAccountClient } from 'permissionless'
 
const smartAccountClient = createSmartAccountClient({
    account,
    chain: seiTestnet,
    bundlerTransport: http(pimlicoUrl),
    paymaster: pimlicoClient,
    userOperation: {
        estimateFeesPerGas: async () => {
            return (await pimlicoClient.getUserOperationGasPrice()).fast
        }
    }
})

Sending a Gasless Transaction

With everything set up, we can now send a gasless transaction from our smart account:

const txHash = await smartAccountClient.sendTransaction({
    to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
    value: 0n,
    data: "0x1234"
})
 
console.log(`Transaction included: ${txHash}`)
return txHash

Complete Example

Here's a complete example that puts everything together:

import { createSmartAccountClient } from 'permissionless'
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'
import { createPublicClient, http, Hex } from 'viem'
import { seiTestnet } from 'viem/chains'
import { toSimpleSmartAccount } from 'permissionless/accounts'
import { writeFileSync } from 'fs'
import "dotenv/config"
 
async function main() {
    // Initialize clients and account
    const apiKey = process.env.PIMLICO_API_KEY
    if (!apiKey) throw new Error("Missing PIMLICO_API_KEY")
 
    // Generate or load private key
    const privateKey = process.env.PRIVATE_KEY ?? (() => {
        const pk = generatePrivateKey()
        writeFileSync(".env", `PRIVATE_KEY=${pk}`)
        return pk
    })()
 
    // Create public client
    const publicClient = createPublicClient({
        chain: seiTestnet,
        transport: http("https://evm-rpc-testnet.sei-apis.com")
    })
 
    // Create Pimlico client
    const pimlicoUrl = `https://api.pimlico.io/v2/${seiTestnet.id}/rpc?apikey=${apiKey}`
 
    const pimlicoClient = createPimlicoClient({
        chain: seiTestnet,
        transport: http(pimlicoUrl),
    })
 
    // Create smart account
    const account = await toSimpleSmartAccount({
        client: publicClient,
        owner: privateKeyToAccount(privateKey as Hex),
    })
 
    console.log(`Smart account address: ${account.address}`)
 
    // Create smart account client
    const smartAccountClient = createSmartAccountClient({
        account,
        chain: seiTestnet,
        bundlerTransport: http(pimlicoUrl),
        paymaster: pimlicoClient,
        userOperation: {
            estimateFeesPerGas: async () => {
                return (await pimlicoClient.getUserOperationGasPrice()).fast
            }
        }
    })
 
    // Send transaction
    const txHash = await smartAccountClient.sendTransaction({
        to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
        value: 0n,
        data: "0x1234"
    })
 
    console.log(`Transaction included: ${txHash}`)
}
 
main().catch(console.error)

What's Happening Under the Hood?

When you send a transaction using the smart account client:

  1. The client builds a user operation (a transaction format for smart accounts)
  2. Requests sponsorship from Pimlico's paymaster
  3. Signs the operation with the smart account owners's private key
  4. Submits it to Pimlico's bundler
  5. The bundler monitors the chain until the operation is included in a block

The first transaction will also deploy your smart account contract if it hasn't been deployed yet.

Conclusion

You've now learned how to:

  • Set up Pimlico's infrastructure
  • Create a smart account
  • Send gasless transactions

This implementation enables a seamless user experience where end users don't need to worry about gas fees or managing native tokens to interact with your dApp.

For more information about Pimlico and its features, check out:

Join the Pimlico Telegram (opens in a new tab) community to get help and share what you're building!