{"id":11542,"library":"permissionless","title":"permissionless.js: ERC-4337 Account Abstraction Utilities","description":"permissionless.js is a robust, TypeScript-first utility library designed to simplify interaction with Ethereum's ERC-4337 Account Abstraction standard. It provides a comprehensive set of client interfaces and helper functions for integrating with ERC-4337 Bundlers and Paymasters, as well as tools for creating and managing Smart Accounts. This enables developers to build dApps with advanced features like gasless transactions, multi-signature accounts, and custom validation logic. The library leverages `viem` for core Ethereum interactions and `ox` for cryptographic operations, offering a type-safe and modular approach to account abstraction development. The current stable version is 0.3.5, with frequent patch releases addressing bug fixes and minor feature enhancements, alongside occasional minor releases for larger feature sets or dependency upgrades.","status":"active","version":"0.3.5","language":"javascript","source_language":"en","source_url":"https://github.com/pimlicolabs/permissionless.js","tags":["javascript","ethereum","erc-4337","eip-4337","paymaster","bundler","typescript"],"install":[{"cmd":"npm install permissionless","lang":"bash","label":"npm"},{"cmd":"yarn add permissionless","lang":"bash","label":"yarn"},{"cmd":"pnpm add permissionless","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Cryptographic utilities; dynamically loaded peer dependency.","package":"ox","optional":false},{"reason":"Core Ethereum client interactions; peer dependency.","package":"viem","optional":false}],"imports":[{"note":"permissionless is an ESM-first library. Use `import` statements.","wrong":"const createSmartAccountClient = require('permissionless');","symbol":"createSmartAccountClient","correct":"import { createSmartAccountClient } from 'permissionless';"},{"note":"Most client creation functions are named exports from the top-level package.","wrong":"import createBundlerClient from 'permissionless/clients/createBundlerClient';","symbol":"createBundlerClient","correct":"import { createBundlerClient } from 'permissionless';"},{"note":"Type imports should use `import type` for clarity and bundler optimization.","wrong":"import { UserOperation } from 'permissionless/types';","symbol":"UserOperation","correct":"import type { UserOperation } from 'permissionless/types';"}],"quickstart":{"code":"import { createPublicClient, http, privateKeyToAccount, Address } from 'viem';\nimport { optimismSepolia } from 'viem/chains';\nimport { createBundlerClient, createSmartAccountClient, createPimlicoPaymasterClient, ENTRYPOINT_ADDRESS_V07, signerToSimpleSmartAccount } from 'permissionless';\nimport { type UserOperation } from 'permissionless/types';\n\nconst privateKey = (process.env.PRIVATE_KEY as `0x${string}`) || '0x...'; // Replace with your private key\nconst pimlicoRpcUrl = process.env.PIMLICO_RPC_URL || 'https://api.pimlico.io/v2/optimism-sepolia/rpc?apikey=YOUR_PIMLICO_API_KEY';\n\nconst chain = optimismSepolia;\nconst publicClient = createPublicClient({\n  chain,\n  transport: http(chain.rpcUrls.default.http[0]),\n});\n\nconst bundlerClient = createBundlerClient({\n  chain,\n  transport: http(pimlicoRpcUrl),\n  entryPoint: ENTRYPOINT_ADDRESS_V07\n});\n\nconst paymasterClient = createPimlicoPaymasterClient({\n  chain,\n  transport: http(pimlicoRpcUrl),\n  entryPoint: ENTRYPOINT_ADDRESS_V07\n});\n\nasync function sendSimpleUserOperation() {\n  const signer = privateKeyToAccount(privateKey);\n\n  const simpleSmartAccountClient = await signerToSimpleSmartAccount(publicClient, {\n    signer,\n    entryPoint: ENTRYPOINT_ADDRESS_V07,\n    factoryAddress: '0x9406Cc6185a346906296840746125a0E447645E4' // Example SimpleAccountFactory\n  });\n\n  const smartAccountClient = createSmartAccountClient({\n    account: simpleSmartAccountClient,\n    chain,\n    transport: http(pimlicoRpcUrl),\n    entryPoint: ENTRYPOINT_ADDRESS_V07\n  });\n\n  console.log(`Smart account address: ${smartAccountClient.account.address}`);\n\n  const userOperation = await smartAccountClient.prepareUserOperation({\n    userOperation: {\n      callData: await smartAccountClient.account.encodeCallData({\n        to: smartAccountClient.account.address,\n        value: 0n,\n        data: '0x'\n      })\n    },\n    sponsorUserOperation: async ({ userOperation }) => {\n      return paymasterClient.sponsorUserOperation({\n        userOperation,\n        entryPoint: ENTRYPOINT_ADDRESS_V07\n      });\n    }\n  });\n\n  // For demonstration, not actually sending a transaction\n  console.log('Prepared UserOperation:', userOperation);\n\n  // To send, uncomment:\n  // const userOpHash = await smartAccountClient.sendUserOperation({\n  //   userOperation: userOperation,\n  //   entryPoint: ENTRYPOINT_ADDRESS_V07\n  // });\n  // console.log(`UserOperation sent, hash: ${userOpHash}`);\n  // const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: userOpHash });\n  // console.log('UserOperation receipt:', receipt);\n}\n\nsendSimpleUserOperation().catch(console.error);\n","lang":"typescript","description":"Demonstrates setting up `viem` and `permissionless` clients, creating a simple smart account, preparing a user operation with paymaster sponsorship, and logging the prepared UserOperation."},"warnings":[{"fix":"Upgrade `permissionless` to v0.3.0 or higher and ensure your Kernel smart account factory supports the patched version.","message":"Version 0.3.0 introduced a critical fix for a vulnerability in previous Kernel validator versions. Users on older Kernel-based smart accounts should upgrade immediately to patch 'unsafe to use' functionality.","severity":"breaking","affected_versions":"<0.3.0"},{"fix":"Check your project's `package.json` for `permissionless` and its peer dependencies. Run `npm install viem@^2.44.4 ox@^0.11.3` (or the specific versions required by your `permissionless` version).","message":"`permissionless` has `viem` and `ox` as peer dependencies. Ensure you install compatible versions as specified in `package.json` to avoid runtime errors or type mismatches. Regular updates to `permissionless` often include peer dependency version bumps (e.g., v0.3.4 updated `viem` to `^2.44.4` and `ox` to `^0.11.3`).","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Ensure `ox` is explicitly listed as a dependency in your `package.json` and installed, even though it's a peer dependency. If using a bundler like Webpack or Rollup, ensure it can handle dynamic imports or include `ox` in your build configuration.","message":"The `ox` library, a dependency for cryptographic operations, is dynamically loaded. In certain environments or bundler configurations, this might lead to 'Cannot find module 'ox'' errors if not properly handled by your build system.","severity":"gotcha","affected_versions":">=0.3.1"},{"fix":"Always use the correct `ENTRYPOINT_ADDRESS_V06` or `ENTRYPOINT_ADDRESS_V07` (or newer if available) constant provided by `permissionless` that matches the network and bundler/paymaster you are interacting with.","message":"The `entryPoint` address is a critical configuration parameter for all ERC-4337 clients (`BundlerClient`, `PaymasterClient`, `SmartAccountClient`). Using an incorrect or outdated entryPoint address will lead to transaction failures.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"When initializing `createPublicClient` or `createBundlerClient`, `createSmartAccountClient`, ensure a `chain` object (e.g., `optimismSepolia`) is passed in the configuration.","cause":"Attempting to create a `permissionless` client (e.g., `createBundlerClient`) without providing a valid `chain` object from `viem/chains`.","error":"Error: The client must be configured with a chain. Ensure that `chain` is not `undefined`."},{"fix":"Verify that the private key or signer used for signing is correct, the `UserOperation` fields were not mutated after signing, and that the smart account's `validateUserOp` logic on-chain is correctly implemented.","cause":"The `UserOperation` was signed incorrectly, or the `signature` field does not match the expected format or validation logic of the smart account.","error":"Error: Invalid user operation signature"},{"fix":"Check the Paymaster's specific API documentation for error codes. Ensure the `UserOperation` is valid and that your Paymaster account has sufficient balance or allowance for the transaction. Also, verify your API key and endpoint URL.","cause":"The connected Paymaster service responded with an error or an incorrectly formatted object during the `sponsorUserOperation` call, often due to insufficient funds, an invalid `UserOperation`, or rate limiting.","error":"Error: Paymaster returned an invalid response."},{"fix":"Inspect the `callData` for correctness. Use a debugger (if available for your bundler) or manually trace the `UserOperation` execution to identify the revert reason. Ensure `sender` account has enough ETH for the `preVerificationGas` or that the paymaster is properly sponsoring.","cause":"The bundler failed to estimate gas for the `UserOperation`, often indicating a revert on execution, an invalid `callData`, or an issue with the gas parameters.","error":"Error: Could not estimate gas for UserOperation"}],"ecosystem":"npm"}