Skip to content

Commit ba5ce2a

Browse files
Merge pull request #508 from pimlicolabs/claude/beautiful-elion
docs: add comprehensive documentation and improve test infrastructure
2 parents 7f7752e + 97cc8a7 commit ba5ce2a

44 files changed

Lines changed: 4987 additions & 53 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/README.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# permissionless
2+
3+
> **Version 0.3.5** | TypeScript SDK for ERC-4337 Account Abstraction, built on [viem](https://viem.sh)
4+
5+
`permissionless` is a utility library for working with ERC-4337 smart accounts, bundlers, and paymasters. It extends viem's account abstraction primitives with support for 12 smart account implementations, multiple bundler providers, ERC-7579 modular accounts, and EIP-7702 delegation.
6+
7+
## Peer Dependencies
8+
9+
| Package | Version | Required |
10+
|---------|---------|----------|
11+
| `viem` | `^2.44.4` | Yes |
12+
| `ox` | `^0.11.3` | No (optional, for WebAuthn/passkey features) |
13+
14+
## Install
15+
16+
```bash
17+
npm install permissionless viem
18+
```
19+
20+
## Quick Start
21+
22+
```typescript
23+
import { createPublicClient, http } from "viem"
24+
import { sepolia } from "viem/chains"
25+
import { privateKeyToAccount } from "viem/accounts"
26+
import { toSimpleSmartAccount } from "permissionless/accounts"
27+
import { createSmartAccountClient } from "permissionless"
28+
29+
// 1. Create an owner (the EOA that controls the smart account)
30+
const owner = privateKeyToAccount("0x...")
31+
32+
// 2. Create a public client for on-chain reads
33+
const publicClient = createPublicClient({
34+
chain: sepolia,
35+
transport: http("https://rpc.sepolia.org"),
36+
})
37+
38+
// 3. Create the smart account (computes counterfactual address)
39+
const account = await toSimpleSmartAccount({
40+
client: publicClient,
41+
owner,
42+
})
43+
44+
// 4. Create a smart account client (wraps a bundler)
45+
const smartAccountClient = createSmartAccountClient({
46+
account,
47+
chain: sepolia,
48+
bundlerTransport: http("https://bundler.example.com"),
49+
})
50+
51+
// 5. Send a transaction (creates, signs, and submits a UserOperation)
52+
const txHash = await smartAccountClient.sendTransaction({
53+
to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
54+
value: 0n,
55+
data: "0x",
56+
})
57+
```
58+
59+
## Documentation
60+
61+
### Architecture
62+
63+
- [Package Overview](./architecture/01-overview.md) -- module hierarchy, viem integration, decorator pattern
64+
- [Export Map](./architecture/02-export-map.md) -- complete inventory of every subpath export and symbol
65+
- [Build System](./architecture/03-build-system.md) -- TypeScript compilation, output formats, tooling
66+
67+
### ERC-4337 Concepts
68+
69+
- [ERC-4337 Overview](./concepts/01-erc4337-overview.md) -- primitives mapped to library abstractions
70+
- [EntryPoint Versions](./concepts/02-entrypoint-versions.md) -- 0.6 vs 0.7 vs 0.8 comparison
71+
- [Smart Account Lifecycle](./concepts/03-smart-account-lifecycle.md) -- end-to-end UserOperation flow
72+
- [EIP-7702 Delegation](./concepts/04-eip-7702.md) -- EOA code delegation support
73+
74+
### Smart Accounts
75+
76+
- [Accounts Overview](./accounts/README.md) -- common patterns, parameter reference, summary table
77+
- [SimpleSmartAccount](./accounts/simple-smart-account.md)
78+
- [SimpleSmartAccount (EIP-7702)](./accounts/simple-smart-account-7702.md)
79+
- [SafeSmartAccount](./accounts/safe-smart-account.md)
80+
- [KernelSmartAccount](./accounts/kernel-smart-account.md)
81+
- [EcdsaKernelSmartAccount](./accounts/ecdsa-kernel-smart-account.md)
82+
- [KernelSmartAccount (EIP-7702)](./accounts/kernel-smart-account-7702.md)
83+
- [LightSmartAccount](./accounts/light-smart-account.md)
84+
- [BiconomySmartAccount](./accounts/biconomy-smart-account.md)
85+
- [TrustSmartAccount](./accounts/trust-smart-account.md)
86+
- [EtherspotSmartAccount](./accounts/etherspot-smart-account.md)
87+
- [NexusSmartAccount](./accounts/nexus-smart-account.md)
88+
- [ThirdwebSmartAccount](./accounts/thirdweb-smart-account.md)
89+
90+
### Clients
91+
92+
- [Clients Overview](./clients/README.md) -- client types, decorator pattern
93+
- [SmartAccountClient](./clients/smart-account-client.md) -- `createSmartAccountClient`
94+
- [PimlicoClient](./clients/pimlico-client.md) -- `createPimlicoClient` + `pimlicoActions`
95+
- [PasskeyServerClient](./clients/passkey-server-client.md) -- `createPasskeyServerClient`
96+
97+
### Actions
98+
99+
- [Actions Overview](./actions/README.md) -- action system, standalone vs decorator usage
100+
- [Public Actions](./actions/public-actions.md) -- `getAccountNonce`, `getSenderAddress`
101+
- [Smart Account Actions](./actions/smart-account-actions.md) -- `sendTransaction`, `sendCalls`, `signMessage`, `signTypedData`, `writeContract`
102+
- [Pimlico Actions](./actions/pimlico-actions.md) -- gas price, sponsorship, token quotes
103+
- [ERC-7579 Actions](./actions/erc7579-actions.md) -- module install/uninstall/query
104+
- [Etherspot Actions](./actions/etherspot-actions.md) -- Etherspot bundler actions
105+
- [Passkey Server Actions](./actions/passkey-server-actions.md) -- WebAuthn registration/authentication
106+
107+
### Utilities
108+
109+
- [Utils Overview](./utils/README.md) -- utility categories
110+
- [Nonce Utils](./utils/nonce-utils.md) -- `encodeNonce`, `decodeNonce`
111+
- [UserOperation Utils](./utils/user-operation-utils.md) -- `getPackedUserOperation`, `getRequiredPrefund`, `deepHexlify`
112+
- [ERC-7579 Utils](./utils/erc7579-utils.md) -- `encode7579Calls`, `decode7579Calls`, `encodeInstallModule`
113+
- [ERC-20 Utils](./utils/erc20-utils.md) -- `erc20AllowanceOverride`, `erc20BalanceOverride`
114+
- [Account Utils](./utils/account-utils.md) -- `isSmartAccountDeployed`, `toOwner`
115+
116+
### Types & Errors
117+
118+
- [Types & Errors Overview](./types-and-errors/README.md)
119+
- [Errors](./types-and-errors/errors.md) -- `AccountNotFoundError`, `InvalidEntryPointError`
120+
- [RPC Schemas](./types-and-errors/rpc-schemas.md) -- `PimlicoRpcSchema`, `EtherspotBundlerRpcSchema`
121+
122+
### Experimental
123+
124+
- [Experimental Overview](./experimental/README.md) -- stability warning
125+
- [ERC-20 Paymaster](./experimental/erc20-paymaster.md) -- `prepareUserOperationForErc20Paymaster`
126+
127+
### Testing
128+
129+
- [Testing Infrastructure](./testing/01-architecture.md) -- existing test docs (6 files)
130+
131+
## External Resources
132+
133+
- [Pimlico Documentation](https://docs.pimlico.io/permissionless) -- hosted user guides and tutorials
134+
- [GitHub Repository](https://github.com/pimlicolabs/permissionless.js)
135+
- [viem Documentation](https://viem.sh)
136+
- [ERC-4337 Specification](https://eips.ethereum.org/EIPS/eip-4337)

docs/accounts/README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Smart Accounts
2+
3+
permissionless provides 12 smart account implementations, each created by an async factory function that returns a viem `SmartAccount`.
4+
5+
## Common Factory Pattern
6+
7+
Every account is created by a `to*SmartAccount()` function:
8+
9+
```typescript
10+
import { toSimpleSmartAccount } from "permissionless/accounts"
11+
12+
const account = await toSimpleSmartAccount({
13+
client: publicClient, // viem Client for on-chain reads
14+
owner, // key that controls the account
15+
// Optional parameters:
16+
entryPoint: { address, version: "0.7" },
17+
factoryAddress: "0x...",
18+
index: 0n,
19+
address: "0x...",
20+
nonceKey: 0n,
21+
})
22+
```
23+
24+
### Common Parameters
25+
26+
| Parameter | Type | Required | Default | Description |
27+
|-----------|------|----------|---------|-------------|
28+
| `client` | `Client<Transport, Chain \| undefined>` | Yes | -- | viem client for on-chain reads (public client, wallet client, etc.) |
29+
| `owner` | `LocalAccount \| WalletClient \| EthereumProvider` | Yes | -- | The key that signs UserOperations |
30+
| `entryPoint` | `{ address: Address, version: EntryPointVersion }` | No | `{ address: entryPoint07Address, version: "0.7" }` | EntryPoint contract to use |
31+
| `factoryAddress` | `Address` | No | Account-specific default | Factory contract that deploys the account |
32+
| `index` | `bigint` | No | `0n` | Salt for deterministic address computation |
33+
| `address` | `Address` | No | Computed from factory | Override the counterfactual address |
34+
| `nonceKey` | `bigint` | No | `0n` | Default nonce key for 2D nonce system |
35+
36+
Note: Not all accounts support all parameters. EIP-7702 accounts do not accept `factoryAddress`, `index`, `address`, or `nonceKey`. Some accounts have additional provider-specific parameters.
37+
38+
### Common Return Interface
39+
40+
Every `SmartAccount` returned by a factory has these methods:
41+
42+
| Method | Returns | Description |
43+
|--------|---------|-------------|
44+
| `getAddress()` | `Address` | Counterfactual address (works pre-deployment) |
45+
| `encodeCalls(calls)` | `Hex` | Encode calls into account-specific execution calldata |
46+
| `decodeCalls(data)` | `{ to, value, data }[]` | Decode calldata back to individual calls |
47+
| `getNonce()` | `bigint` | Read current nonce from EntryPoint |
48+
| `getStubSignature()` | `Hex` | Dummy signature for gas estimation |
49+
| `sign(hash)` | `Hex` | Sign a raw hash |
50+
| `signMessage(message)` | `Hex` | EIP-191 message signature (ERC-1271) |
51+
| `signTypedData(typedData)` | `Hex` | EIP-712 typed data signature (ERC-1271) |
52+
| `signUserOperation(userOp)` | `Hex` | Sign a complete UserOperation |
53+
| `getFactoryArgs()` | `{ factory, factoryData } \| undefined` | Factory data for first UserOp (undefined after deployment) |
54+
55+
## Account Summary
56+
57+
| Account | Factory Function | EntryPoint | ERC-7579 | EIP-7702 | ERC-1271 |
58+
|---------|-----------------|------------|----------|----------|----------|
59+
| [Simple](./simple-smart-account.md) | `toSimpleSmartAccount` | 0.6, 0.7, 0.8 | No | No | No |
60+
| [Simple (7702)](./simple-smart-account-7702.md) | `to7702SimpleSmartAccount` | 0.8 | No | Yes | No |
61+
| [Safe](./safe-smart-account.md) | `toSafeSmartAccount` | 0.6, 0.7 | Yes (0.7) | No | Yes |
62+
| [Kernel](./kernel-smart-account.md) | `toKernelSmartAccount` | 0.6, 0.7 | Yes (v3+) | No | Yes |
63+
| [ECDSA Kernel](./ecdsa-kernel-smart-account.md) | `toEcdsaKernelSmartAccount` | 0.6, 0.7 | Yes (v3+) | No | Yes |
64+
| [Kernel (7702)](./kernel-smart-account-7702.md) | `to7702KernelSmartAccount` | 0.8 | Yes | Yes | Yes |
65+
| [Light](./light-smart-account.md) | `toLightSmartAccount` | 0.6, 0.7 | No | No | Yes |
66+
| [Biconomy](./biconomy-smart-account.md) | `toBiconomySmartAccount` | 0.7 | No | No | Yes |
67+
| [Trust](./trust-smart-account.md) | `toTrustSmartAccount` | 0.7 | No | No | Yes |
68+
| [Etherspot](./etherspot-smart-account.md) | `toEtherspotSmartAccount` | 0.7 | Yes | No | Yes |
69+
| [Nexus](./nexus-smart-account.md) | `toNexusSmartAccount` | 0.7 | Yes | No | Yes |
70+
| [Thirdweb](./thirdweb-smart-account.md) | `toThirdwebSmartAccount` | 0.7 | No | No | Yes |
71+
72+
## Import
73+
74+
All account factories are available from a single subpath:
75+
76+
```typescript
77+
import {
78+
toSimpleSmartAccount,
79+
to7702SimpleSmartAccount,
80+
toSafeSmartAccount,
81+
toKernelSmartAccount,
82+
toEcdsaKernelSmartAccount,
83+
to7702KernelSmartAccount,
84+
toLightSmartAccount,
85+
toBiconomySmartAccount,
86+
toTrustSmartAccount,
87+
toEtherspotSmartAccount,
88+
toNexusSmartAccount,
89+
toThirdwebSmartAccount,
90+
} from "permissionless/accounts"
91+
```
92+
93+
## Types
94+
95+
Each account exports three types following a consistent naming pattern:
96+
97+
```typescript
98+
import type {
99+
ToSimpleSmartAccountParameters, // Factory input type
100+
ToSimpleSmartAccountReturnType, // Factory output type
101+
SimpleSmartAccountImplementation, // Implementation details type
102+
} from "permissionless/accounts"
103+
```
104+
105+
Some accounts export additional types:
106+
- `SafeVersion` -- `"1.4.1" | "1.5.0"`
107+
- `LightAccountVersion` -- `"1.1.0" | "2.0.0"`
108+
- `KernelVersion` -- Kernel version identifier
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# BiconomySmartAccount
2+
3+
> **Deprecated:** For new integrations, use [NexusSmartAccount](./nexus-smart-account.md) instead.
4+
5+
The Biconomy smart account uses an ECDSA validation module and supports EntryPoint 0.6.
6+
7+
## Import
8+
9+
```typescript
10+
import { toBiconomySmartAccount } from "permissionless/accounts"
11+
import type {
12+
ToBiconomySmartAccountParameters,
13+
ToBiconomySmartAccountReturnType,
14+
BiconomySmartAccountImplementation,
15+
} from "permissionless/accounts"
16+
```
17+
18+
## Factory Function
19+
20+
```typescript
21+
async function toBiconomySmartAccount(
22+
parameters: ToBiconomySmartAccountParameters
23+
): Promise<ToBiconomySmartAccountReturnType>
24+
```
25+
26+
## Parameters
27+
28+
| Parameter | Type | Required | Default | Description |
29+
|-----------|------|----------|---------|-------------|
30+
| `client` | `Client` | Yes | -- | viem client for on-chain reads |
31+
| `owners` | `[LocalAccount \| WalletClient \| EthereumProvider]` | Yes | -- | Single owner in array format |
32+
| `entryPoint` | `{ address: Address, version: "0.6" }` | Yes | -- | Must be EntryPoint 0.6 |
33+
| `address` | `Address` | No | Computed | Override counterfactual address |
34+
| `index` | `bigint` | No | `0n` | Salt for deterministic address |
35+
| `nonceKey` | `bigint` | No | `0n` | Default nonce key |
36+
| `factoryAddress` | `Address` | No | `0x000000a56Aaca3e9a4C479ea6b6CD0DbcB6634F5` | Factory contract |
37+
| `ecdsaModuleAddress` | `Address` | No | `0x0000001c5b32F37F5beA87BDD5374eB2aC54eA8e` | ECDSA module |
38+
| `accountLogicAddress` | `Address` | No | `0x0000002512019Dafb59528B82CB92D3c5D2423aC` | Account logic |
39+
| `fallbackHandlerAddress` | `Address` | No | Default | Fallback handler |
40+
41+
## Supported EntryPoint Versions
42+
43+
- **0.6** only (required)
44+
45+
## Example
46+
47+
```typescript
48+
import { createPublicClient, http } from "viem"
49+
import { sepolia } from "viem/chains"
50+
import { privateKeyToAccount } from "viem/accounts"
51+
import { toBiconomySmartAccount } from "permissionless/accounts"
52+
53+
const account = await toBiconomySmartAccount({
54+
client: createPublicClient({ chain: sepolia, transport: http() }),
55+
owners: [privateKeyToAccount("0x...")],
56+
entryPoint: {
57+
address: "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
58+
version: "0.6",
59+
},
60+
})
61+
```
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# EcdsaKernelSmartAccount
2+
3+
> **Note:** This account is a convenience wrapper around `toKernelSmartAccount`. For new integrations, prefer using `toKernelSmartAccount` directly.
4+
5+
The ECDSA Kernel smart account wraps `toKernelSmartAccount` with an explicit `ecdsaValidatorAddress` parameter.
6+
7+
## Import
8+
9+
```typescript
10+
import { toEcdsaKernelSmartAccount } from "permissionless/accounts"
11+
import type {
12+
ToEcdsaKernelSmartAccountParameters,
13+
ToEcdsaKernelSmartAccountReturnType,
14+
EcdsaKernelSmartAccountImplementation,
15+
} from "permissionless/accounts"
16+
```
17+
18+
## Factory Function
19+
20+
```typescript
21+
async function toEcdsaKernelSmartAccount<
22+
entryPointVersion extends "0.6" | "0.7",
23+
kernelVersion extends KernelVersion<entryPointVersion>,
24+
owner extends OneOf<EthereumProvider | WalletClient | LocalAccount>
25+
>(
26+
parameters: ToEcdsaKernelSmartAccountParameters<entryPointVersion, kernelVersion, owner>
27+
): Promise<ToEcdsaKernelSmartAccountReturnType<entryPointVersion>>
28+
```
29+
30+
## Parameters
31+
32+
Inherits all parameters from `toKernelSmartAccount` plus:
33+
34+
| Parameter | Type | Required | Default | Description |
35+
|-----------|------|----------|---------|-------------|
36+
| `ecdsaValidatorAddress` | `Address` | No | Default ECDSA validator | Custom ECDSA validator contract |
37+
38+
See [KernelSmartAccount](./kernel-smart-account.md) for all other parameters.
39+
40+
## Implementation Details
41+
42+
Internally maps `ecdsaValidatorAddress` to `validatorAddress` and calls `toKernelSmartAccount`.
43+
44+
## Example
45+
46+
```typescript
47+
import { createPublicClient, http } from "viem"
48+
import { sepolia } from "viem/chains"
49+
import { privateKeyToAccount } from "viem/accounts"
50+
import { toEcdsaKernelSmartAccount } from "permissionless/accounts"
51+
52+
const publicClient = createPublicClient({
53+
chain: sepolia,
54+
transport: http(),
55+
})
56+
57+
const account = await toEcdsaKernelSmartAccount({
58+
client: publicClient,
59+
owners: [privateKeyToAccount("0x...")],
60+
version: "0.3.1",
61+
entryPoint: {
62+
address: entryPoint07Address,
63+
version: "0.7",
64+
},
65+
})
66+
```

0 commit comments

Comments
 (0)