Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: e is not a function #327

Open
ghost opened this issue Jan 1, 2022 · 8 comments
Open

TypeError: e is not a function #327

ghost opened this issue Jan 1, 2022 · 8 comments

Comments

@ghost
Copy link

ghost commented Jan 1, 2022

Dear team,

I've played with the Plug Wallet and tried to integrate it into my small app, but to no avail. I'm using version 0.4.4 with latest Firefox and here's my code almost without any modifications from your docs:

await window?.ic?.plug?.requestConnect({ host, });
const status = await window.ic.plug.isConnected();
console.log("connected:", status, canisterId, idlFactory);
const actor = await window.ic.plug.createActor({ canisterId, idlFactory });

The first 3 lines work as expected and I see a console output with status being true, my canister id and that the idlFunction is initialized. However, the execution of createAgent fails with an exception (see the screenshot).

Screenshot 2022-01-01 at 13 28 06

Since it's an internal exception and not an error returned from the actor constructor, I am a bit clueless about how to proceed.

Any help is appreciated!

@tomiir
Copy link
Contributor

tomiir commented Jan 4, 2022

Hi! At first sight I can see that you are passing idlFactory when it's expecting interfaceFactory.
Other than that the code seems fine I think. Let me know if this works or not. You can also always drop us a message in the discord channel (should get a quicker answer too!)

  public async createActor<T>({
    canisterId,
    interfaceFactory,
  }: CreateActor<T>): Promise<ActorSubclass<T>> 

@ghost
Copy link
Author

ghost commented Jan 7, 2022

@tomiir thanks so much, this was indeed the problem. After I started passing idlFactory as interfaceFactory I indeed could create the agent successfully:

        let status = await window.ic.plug.isConnected();
        if (status) {
            console.log(status, host, canisterId, idlFactory);
            const actor = await window.ic.plug.createActor({ host, canisterId, interfaceFactory: idlFactory });
            let result = await actor.popular_tags();
        }

However now I run into the next problem with this newly created agent. Whenever I call any function on it (eg popular_tags in the example above) I always get Uncaught (in promise) Error: No Agent could be found. I asked this question in #plug channel on discord, but didn't get useful hints. Do you have an idea maybe?

@ghost
Copy link
Author

ghost commented Jan 7, 2022

Btw, I figured out the issue - my flow reloaded the window after the connection and this destroyed the agent. I'm puzzled right now how to avoid reconnecting on every new app visit, but will consult the docs first. Sorry for the noise!

@ghost
Copy link
Author

ghost commented Jan 8, 2022

FYI, I decided to not integrate Plug for now. I managed to get it working, but I don't think the only workflow I found working is user friendly. Let me sketch the issues I encountered so that you can consider improving them in the future.

  1. TypeError: e is not a function: was caused by me misreading idlFactory as interfaceFactory. So it seems that interfaceFactory is a required parameter of the createActor constructor. This problem wouldn't be a problem if createActor would check all required arguments and return an error if one of them is missing.
  2. Uncaught (in promise) Error: No Agent could be found.: it turns out that for some unclear (to me) reason, even if await window.ic.plug.isConnected() returns true I still need to call await window.ic.plug.requestConnect({ host, whitelist: [canisterId] }) so that the agent gets initialized. Which effectively means there is no notion of a session and the Plug modal is shown on every single loading of the page. This makes no sense to me.
  3. Once I "fixed" the issue by requiring a connection on every load I ran into the next issue of failing to certify responses from the back end. I realized that it might has something to do with Plug using the NNS root key in local development mode, so with some googling and reading the dfinity forum I manager to overcome this problem using this code:
    if (process.env.DFX_NETWORK == "local") await window.ic.plug.agent.fetchRootKey();
    But it really should be in the docs or even automated.
  4. The logout using await window.ic.plug.disconnect() is not working: it just hangs on that await for quite some time and then eventually I see the error Uncaught (in promise) Error: There was an error when this app/page tried to interact with your wallet in Plug. Please contact this project’s developers. I guess I could solve this as well somehow, but I decided to deprioritize the ingreation for now.

I help it helps during the future development!

@ghost ghost closed this as completed Jan 8, 2022
@rocky-fleek
Copy link
Contributor

Reopening this issue as it contains a lot of valid points and possible improvements.

@rocky-fleek rocky-fleek reopened this Jan 21, 2022
@rocky-fleek
Copy link
Contributor

rocky-fleek commented Jan 21, 2022

Hi @taggrx.
Thanks for taking the time to debug and describe these issues so thoroughly and sorry for the late reply 🙏
You make very valid points and I'll try to address them individually:

  1. You are right. We'll add parameter validation/sanitization on the provider interface methods. We use typescript but clearly this won't fail on JS code at all.
  2. Will review this point in particular, as the createActor method should be creating an agent if it's not present. The issue with the agent is that whenever a page refreshes, the inpage script in plug is re-executed, and the provider re-instantiated, causing the agent to be removed. We've had this issue for some time now and part of the reason we are trying to push the createActor approach (instead of creating actors with ic.plug.agent) is to ensure the agent is created at the time of execution and thus always available to the user.
  3. This fix is being added to the new version of plug. Probably coming out next week. (Add root key fetching if host is not default plug-inpage-provider#68)
  4. Will look into this as well. Might have to do with a refactor we did in the frontend regarding events and connection statuses.

We'll be scoping and planning these fixes next week and will let you know when they are released.
Thanks again for the feedback and feel free to drop a message in our discord anytime!
https://discord.gg/pFjDRhms

@ghost
Copy link
Author

ghost commented Jan 21, 2022

Thanks so much for addressing my feedback! I should have more time in a couple of weeks and would be very happy to try integrating Plug again!

@riveign
Copy link
Collaborator

riveign commented Mar 30, 2022

Hi! @taggrx wanted to do a follow up on this points

  1. This was released in 0.5 feat: validate createActorArgs plug-inpage-provider#73
  2. This will be released in 0.6 (next version)
  3. This was released in 0.5 Add root key fetching if host is not default plug-inpage-provider#68
  4. This was released in the previous 0.4.7

Will keep the issue open till we release 0.6.

Thank you very much for all the feedback :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants