Building Blocks
Discover and install building blocks to extend your WDK integration.
Discover and install building blocks to extend your WDK integration.
@tetherto/wdk-wallet-evm-erc-4337
ERC-4337 Account Abstraction for EVM chains
Loading README…
Ethereum and EVM-compatible chains wallet
Bitcoin SegWit wallet with BIP-39/BIP-44 support
Solana blockchain wallet
Note: This package is currently in beta. Please test thoroughly in development environments before using in production.
A simple and secure package to manage ERC-4337 compliant wallets for EVM-compatible blockchains. This package provides a clean API for creating, managing, and interacting with account abstraction wallets using BIP-39 seed phrases and EVM-specific derivation paths.
This module is part of the WDK (Wallet Development Kit) project, which empowers developers to build secure, non-custodial wallets with unified blockchain access, stateless architecture, and complete user control.
For detailed documentation about the complete WDK ecosystem, visit docs.wdk.tether.io.
npm install @tetherto/wdk-wallet-evm-erc-4337import WalletManagerEvmErc4337 from '@tetherto/wdk-wallet-evm-erc-4337'
const seedPhrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'
const wallet = new WalletManagerEvmErc4337(seedPhrase, {
chainId: 11155111, // Sepolia
provider: 'https://sepolia.drpc.org',
bundlerUrl: 'https://api.pimlico.io/v2/sepolia/rpc?apikey=YOUR_KEY',
safeModulesVersion: '0.3.0',
useNativeCoins: true,
})
const account = await wallet.getAccount(0)
const address = await account.getAddress()
console.log('Smart account address:', address)
wallet.dispose()Some providers require an API key sent as an HTTP header. Pass bundlerHeaders and/or
paymasterHeaders to attach headers to every request to those services:
const wallet = new WalletManagerEvmErc4337(seedPhrase, {
chainId: 11155111,
provider: 'https://sepolia.drpc.org',
bundlerUrl: 'https://bundler.example.com/rpc',
bundlerHeaders: { Authorization: 'Bearer YOUR_KEY' },
safeModulesVersion: '0.3.0',
isSponsored: true,
paymasterUrl: 'https://paymaster.example.com/rpc',
paymasterHeaders: { Authorization: 'Bearer YOUR_KEY' },
})Both fields are optional. When omitted, requests are sent without extra headers, so providers
that authenticate via the URL (e.g. an apikey query parameter) keep working unchanged.
Authorization) to bundler and paymaster requestsparallel: true or a reusable nonceKey)By default every send uses the account's key-0 nonce, so it is sequential — a second send fired before the first is mined would collide on the nonce. To send independent operations concurrently, put each in its own nonce lane (an ERC-4337 two-dimensional nonce: a 192-bit key with its own sequence). Ops in different keys have no ordering constraint and validate independently, so they can be submitted at the same time.
// parallel: true → each send gets a fresh random lane (sequence 0). Fire them together:
const [a, b] = await Promise.all([
account.sendTransaction({ to: '0x...', value: 0n }, { parallel: true }),
account.sendTransaction({ to: '0x...', value: 0n }, { parallel: true })
])
// nonceKey: a string is a reusable named lane (same label resumes the same lane across sessions);
// a bigint is used as the raw uint192 key. Same key = ordered; different keys = parallel.
await account.sendTransaction(tx, { nonceKey: 'payments' })
await account.sendTransaction(tx, { nonceKey: 1n })Both options can also be set at construction (new WalletManagerEvmErc4337(seed, { ..., parallel: true })) and overridden per call. Precedence: nonceKey > parallel > default (key 0).
Notes:
SAME_SENDER_MEMPOOL_COUNT = 4). Firing more than 4 lanes concurrently may be rejected until earlier ops mine. This is a mempool validation limit, separate from parallel-key support, and can be raised by the bundler operator if needed.parallel: true mints a new EntryPoint nonce slot per send (a one-time gas cost per lane; permanent state). For repeated parallel workloads, reuse a fixed set of lanes with nonceKey labels instead of a fresh key every time.nonceKey collide on the sequence: the second is typically still accepted by the bundler and returns a hash, yet can never mine — its hash never resolves to a receipt and no error is thrown (a silent phantom hash). To run operations concurrently, give each its own lane (parallel: true, or distinct nonceKeys). If operations must share a lane, either await each send's receipt before firing the next, or batch them into a single UserOperation by passing an array to sendTransaction([tx1, tx2, ...]) — batched calls execute atomically, in order, under one nonce.| Topic | Description | Link |
|---|---|---|
| Overview | Module overview and feature summary | Wallet EVM ERC-4337 Overview |
| Usage | End-to-end integration walkthrough | Wallet EVM ERC-4337 Usage |
| Configuration | Provider, bundler, paymaster, and network setup | Wallet EVM ERC-4337 Configuration |
| API Reference | Complete class and type reference | Wallet EVM ERC-4337 API Reference |
| Example | Description |
|---|---|
| Create Wallet | Initialize ERC-4337 wallets with paymaster token and native coins modes |
| Manage Accounts | Work with multiple smart accounts and custom derivation paths |
| Check Balances | Query native token and ERC-20 balances for smart accounts |
| Read-Only Account | Monitor smart account balances and estimate fees without a private key |
| Send Transaction | Send transactions via UserOperations through the bundler |
| Token Transfer | Transfer ERC-20 tokens via UserOperations with gas mode overrides |
| Sign & Verify Message | Sign messages and verify signatures with ERC-4337 accounts |
| Fee Management | Retrieve current bundler fee rates |
| Memory Management | Securely dispose smart wallets and clear private keys from memory |
For detailed walkthroughs, see the Usage Guide. See all runnable examples in the wdk-examples repository.
Join the WDK Discord to connect with other developers.
For support, please open an issue on GitHub or reach out via email.
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.