Help with PocketIC intercanister calls

I am using PocketIC (js implementation) to test my app but i am having an issue with inter canister calls. In my ‘league’ canister I import my ‘teams’ canister with import TeamsActor "canister:teams"; which I THINK is causing an issue when running my pocketic tests

I get an error: Error: No route to canister bw4dl-smaaa-aaaaa-qaacq-cai
When making a call to the league, which then calls the teams. I believe this is due to the WASM being built has the canister id stamped in it? Then when i go to use pocketic instead of using its ids

League cansiter id  lxzze-o7777-77777-aaaaa-cai
Teams cansiter id  lqy7q-dh777-77777-aaaaq-cai

its trying to use the one from my local replica subnet


  "teams": {
    "local": "bw4dl-smaaa-aaaaa-qaacq-cai"
  },

Im not sure how to get around this issue
Any help would be great

Here is a link to my tests

I have confirmed that this is the issue by manually updating the canister_ids.json to what pocketic gives me

The options i see are:

  • modify the WASM bytes on test runs
  • set the canister ids to what is in local (doesn’t seem possible after testing)
  • run a dfx build in a test run
  • remove the canister imports and have each actor take as params the other canister ids. This seems like a real pain, but possible

There is targetCanisterId for setupCanister but according doc it can only be used on Bitcoin, Fiduciary, II, SNS and NNS subnets.

Maybe another workaround is to use that option and use one of those subnets for your tests?

No luck

I went with no canister imports and instead making all the actors into actor classes then passing in the cansiter ids. Had to break it up and create all the canisters first, then do the install, but seems to be working. It actually solved a few other issues i was having with cyclical canister references, but it seems like you should be able to import the canisters and have it work

Problem is, im not sure how to handle my dfx builds/deploys without doing a custom script to get the proper canisterids based on the environment
Is there a way to do canister install args that are environment specific?

I cannot help here; I have no idea about Motoko and DFX.

I’m using PicJS but have not had to set a particular canister ID when deploying a test canister so far. @NathanosDev, is that a feature that can potentially be implemented?

I’m using PicJS but have not had to set a particular canister ID when deploying a test canister so far. @NathanosDev, is that a feature that can potentially be implemented?

Unfortunately, there’s is a feature mismatch between PocketIC and DFX. DFX will figure out the IDs of your canisters at build time and inject them somehow into the canister’s WASM, but PocketIC only tells you the canister ID at runtime.

There’s nothing that I can do about that in the JS library, it’s something that needs to be solved by the core PocketIC server.

I went with no canister imports and instead making all the actors into actor classes then passing in the cansiter ids. Had to break it up and create all the canisters first, then do the install, but seems to be working. It actually solved a few other issues i was having with cyclical canister references, but it seems like you should be able to import the canisters and have it work

So I’m a bit late now since you already figured this out, but for future reference there’s a Motoko multicanister example project in the pic-js repo that demonstrates the cleanest approach to solving this problem that I could find: pic-js/examples/multicanister at main · hadronous/pic-js · GitHub.

Problem is, im not sure how to handle my dfx builds/deploys without doing a custom script to get the proper canisterids based on the environment
Is there a way to do canister install args that are environment specific?

@Severin do you know if there’s a way to reference the canister IDs through the enviornment variables that are written to the .env file by DFX in the canister’s init args in dfx.json?

2 Likes

dfx currently has no way to interpret init_arg. Your two options are:

Use init_arg_file instead of init_arg in dfx.json. Then you can have a build script inject the right canister IDs to that file from a template

Or dynamically construct the arg for dfx canister install --argument '(...)'

2 Likes

There is targetCanisterId for setupCanister but according doc it can only be used on Bitcoin, Fiduciary, II, SNS and NNS subnets.

We’re working on making it work for all IC mainnet canister IDs. I’m confident that this feature will be available in the next PocketIC release in a week or two.

1 Like

Thanks for the responses
Sounds like I’m going to go for a custom build script vs dfx while having all the canister ids as canister parameters