stackup-wallet / userop.js

A simple JS library for building ERC-4337 UserOperations.
MIT License
113 stars 32 forks source link

Support middleware concurrent #105

Open alberthuang24 opened 9 months ago

alberthuang24 commented 9 months ago

Question

Now let's assume we have a builder like this one.

        return instance
            .useDefaults({
                sender: instance.proxyImpl.address,
                verificationGasLimit: 200000,
                preVerificationGas: 21000
            })
            .useMiddleware(instance.resolveAccount)
            .useMiddleware(Presets.Middleware.getGasPrice(provider))
            .useMiddleware(SodiumCallData(instance, signer))
            .useMiddleware(instance.paymasterMiddleware())
            .useMiddleware(estimateUserOperationGas(instance.provider))
-> resolveAccount(100ms) -> getGasPrice (100ms) -> setupCalldata (100ms) -> paymasterMiddleware(100ms) -> estimateUserOperationGas(100ms).

The buildOp execution will be very slow because they are executed synchronously.

Maybe we can optimize them this way

        return instance
            .useDefaults({
                sender: instance.proxyImpl.address,
                verificationGasLimit: 200000,
                preVerificationGas: 21000
            })
            .useConcurrentMiddleware(instance.resolveAccount)
            .useConcurrentMiddleware(Presets.Middleware.getGasPrice(provider))
            .useConcurrentMiddleware(SodiumCallData(instance, signer))
            .useConcurrentMiddleware(instance.paymasterMiddleware())
            .useMiddleware(estimateUserOperationGas(instance.provider))
  async buildOp(entryPoint: string, chainId: BigNumberish) {
    const ctx = new UserOperationMiddlewareCtx(
      this.currOp,
      entryPoint,
      chainId
    );

    await Promise.all(this.concurrentMiddlewareStack.map(fn));
    for (const fn of this.middlewareStack) {
      await fn(ctx);
    }
    this.setPartial(ctx.op);

    return OpToJSON(this.currOp);
  }
(resolveAccount, getGasPrice, setupCalldata, paymasterMiddleware)(100ms) -> estimateUserOperationGas(100ms);