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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions