Guide
Creating accounts
newSmartAccount 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 (proxy: 'upgradeable') the account is an UpgradeableAccount (CoinbaseSmartWalletV2) behind an ERC-1967 proxy, swappable later via an admin-signed upgrade. That implementation is pending deployment against the canonical Keystore, so until it lands you must pass an explicit implementation or choose proxy: 'erc1167' for an immutable minimal proxy to the DefaultAccount.
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'import { newSmartAccount } from 'viem/eip8130'
const owner = privateKeyToAccount(generatePrivateKey())
const account = newSmartAccount({ signer: owner })
account.address // counterfactual addressaccount.createChange // include in accountChanges to deploy on first use// First create bumps the local config sequence 0 → 1Pass a fixed salt to recover the same address across sessions and chains:
const account = newSmartAccount({ signer: owner, salt: '0x0000000000000000000000000000000000000000000000000000000000000001',})Signer types
P-256
import * as P256 from 'ox/P256'import { newSmartAccount, toP256Signer } from 'viem/eip8130'
const signer = toP256Signer({ privateKey: P256.randomPrivateKey() })const account = newSmartAccount({ signer })WebAuthn / passkey
import { createWebAuthnCredential, toWebAuthnAccount } from 'viem/account-abstraction'import { newSmartAccount, toWebAuthnSigner } from 'viem/eip8130'
const credential = await createWebAuthnCredential({ name: 'vibes' })const signer = toWebAuthnSigner(toWebAuthnAccount({ credential }))const account = newSmartAccount({ 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, newSmartAccount, toP256Signer } from 'viem/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 = newSmartAccount({ signer: owner, extraActors: [key.p256(p256.publicKey)],})Plain / delegated EOAs
For the cheapest auth path (bare 65-byte signature, no contract required), use toEoaAccount. You can later install smart-account code with account.delegate(impl) in the first transaction's account changes. Full EOA k1 revoke is pending the bridge upgrade.
import { privateKeyToAccount, generatePrivateKey } from 'viem/accounts'import { toEoaAccount } from 'viem/eip8130'
const account = toEoaAccount(privateKeyToAccount(generatePrivateKey()))// Later: account.delegate(impl) in the first tx's accountChangesDeployment templates
| Concept | Meaning |
|---|---|
| Upgradeable | Default (proxy: 'upgradeable'). ERC-1967 proxy to CoinbaseSmartWalletV2; admin-signed upgrade. Pending deployment: pass an explicit implementation for now. |
| 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. Authorize the EntryPoint as a K1 operational actor (key.k1(entryPoint) with actorScope.operator) so it can drive executeBatch.
import { canonicalEip8130Deployment, toSmartAccount,} from 'viem/eip8130'
const account = await toSmartAccount({ 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