Agent-js call query as update

Is there a simple way to instruct agent-js to call a function exposed as query with an update call?

Note that I know how we mumbo jumbo this in ic-js to expose both options for the same function. My question is really about a simpler option, like a flag on the actor or something, which can be easily use by the community. Maybe such an option already exists?

Considering the current agent and actor design, such a flag would have to be added to the actor. Else you would have to change the current design and move the actor polling logic into the agent. Currently there’s no flag as far as I can see in the implementation.

The most straightforward approach to do this outside of actor or agent would be modifying the IDL that is passed when creating the actor. Basically removing the query annotation from the IDL.

An untested IDL approach as mentioned above would be something like this:

const upgradeToCall = (fn) => ({ IDL }) => fn({ 
  IDL: new Proxy(IDL, {
    get(target, prop) {
      if (prop === 'Func') {
        return (arg, res) => target.Func.call(target, arg, res, []);
      }
      return target[prop];
    }
  })
});

// Usage
export const ledger_canister = Actor.createActor(upgradeToCall(idlFactory), {
  canisterId: LEDGER_CANISTER_ID,
});

Having a flag when creating an actor would be nice to have though.

I’ve had an idea I’ve toyed around with for a while but haven’t sat down and implemented yet.

If you have a method like actor.greet(), you could add a method to the prototype of greet so you could instead call actor.greet.as_query() or actor.greet.as_update(), passing in the same argument you would pass to the normal function

We already have actor.greet.withOption(customOptions)(name).

I suppose you could make this chainable for example actor.greet.asUpdate().withOption(customOptions)(name).

Also something like a prop callMethod?: 'query' | 'update' could be added to CallConfig. So you can just set it for the whole actor or with withOptions on each method, avoiding the need for additional methods and chaining.

So, to answer my question, no, there is currently no such option.

Configuring an entire actor to use queries or updates regardless of what the canister methods actually support seems unintuitive to me. Should I let you attempt to call an update-only method as a query, knowing it will fail?

Woops, you’re right, upgrading a query to a call indeed would be the only logical thing here :joy:

But then I suppose it could still be something like a global/method boolean flag upgradeToCall.

but yeah, I could imagine having a flag to have an actor always use update calls