Multi canister call

Good morning!

Please someone can help with this tricky issue.
I two canisters, one is Server and the other is Client, they are deployed as two different projects.
I do a call to the server from the client by agentCreate , example below:
import { createActor } from ‘…/…/…/declarations/Server/index’;
class clientService {
constructor(identity) {
const canisterId = process.env.CANISTER_ID_SERVER;
this.actor = createActor(canisterId, { agentOptions: { identity } });
}
async clientFunc(principal) {
const resp = await this.actor.serverFunc(principal);
console.log(resp);
return resp;
}
}
When I run locally everything is working without issues
but when I deploy on chain and run, I get errors like below:

POST …-cai/call 400 (Bad Request)

and
index.js:2 Uncaught (in promise) pt: Server returned an error:
Code: 400 ()
Body: subnet_not_found

Hi @jaxopaxo,

It seems like you’re encountering challenges with managing connectivity and agent management.

To streamline your deployment process and enhance agent management, I recommend considering @ic-reactor/core. This library offers comprehensive solutions for managing agents, identities, and multiple actors.

Here are some examples of how you can manage agents and actors using @ic-reactor/core:

// agent.ts
import { createAgentManager } from "@ic-reactor/core"

export const agentManager = createAgentManager() // Connects to IC network by default
// actor.ts
import { createActorManager } from "@ic-reactor/core"
import * as candidA from "./declarations/candidA"
import * as candidB from "./declarations/candidB"
import { agentManager } from "./agent"

type CandidA = typeof candidA.candidA
type CandidB = typeof candidB.candidB

const actorA = createActorManager<CandidA>({
  agentManager,
  canisterId: candidA.canisterId,
  idlFactory: candidA.idlFactory,
})

const actorB = createActorManager<CandidB>({
  agentManager,
  canisterId: candidB.canisterId,
  idlFactory: candidB.idlFactory,
})

Once you’ve set up your agent and actors, you can use them as follows:

const { dataPromise } = actorA.queryCall({
  functionName: "serverFunc",
  args: [ principal ]
})
console.log("Response from CanisterA method:", await dataPromise)

const { dataPromise: versionActorB } = actorB.queryCall({
  functionName: "version",
})
console.log("Response from CanisterB method:", await versionActorB)

Feel free to explore the features of @ic-reactor/core to address your current challenges. If you need further assistance or have any questions about integrating the library into your project, don’t hesitate to reach out.

Thanks alot for good help.
One question which makes me a bit confused, I send caller sometimes
public shared ({caller}) func myFunc(param1: Text, …)
How to pass the parameters
Can I do
const { caller, param1 } = actorB.queryCall({
functionName: “myFunc”,
})
and one more question is that I send the parameter to aconstructor constructor(identity) {…
I want to pass to this.actor = createActorManager<… how can I do that?

You can pass parameters(arguments) like this:

const { dataPromise, call } = actorA.queryCall({
  functionName: "myFunc",
  args: [ param1 ]
})

you cannot pass the caller, the caller(identity) will sign the message and send it to the canister and node from the signed message will find the caller and pass it to the function.

on ic-reactor It will handle using agentManager, you can change agent, identity or even login using agentManager instances:

agentManager.updateAgent({ identity: yourIdentity })

it will take care of updating actors and other staff behind the scenes.

Hi again!
And thank you for answering, really appreciated your help.
I solved the issue, by creating a local gate_way in the front-end and from the gateway, I make my out calls.
Bellow my solution, it is simplified
1- the endpoint in the client:
import { fe_gateway } from ‘…/…/…/…/declarations/fe_gateway/index’;

const resp = await fe_gateway.gw_function_1(param);

2- The gateway gw.mo file
let canisterToCall= actor (“<canister_id>”) : actor {
be_function_1(param): async Result<Model, Text>;
};
public func gw_function_1 (param: Text): async Result<Model, Text> {
return await canisterToCall.be_function_1(param);
};

Now I don’t know (really new to ICP) if this is the best way to go, but it solved my issue

Again Thanks alot for you giving time to help, and have a super great day