Skip to content

Add middleware for UserOperation lifecycle management #33

Description

@ch4r10t33r

Title

Add middleware for UserOperation lifecycle management

Labels

enhancement, account-abstraction, middleware, ux

Description

Create middleware to automate the complete UserOperation workflow, making it as easy to use as regular transactions.

Requirements

UserOperation Builder

  • Implement builder pattern for creating UserOperations:
    pub const UserOperationBuilder = struct {
        allocator: Allocator,
        sender: ?Address,
        call_data: ?[]u8,
        // ... partial fields
        
        pub fn init(allocator: Allocator) UserOperationBuilder;
        pub fn setSender(self: *Self, address: Address) *Self;
        pub fn setCallData(self: *Self, data: []u8) *Self;
        pub fn setValue(self: *Self, value: u256) *Self;
        pub fn usePaymaster(self: *Self, service: *Paymaster) *Self;
        pub fn estimateGas(self: *Self, provider: *Provider) *Self;
        pub fn build(self: *Self) !UserOperation;
    };

Nonce Management

  • UserOpNonceMiddleware:
    • Track nonces per smart account
    • Support nonce keys for parallel operations
    • Handle sequential and parallel nonce modes
    • Auto-increment after submission

Gas Management

  • UserOpGasMiddleware:
    • Automatic gas estimation
    • Gas price suggestions (maxFeePerGas, maxPriorityFeePerGas)
    • Safety margins and multipliers
    • Network-specific optimizations

Signing Middleware

  • UserOpSignerMiddleware:
    • Automatic UserOp signing
    • Support multiple signer types
    • EIP-712 structured data signing
    • Multi-sig coordination

Submission & Confirmation

  • UserOpSubmissionMiddleware:

    • Automatic bundler selection
    • Retry logic for failed submissions
    • Wait for confirmation with timeout
    • Status polling
  • waitForUserOperation(hash: Hash, timeout_ms: u64) UserOperationReceipt

Complete Workflow Chain

  • Combine all middleware:
    const aa_provider = try provider
        .withSmartAccount(account)
        .withPaymaster(paymaster_service)
        .withUserOpMiddleware(.{
            .auto_estimate_gas = true,
            .auto_nonce = true,
            .auto_sign = true,
        });
    
    // Simple as a regular transaction!
    const receipt = try aa_provider.sendUserOperation(.{
        .to = recipient,
        .value = @as(u256, 1_000_000),
        .data = &[_]u8{},
    });

Error Recovery

  • Handle common AA errors:
    • Nonce mismatch recovery
    • Gas estimation failures
    • Paymaster rejections
    • Signature issues
    • Account not deployed

File Structure

src/account_abstraction/middleware/
  ├── builder.zig              # UserOperation builder
  ├── nonce.zig                # Nonce management
  ├── gas.zig                  # Gas estimation
  ├── signer.zig               # Signing
  ├── submission.zig           # Submission & confirmation
  └── root.zig                 # Combined middleware

Example Usage

// Simple sponsored transaction
const aa_provider = try provider
    .withSmartAccount(my_account)
    .withPaymaster(pimlico);

// Send like a normal transaction!
const receipt = try aa_provider.sendTransaction(.{
    .to = recipient,
    .value = @as(u256, 1_000_000_000_000_000_000), // 1 ETH
    .data = &[_]u8{},
});

std.debug.print("✅ Gasless transaction confirmed!\n", .{});
std.debug.print("   Hash: {}\n", .{receipt.userOpHash});
std.debug.print("   Gas paid by: {}\n", .{receipt.paymaster.?});

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions