I’m trying to send tokens from my canister’s default sub account to about 30,000 sub accounts.
In my rust based canister I’m create a vector of Futures and then using join_all from the futures crate.
The code looks very similar to this but I’ve stripped out some code for readability.
...
let mut transfer_futures = Vec::new();
for (sub_account, icp_amount) in neurons {
...
let icp_transfer_future = transfer_icp_to_sub_account(sub_account, icp_amount);
transfer_futures.push((sub_account, icp_transfer_future));
}
// Execute all transfer futures concurrently and collect results
let results = join_all(transfer_futures.into_iter().map(|(sub_account, future)| async move {
match future.await {
Ok(_) => Ok(sub_account),
Err(e) => {
debug!("!!error in transfer - sub_account ::: {} - error ::: {}", sub_account, e);
Err(())
}, // Handle error if needed
}
})).await;
The errors I get back look like this.
{"timestamp":"1710344202865","level":"ERROR","fields":{"message":"Error calling c2c","method_name":"icrc1_transfer","canister_id":"ete3q-rqaaa-aaaal-qdlva-cai","error_code":"SysTransient","error_message":"Couldn't send message"},"target":"canister_client","filename":"backend/libraries/canister_client/src/lib.rs","line_number":75}
The key part of the error here as I understand is the SysTransient
part.
After looking at some documentation I can see SysTransient is related to a frozen canister either due to cycle balances or resource usage. I checked the cycles and I have plenty in there.
So I have some questions.
How can i monitor the resource usage of my canister?
How can i better structure this to make sure my calls go through? Would it be better to perhaps batch the calls in chunks of lets say 100? because it seems 30,000 calls is too much
Thanks