{"id":32305549,"url":"https://github.com/fuseio/userop.dart","last_synced_at":"2025-10-23T06:52:14.772Z","repository":{"id":186512334,"uuid":"674135966","full_name":"fuseio/userop.dart","owner":"fuseio","description":"A lightweight Dart library for quickly and easily building ERC-4337 UserOperations.","archived":false,"fork":false,"pushed_at":"2024-12-01T12:53:52.000Z","size":183,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-01T13:39:42.203Z","etag":null,"topics":["erc4337","ethereum"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/userop","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fuseio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-03T08:15:38.000Z","updated_at":"2024-12-01T12:53:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"f5b718a1-6be9-4a10-913f-2792ded7133f","html_url":"https://github.com/fuseio/userop.dart","commit_stats":null,"previous_names":["fuseio/userop.dart"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fuseio/userop.dart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuseio%2Fuserop.dart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuseio%2Fuserop.dart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuseio%2Fuserop.dart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuseio%2Fuserop.dart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fuseio","download_url":"https://codeload.github.com/fuseio/userop.dart/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fuseio%2Fuserop.dart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280577134,"owners_count":26354072,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-23T02:00:06.710Z","response_time":142,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erc4337","ethereum"],"created_at":"2025-10-23T06:52:13.103Z","updated_at":"2025-10-23T06:52:14.765Z","avatar_url":"https://github.com/fuseio.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# userop.dart\n## Table of Contents\n\n- [userop.dart](#useropdart)\n  - [Table of Contents](#table-of-contents)\n  - [Introduction](#introduction)\n      - [What is userop.dart?](#what-is-useropdart)\n      - [Why userop.dart?](#why-useropdart)\n  - [Installation](#installation)\n    - [Examples](#examples)\n      - [Create a simple account](#create-a-simple-account)\n      - [Transfer funds](#transfer-funds)\n      - [Transfer ERC20 token](#transfer-erc20-token)\n      - [Batch transaction](#batch-transaction)\n  - [Client](#client)\n    - [Usage](#usage)\n      - [sendUserOperation](#senduseroperation)\n      - [buildUserOperation](#builduseroperation)\n      - [constants](#constants)\n  - [Provider](#provider)\n    - [BundlerJsonRpcProvider](#bundlerjsonrpcprovider)\n  - [Presets](#presets)\n    - [Builder](#builder)\n      - [Kernel](#kernel)\n      - [Etherspot Wallet](#etherspot-wallet)\n      - [SimpleAccount](#simpleaccount)\n    - [Middleware](#middleware)\n      - [estimateUserOperationGas](#estimateuseroperationgas)\n      - [getGasPrice](#getgasprice)\n      - [verifyingPaymaster](#verifyingpaymaster)\n      - [eOASignature](#eoasignature)\n\n## Introduction\n\n#### What is userop.dart?\n\n`userop.dart` is a comprehensive library tailored for crafting ERC-4337 User Operations. While `web3dart` equips developers to effortlessly generate standard EVM transactions, `userop.dart` streamlines the creation and dispatch of User Operations to ERC-4337 Bundlers.\n\n#### Why userop.dart?\n\n- 💪 Versatile Implementation: Suitable for generating User Operations for any ERC-4337 Smart Account, Bundler platform, or Paymaster.\n\n- 🏗️ User-friendly architecture: Adopts the builder design pattern, reflecting the real-world construction of User Operations.\n\n## Installation\n\n ```yaml               \ndependencies:       \n  userop: [latest-version]\n```      \n\n### Examples\n\n#### [Create a simple account](./example/address.dart)\n\n#### [Transfer funds](./example/transfer.dart)\n\n#### [Transfer ERC20 token](./example/erc20_transfer.dart)\n\n#### [Batch transaction](./example/batch_transfer.dart)\n\n## Client\n\nConnecting to an ERC-4337 bundler is easy using `userop.dart`\n\n`userop.dart` allows you connect to a bundler RPC using the client interface.\n\nAn instance of a client is an abstraction for building and sending your User Operations to the `eth_sendUserOperation` RPC method on a bundler.\n\n### Usage\n\n```dart\n\nimport 'package:userop/userop.dart';\n\nfinal String bundlerRPC = 'YOUR_BUNDLER_RPC_URL';\nfinal iClientOpts = IClientOpts()\n  ..overrideBundlerRpc = bundlerRPC\n  ..entryPoint = EthereumAddress.fromHex('YOU_ENTRY_POINT' ?? ERC4337.ENTRY_POINT);\n\nfinal client = await Client.init(\n  bundlerRPC,\n  opts: iClientOpts,\n);\n\n```\n\n#### sendUserOperation\n\nA method for directing a `builder` instance to create a User Operation and send it to a bundler via `eth_sendUserOperation`.\n\n  ```dart\n\nimport 'package:userop/userop.dart';\n\nfinal response = await client.sendUserOperation(\n    await simpleAccount.execute(\n      Call(\n        to: targetAddress,\n        value: amount,\n        data: Uint8List(0),\n      )\n    ),\n    opts: sendOpts,\n);\nfinal filterEvent = await response.wait();\n\n  ```\n\n\n#### buildUserOperation\n\nThis method can be used to direct a builder using the client's entryPoint and chainID. However it will only return the UserOperation and not initiate a send request.\n\n  ```dart\nfinal userOp = await client.buildUserOperation(builder);\n  ```\n\n#### constants\n\nA instance of a client has several constants that can be set.\n\n  ```dart\n// The maximum amount of time to wait for the UserOperationEvent after calling response.wait()\nclient.waitTimeoutMs = 30000;\n\n// The interval at which it will poll the node to look up UserOperationEvent.\nclient.waitIntervalMs = 5000;\n  ```\n\n\n## Provider\n\n`userop.dart` provides a straightforward wrapper over `web3dart` JsonRPC, offering the flexibility to re-route bundler methods. By default, it assumes that both bundler and node methods share the same RPC url. However, in instances where this isn't the case, this module offers the added capability to override the bundler RPC, allowing all bundler RPC methods to be redirected to a different endpoint.\n\n### BundlerJsonRpcProvider\n\n  ```dart\n\nimport 'package:userop/userop.dart';\nimport 'package:http/http.dart' as http;\n\nfinal String bundlerRPC = 'YOUR_BUNDLER_RPC_URL';\nfinal provider = BundlerJsonRpcProvider(rpcUrl, http.Client());\n  ```\n\n## Presets\n\n`userop.dart` comes bundled with common presets, facilitating a quicker setup for specific use cases.\n\n### Builder\n\nBuilder presets offer pre-configured builders for known contract account implementations. These presets can be utilized directly or can be customized using get and set functions.\n\n#### Kernel\nThe Kernel preset is an abstraction to build User Operations for an ERC-4337 account based on [ZeroDev Kernel V2](https://github.com/zerodevapp/kernel/blob/main/src/Kernel.sol) - a modular contract account framework. It deploys with the [ECDSA validator](https://github.com/zerodevapp/kernel/blob/main/src/validator/ECDSAValidator.sol) by default.\n\n  ```dart\nimport 'package:userop/userop.dart';\n\nfinal targetAddress = EthereumAddress.fromHex('YOUR_TARGET_ADDRESS');\nfinal amount = BigInt.parse('AMOUNT_IN_WEI');\nfinal signingKey = EthPrivateKey.fromHex('YOUR_PRIVATE_KEY');\nfinal bundlerRPC = 'YOUR_BUNDLER_RPC_URL';\nfinal opts = IPresetBuilderOpts()\n  ..factoryAddress = EthereumAddress.fromHex(\n    'YOUR_FACTORY_ADDRESS',\n  );\nfinal kernel = await Kernel.init(\n    signingKey,\n    bundlerRPC,\n    opts: opts,\n);\n\nfinal client = await Client.init(bundlerRPC);\n\nfinal res = await client.sendUserOperation(\n    await kernel.execute(\n      Call(\n        to: targetAddress,\n        value: amount,\n        data: Uint8List(0),\n      ),\n    ),\n);\nprint('UserOpHash: ${res.userOpHash}');\n\nprint('Waiting for transaction...');\nfinal ev = await res.wait();\nprint('Transaction hash: ${ev?.transactionHash}');\n  ```\n  \n\n#### Etherspot Wallet\n\nThe `EtherspotWallet` preset provides an abstraction to construct User Operations for an ERC-4337 account. It's based on [EtherspotWallet.sol](https://github.com/etherspot/etherspot-prime-contracts/blob/master/src/wallet/EtherspotWallet.sol).\n\n  ```dart\nimport 'package:userop/userop.dart';\n\nfinal targetAddress = EthereumAddress.fromHex('YOUR_TARGET_ADDRESS');\nfinal amount = BigInt.parse('AMOUNT_IN_WEI');\nfinal signingKey = EthPrivateKey.fromHex('YOUR_PRIVATE_KEY');\nfinal bundlerRPC = 'YOUR_BUNDLER_RPC_URL';\n\nfinal etherspotWallet = await EtherspotWallet.init(\n    signingKey,\n    bundlerRPC,\n);\n\nfinal client = await Client.init(bundlerRPC);\n\nfinal res = await client.sendUserOperation(\n    await etherspotWallet.execute(\n      Call(\n        to: targetAddress,\n        value: amount,\n        data: Uint8List(0),\n      ),\n    ),\n);\nprint('UserOpHash: ${res.userOpHash}');\n\nprint('Waiting for transaction...');\nfinal ev = await res.wait();\nprint('Transaction hash: ${ev?.transactionHash}');\n  ```\n  \n\n#### SimpleAccount\n\nThe `SimpleAccount` preset provides an abstraction to construct User Operations for an ERC-4337 account. It's based on [SimpleAccount.sol](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccount.sol).\n\n  ```dart\nimport 'package:userop/userop.dart';\n\nfinal targetAddress = EthereumAddress.fromHex('YOUR_TARGET_ADDRESS');\nfinal amount = BigInt.parse('AMOUNT_IN_WEI');\nfinal signingKey = EthPrivateKey.fromHex('YOUR_PRIVATE_KEY');\nfinal bundlerRPC = 'YOUR_BUNDLER_RPC_URL';\n\nfinal simpleAccount = await SimpleAccount.init(\n    signingKey,\n    bundlerRPC,\n);\n\nfinal client = await Client.init(bundlerRPC);\n\nfinal res = await client.sendUserOperation(\n    await simpleAccount.execute(\n      Call(\n        to: targetAddress,\n        value: amount,\n        data: Uint8List(0),\n      ),\n    ),\n);\nprint('UserOpHash: ${res.userOpHash}');\n\nprint('Waiting for transaction...');\nfinal ev = await res.wait();\nprint('Transaction hash: ${ev?.transactionHash}');\n  ```\n  \n\n### Middleware\n\nMiddleware presets are reusable implementations of middleware functions tailored for different builder instances.\n\n#### estimateUserOperationGas\n\nThis middleware function is designed for sending UserOperations to the `eth_estimateUserOperationGas` endpoint, ensuring accurate gas limit estimations for `preVerificationGas`, `verificationGasLimit`, and `callGasLimit`.\n\n\n  ```dart\nimport 'package:userop/userop.dart';\n\nfinal builder = UserOperationBuilder();\n\nbuilder = builder.useMiddleware(estimateUserOperationGas(\n    Web3Client('RPC_URL', http.Client()),\n    BundlerJsonRpcProvider('RPC_URL', http.Client()),\n))\n  ```\n\n#### getGasPrice\n\nThis middleware function retrieves the latest values for `maxFeePerGas` and `maxPriorityFeePerGas`.\n\n  ```dart\nimport 'package:userop/userop.dart';\n\nfinal builder = UserOperationBuilder();\n\nbuilder = builder.useMiddleware(getGasPrice(\n    Web3Client('RPC_URL', http.Client()),\n    BundlerJsonRpcProvider('RPC_URL', http.Client()),\n))\n  ```\n\n#### verifyingPaymaster\n\nThis middleware function requests gas sponsorship from a Paymaster service. It assumes the service adheres to the proposed [JSON-RPC API for verifying paymasters](https://hackmd.io/@stackup/H1oIvV-qi).\n\n ```dart\nfinal paymasterMiddleware = verifyingPaymaster(\n  'YOUR_PAYMASTER_SERVICE_URL',\n  {},\n);\n\nfinal IPresetBuilderOpts opts = IPresetBuilderOpts()\n    ..paymasterMiddleware = paymasterMiddleware;\n\nfinal simpleAccount = await SimpleAccount.init(\n    signingKey,\n    bundlerRPC,\n    opts: opts,\n);\n ```\n\n#### eOASignature\n\nA middleware function designed to sign the User Operation using an EOA private key.\n\n  ```dart\nimport 'package:userop/userop.dart';\n\nfinal builder = UserOperationBuilder();\nbuilder = builder.useMiddleware(eOASignature(signer))\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuseio%2Fuserop.dart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuseio%2Fuserop.dart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuseio%2Fuserop.dart/lists"}