eth-infinitism/bundler

@account-abstraction/sdk TypeError: class constructors must be invoked with 'new'

jacque006 opened this issue · 4 comments

env

Ubuntu: 22.04.2 (Also seeing in OSX)
NodeJS: 18.16.0
Firefox: 112.0.2 (64-bit) (Also seeing in Brave)

ethers@v5.7.2
account-abtraction/sdk@v0.6.0

error

In browser

Uncaught (in promise) TypeError: class constructors must be invoked with 'new'
    SimpleAccountFactory__factory SimpleAccountFactory__factory.js:111
    wrapProvider Provider.js:24
    getAaProvider page.tsx:29
    Home page.tsx:40
    commitHookEffectListMount react-dom.development.js:19974
    commitHookPassiveMountEffects react-dom.development.js:22022
    commitPassiveMountOnFiber react-dom.development.js:22127

code

https://github.com/web3well/eth-global-lisbon-hackathon/blob/1d53cb7aa4f6d00d904156e88bd06f7b1841f5b1/frontend/src/app/page.tsx#L28

This should also reproduce (in browser):

import { wrapProvider } from "@account-abstraction/sdk";
import { providers, Wallet } from "ethers";

const privateKey = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; // or other, well known key
const entryPointAddress = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
const bundlerUrl = "http://localhost:3000/rpc";
const rpcUrl = "http://localhost:8545";

const provider = new providers.JsonRpcProvider(
    rpcUrl,
    {
        name: 'localhost',
        chainId: 31337,
    },
);
const signer = new Wallet(privateKey, provider);

const main = async () => {
    const aaProvider = await wrapProvider(
        provider as any,
        {
          entryPointAddress,
          bundlerUrl,
        },
        signer as any,
      )
    console.log(aaProvider);
};

main()
    .catch((err) => { console.error(err) });

workaround

getwax/eth-global-lisbon-hackathon@8e75fad

This appears to be due to how ethers.js & typechain is transpiled in @account-abstraction/contracts targeting an older es format. It may be desirable to target a newer es version (es6, esnext) and allow project transpilers to target their desired es version.

Specifically, the issue occurs in an environment where ethers hasn't also been transpiled down to ES5.

In @account-abstraction/contracts/dist/types/factories/SimpleAccount__factory.js:

var SimpleAccount__factory = /** @class */ (function (_super) {
    __extends(SimpleAccount__factory, _super);
    function SimpleAccount__factory() {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        var _this = this;
        if (isSuperArgs(args)) {
            _this = _super.apply(this, args) || this;
        }
        else {

            // ========= HERE ==========
            // _super is ethers.ContractFactory, which is a real class
            // the idea is that we're extending that class, but the ES5
            // transpiled code doesn't work with a real class because
            // on this line ethers.ContractFactory is called as a function
            // without the new keyword
            //
            // The solution is to avoid transpiling code in libraries so that
            // transpilation can be done downstream in a consistent way
            // and only as much as necessary

            _this = _super.call(this, _abi, _bytecode, args[0]) || this;
        }
        return _this;
    }
    SimpleAccount__factory.prototype.deploy = function (anEntryPoint, overrides) {
        return _super.prototype.deploy.call(this, anEntryPoint, overrides || {});
    };
    SimpleAccount__factory.prototype.getDeployTransaction = function (anEntryPoint, overrides) {
        return _super.prototype.getDeployTransaction.call(this, anEntryPoint, overrides || {});
    };
    SimpleAccount__factory.prototype.attach = function (address) {
        return _super.prototype.attach.call(this, address);
    };
    SimpleAccount__factory.prototype.connect = function (signer) {
        return _super.prototype.connect.call(this, signer);
    };
    SimpleAccount__factory.createInterface = function () {
        return new ethers_1.utils.Interface(_abi);
    };
    SimpleAccount__factory.connect = function (address, signerOrProvider) {
        return new ethers_1.Contract(address, _abi, signerOrProvider);
    };
    SimpleAccount__factory.bytecode = _bytecode;
    SimpleAccount__factory.abi = _abi;
    return SimpleAccount__factory;
}(ethers_1.ContractFactory));

I have the same problem. Someone was able to solve it?

I have the same problem. Someone was able to solve it?

@PavelNaydanov Kinda. Workaround: getwax/eth-global-lisbon-hackathon@8e75fad.

I think it was a mistake to add the typechain generated classes of a specific version in the contracts package.
In a future version it will be removed, and leave just the contract and ABI files.