Guide
Creating accounts
newSmartAccount8130 turns a signer into a counterfactual EIP-8130 smart account. The account is not deployed yet; deployment happens atomically inside its first transaction.
Default smart account
By default the account is an UpgradeableAccount behind an ERC-1967 proxy (swappable later via an admin-signed upgrade). Pass upgradeable: false for an immutable CanonicalHighRatePayerAccount (ERC-1167) when you care about throughput and a fixed implementation.
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'import { newSmartAccount8130 } from 'viem/experimental/eip8130'
const owner = privateKeyToAccount(generatePrivateKey())
const account = newSmartAccount8130({ signer: owner })
account.address // counterfactual addressaccount.createChange // include in accountChanges to deploy on first usePass a fixed salt to recover the same address across sessions and chains:
const account = newSmartAccount8130({ signer: owner, salt: '0x0000000000000000000000000000000000000000000000000000000000000001',})Signer types
P-256
import * as P256 from 'ox/P256'import { newSmartAccount8130, toP256Signer } from 'viem/experimental/eip8130'
const signer = toP256Signer({ privateKey: P256.randomPrivateKey() })const account = newSmartAccount8130({ signer })WebAuthn / passkey
import { createWebAuthnCredential, toWebAuthnAccount } from 'viem/account-abstraction'import { newSmartAccount8130, toWebAuthnSigner } from 'viem/experimental/eip8130'
const credential = await createWebAuthnCredential({ name: 'vibes' })const signer = toWebAuthnSigner(toWebAuthnAccount({ credential }))const account = newSmartAccount8130({ signer })Multiple initial keys
Register additional actors at creation with extraActors and the key.* builders. Viem sorts by actorId for you (a protocol requirement).
import { key, newSmartAccount8130, toP256Signer } from 'viem/experimental/eip8130'import * as P256 from 'ox/P256'import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'
const owner = privateKeyToAccount(generatePrivateKey())const p256 = toP256Signer({ privateKey: P256.randomPrivateKey() })
const account = newSmartAccount8130({ signer: owner, extraActors: [key.p256(p256.publicKey)],})Plain / delegated EOAs
For the cheapest auth path (bare 65-byte signature, no contract required), use toEoa8130Account. You can later install smart-account code with account.delegate(impl) in the first transaction's account changes.
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'import { toEoa8130Account } from 'viem/experimental/eip8130'
const account = toEoa8130Account(privateKeyToAccount(generatePrivateKey()))// Later: account.delegate(impl) in the first tx's accountChangesDeployment templates
| Concept | Meaning |
|---|---|
| Upgradeable | Default. ERC-1967 proxy; upgrade via upgradeBySignature. |
| DefaultHighRate | Immutable ERC-1167. Prefer for parallel / high-throughput accounts. |
| Default | Standalone building block; EIP-7702 delegation target. |
| ERC-4337 | Portable implementation for chains without native 8130 + bundler providers. |
Cross-chain (ERC-4337) portability
On chains without native EIP-8130, wrap the same account as a Viem Smart Account with the ERC-4337 implementation. Register the EntryPoint as a trusted-executor actor so it can drive executeBatch.
import { canonicalEip8130Deployment, toSmartAccount8130,} from 'viem/experimental/eip8130'
const account = await toSmartAccount8130({ client, owner, userSalt: '0x…', initialActors: [/* key.k1(owner.address), … */], implementation: canonicalEip8130Deployment.accounts.erc4337,})Same salt + initial actors give the same counterfactual address on native Vibenet and on portable providers. More in Multichain.
- Full API: Viem. Creating an Account