-
Notifications
You must be signed in to change notification settings - Fork 316
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
feat(BOUN-1236): add client code for canister #2426
base: or-salt-log-1
Are you sure you want to change the base?
Conversation
787befd
to
60a426b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job! Left some questions/suggestions.
|
||
#[derive(Clone)] | ||
pub struct Canister { | ||
agent: Agent, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do You intend to unit test register()
and other implementations? Having an Agent
field would make it a bit difficult, i guess. Consider using generics with traits to facilitate testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does make sense to do this but I would rather do it for CanisterMethods
and then we can unit test the Tracker part. This would be more valuable because the Tracker is basically a state machine with more involved logic than these simple Canister methods.
use anyhow::{anyhow, Context}; | ||
use async_trait::async_trait; | ||
use candid::{Decode, Encode, Principal}; | ||
use ic_canister_client::Agent; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't one use agent-rs
directly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what we discussed during standup - this Agent is a different implementation that allows you to specify a Sender
, which the regular Agent implementation does not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
drop a comment in code plz
} | ||
|
||
#[async_trait] | ||
pub trait Register: Sync + Send { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curios, why do You need Sync + Send
here. Is there going to be concurrency involved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required because Register
is an async trait.
|
||
let resp = self | ||
.agent | ||
.execute_update( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment above regarding Agent
and unit testing. IMO a trait would be useful here for unit testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would we be unit testing though? These are very thin functions that just make use of the underlying agent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would we be unit testing though?
You could test for the expected errors, cause ATM this is not possible, i suppose. It's just a suggestion, if this function remains thin, maybe it's an overkill.
#[automock]
#[async_trait]
pub trait ExecutesCalls: Sync + Send {
async fn execute_update(&self) -> Result<....>;
async fn execute_query(&self) -> Result<...>;
}
pub struct Canister<Agent> {
agent: Agent,
}
impl<Agent: ExecutesCalls> Register for Canister<Agent> {
async fn register(&self) -> Result<(), String> {
let response = self.agent.execute_update();
...
}
}
This PR adds the client code for the canister. It will later be used by ic-boundary to interact with the canister.