From 341f6ebcb01db95e9c993d64d33ae58367130a26 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Thu, 20 Apr 2023 18:09:12 -0700 Subject: [PATCH 1/6] support custom candid path for export_service --- rust/candid_derive/src/func.rs | 4 ++-- rust/candid_derive/src/lib.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rust/candid_derive/src/func.rs b/rust/candid_derive/src/func.rs index 49e78c5e..0971158d 100644 --- a/rust/candid_derive/src/func.rs +++ b/rust/candid_derive/src/func.rs @@ -80,9 +80,9 @@ pub(crate) fn candid_method(attrs: AttributeArgs, fun: ItemFn) -> Result TokenStream { +pub(crate) fn export_service(path: Option) -> TokenStream { if let Some(meths) = METHODS.lock().unwrap().as_mut() { - let candid = candid_path(&None); + let candid = candid_path(&path); let init = if let Some(opt_args) = INIT.lock().unwrap().as_mut() { let res = opt_args.as_ref().map(|args| { let args = args diff --git a/rust/candid_derive/src/lib.rs b/rust/candid_derive/src/lib.rs index b38748fa..834f6cbc 100644 --- a/rust/candid_derive/src/lib.rs +++ b/rust/candid_derive/src/lib.rs @@ -23,8 +23,12 @@ pub fn candid_method(attr: TokenStream, item: TokenStream) -> TokenStream { } #[proc_macro] -pub fn export_service(_: TokenStream) -> TokenStream { - func::export_service().into() +pub fn export_service(input: TokenStream) -> TokenStream { + if input.is_empty() { + func::export_service(None).into() + } else { + func::export_service(Some(input.into())).into() + } } #[inline] From 31131fff48a9e6bc039874483582629d3d164078 Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Tue, 25 Apr 2023 12:34:45 -0700 Subject: [PATCH 2/6] Add config options for Rust binding --- rust/candid/src/bindings/rust.rs | 66 +++++++++++++++---- rust/candid/tests/assets/ok/actor.rs | 7 +- rust/candid/tests/assets/ok/class.rs | 7 +- rust/candid/tests/assets/ok/comment.rs | 2 +- rust/candid/tests/assets/ok/cyclic.rs | 7 +- rust/candid/tests/assets/ok/escape.rs | 7 +- rust/candid/tests/assets/ok/example.rs | 9 ++- rust/candid/tests/assets/ok/fieldnat.rs | 7 +- rust/candid/tests/assets/ok/keyword.rs | 7 +- rust/candid/tests/assets/ok/recursion.rs | 7 +- .../candid/tests/assets/ok/recursive_class.rs | 7 +- rust/candid/tests/assets/ok/service.rs | 7 +- rust/candid/tests/assets/ok/unicode.rs | 7 +- rust/candid/tests/parse_type.rs | 4 +- 14 files changed, 115 insertions(+), 36 deletions(-) diff --git a/rust/candid/src/bindings/rust.rs b/rust/candid/src/bindings/rust.rs index 901575d6..48abaf18 100644 --- a/rust/candid/src/bindings/rust.rs +++ b/rust/candid/src/bindings/rust.rs @@ -5,6 +5,27 @@ use pretty::RcDoc; use std::collections::BTreeSet; use std::rc::Rc; +#[derive(Clone)] +pub struct Config { + pub candid_crate: String, + /// Applies to all types for now + pub type_attributes: String, + /// Only generates SERVICE struct if canister_id is not provided + pub canister_id: Option, + /// Service name when canister id is provided + pub service_name: String, +} +impl Config { + pub fn new() -> Self { + Config { + candid_crate: "candid".to_string(), + type_attributes: "".to_string(), + canister_id: None, + service_name: "service".to_string(), + } + } +} + type RecPoints<'a> = BTreeSet<&'a str>; // The definition of tuple is language specific. pub(crate) fn is_tuple(fs: &[Field]) -> bool { @@ -80,7 +101,7 @@ fn pp_ty<'a>(ty: &'a Type, recs: &RecPoints) -> RcDoc<'a> { name } } - Principal => str("candid::Principal"), + Principal => str("Principal"), Opt(ref t) => str("Option").append(enclose("<", pp_ty(t, recs), ">")), Vec(ref t) => str("Vec").append(enclose("<", pp_ty(t, recs), ">")), Record(ref fs) => pp_record_fields(fs, recs), @@ -128,8 +149,17 @@ fn pp_variant_fields<'a>(fs: &'a [Field], recs: &RecPoints) -> RcDoc<'a> { enclose_space("{", fields, "}") } -fn pp_defs<'a>(env: &'a TypeEnv, def_list: &'a [&'a str], recs: &'a RecPoints) -> RcDoc<'a> { - let derive = "#[derive(CandidType, Deserialize)]"; +fn pp_defs<'a>( + config: &'a Config, + env: &'a TypeEnv, + def_list: &'a [&'a str], + recs: &'a RecPoints, +) -> RcDoc<'a> { + let derive = if config.type_attributes.is_empty() { + "#[derive(CandidType, Deserialize)]" + } else { + &config.type_attributes + }; lines(def_list.iter().map(|id| { let ty = env.find_type(id).unwrap(); let name = ident(id).append(" "); @@ -256,7 +286,7 @@ fn pp_function<'a>(id: &'a str, func: &'a Function) -> RcDoc<'a> { sig.append(enclose_space("{", body, "}")) } -fn pp_actor<'a>(env: &'a TypeEnv, actor: &'a Type) -> RcDoc<'a> { +fn pp_actor<'a>(config: &'a Config, env: &'a TypeEnv, actor: &'a Type) -> RcDoc<'a> { // TODO trace to service before we figure out what canister means in Rust let serv = env.as_service(actor).unwrap(); let body = RcDoc::intersperse( @@ -266,18 +296,32 @@ fn pp_actor<'a>(env: &'a TypeEnv, actor: &'a Type) -> RcDoc<'a> { }), RcDoc::hardline(), ); - RcDoc::text("pub struct SERVICE(pub candid::Principal);") + let res = RcDoc::text("pub struct SERVICE(pub Principal);") .append(RcDoc::hardline()) .append("impl SERVICE") .append(enclose_space("{", body, "}")) + .append(RcDoc::hardline()); + if let Some(cid) = config.canister_id { + res.append(format!( + r#"pub fn {}() -> SERVICE {{ + SERVICE(Principal::from_text("{}").unwrap()) +}}"#, + config.service_name, cid + )) + } else { + res + } } -pub fn compile(env: &TypeEnv, actor: &Option) -> String { - let header = r#"// This is an experimental feature to generate Rust binding from Candid. +pub fn compile(config: &Config, env: &TypeEnv, actor: &Option) -> String { + let header = format!( + r#"// This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use {}::{{self, CandidType, Deserialize, Principal}}; use ic_cdk::api::call::CallResult; -"#; +"#, + config.candid_crate + ); let (env, actor) = nominalize_all(env, actor); let def_list: Vec<_> = if let Some(actor) = &actor { chase_actor(&env, actor).unwrap() @@ -285,11 +329,11 @@ use ic_cdk::api::call::CallResult; env.0.iter().map(|pair| pair.0.as_ref()).collect() }; let recs = infer_rec(&env, &def_list).unwrap(); - let defs = pp_defs(&env, &def_list, &recs); + let defs = pp_defs(config, &env, &def_list, &recs); let doc = match &actor { None => defs, Some(actor) => { - let actor = pp_actor(&env, actor); + let actor = pp_actor(config, &env, actor); defs.append(actor) } }; diff --git a/rust/candid/tests/assets/ok/actor.rs b/rust/candid/tests/assets/ok/actor.rs index c11b1270..ff50732a 100644 --- a/rust/candid/tests/assets/ok/actor.rs +++ b/rust/candid/tests/assets/ok/actor.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; candid::define_function!(pub f : (i8) -> (i8)); @@ -9,7 +9,7 @@ pub type g = f; #[derive(CandidType, Deserialize)] pub struct o(Option>); -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn f(&self, arg0: candid::Nat) -> CallResult<(h,)> { ic_cdk::call(self.0, "f", (arg0,)).await @@ -24,3 +24,6 @@ impl SERVICE{ ic_cdk::call(self.0, "o", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/class.rs b/rust/candid/tests/assets/ok/class.rs index 40146195..9e6e828f 100644 --- a/rust/candid/tests/assets/ok/class.rs +++ b/rust/candid/tests/assets/ok/class.rs @@ -1,12 +1,12 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; #[derive(CandidType, Deserialize)] pub struct List(Option<(candid::Int,Box,)>); -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn get(&self) -> CallResult<(List,)> { ic_cdk::call(self.0, "get", ()).await @@ -15,3 +15,6 @@ impl SERVICE{ ic_cdk::call(self.0, "set", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/comment.rs b/rust/candid/tests/assets/ok/comment.rs index 30987d38..bb885c00 100644 --- a/rust/candid/tests/assets/ok/comment.rs +++ b/rust/candid/tests/assets/ok/comment.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; pub type id = u8; diff --git a/rust/candid/tests/assets/ok/cyclic.rs b/rust/candid/tests/assets/ok/cyclic.rs index 1c2a0442..6fa1cc54 100644 --- a/rust/candid/tests/assets/ok/cyclic.rs +++ b/rust/candid/tests/assets/ok/cyclic.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; pub type C = Box; @@ -11,7 +11,7 @@ pub struct A(Option); pub type Z = Box; pub type Y = Z; pub type X = Y; -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn f( &self, @@ -25,3 +25,6 @@ impl SERVICE{ ic_cdk::call(self.0, "f", (arg0,arg1,arg2,arg3,arg4,arg5,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/escape.rs b/rust/candid/tests/assets/ok/escape.rs index 66e64b61..2cd6e30d 100644 --- a/rust/candid/tests/assets/ok/escape.rs +++ b/rust/candid/tests/assets/ok/escape.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; #[derive(CandidType, Deserialize)] @@ -15,9 +15,12 @@ pub struct t { _1020746185_: candid::Nat, } -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn _2635468193_(&self, arg0: t) -> CallResult<()> { ic_cdk::call(self.0, "\n\'\"\'\'\"\"\r\t", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/example.rs b/rust/candid/tests/assets/ok/example.rs index b5f368b0..b6f4eed2 100644 --- a/rust/candid/tests/assets/ok/example.rs +++ b/rust/candid/tests/assets/ok/example.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; #[derive(CandidType, Deserialize)] @@ -9,7 +9,7 @@ pub struct node { head: candid::Nat, tail: Box } #[derive(CandidType, Deserialize)] pub struct list(Option); -pub type my_type = candid::Principal; +pub type my_type = Principal; #[derive(CandidType, Deserialize)] pub struct List_inner { head: candid::Int, tail: Box } @@ -57,7 +57,7 @@ pub struct b (candid::Int,candid::Nat,); #[derive(CandidType, Deserialize)] pub enum a { a, b(b) } -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn f( &self, @@ -89,3 +89,6 @@ impl SERVICE{ (Option,Option,) > { ic_cdk::call(self.0, "x", (arg0,arg1,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/fieldnat.rs b/rust/candid/tests/assets/ok/fieldnat.rs index 58422e4c..1b2a457f 100644 --- a/rust/candid/tests/assets/ok/fieldnat.rs +++ b/rust/candid/tests/assets/ok/fieldnat.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; #[derive(CandidType, Deserialize)] @@ -30,7 +30,7 @@ pub struct foo_arg0 { _2_: candid::Int } #[derive(CandidType, Deserialize)] pub struct foo_ret0 { _2_: candid::Int, _2: candid::Int } -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn bab(&self, arg0: candid::Int, arg1: candid::Nat) -> CallResult< () @@ -54,3 +54,6 @@ impl SERVICE{ ic_cdk::call(self.0, "foo", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/keyword.rs b/rust/candid/tests/assets/ok/keyword.rs index 2c8d3d98..a33dc271 100644 --- a/rust/candid/tests/assets/ok/keyword.rs +++ b/rust/candid/tests/assets/ok/keyword.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; #[derive(CandidType, Deserialize)] @@ -46,7 +46,7 @@ candid::define_function!(pub t : (r#return) -> ()); #[derive(CandidType, Deserialize)] pub enum variant_arg0 { A, B, C, D(f64) } -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn Oneway(&self) -> CallResult<()> { ic_cdk::call(self.0, "Oneway", ()).await @@ -82,3 +82,6 @@ impl SERVICE{ ic_cdk::call(self.0, "variant", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/recursion.rs b/rust/candid/tests/assets/ok/recursion.rs index d0aa6f0f..f140db9c 100644 --- a/rust/candid/tests/assets/ok/recursion.rs +++ b/rust/candid/tests/assets/ok/recursion.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; candid::define_function!(pub t : (s) -> ()); @@ -31,7 +31,7 @@ candid::define_service!(pub s : { "f" : t::ty(); "g" : candid::func!((list) -> (B, tree, stream)); }); -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn f(&self, arg0: s) -> CallResult<()> { ic_cdk::call(self.0, "f", (arg0,)).await @@ -40,3 +40,6 @@ impl SERVICE{ ic_cdk::call(self.0, "g", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/recursive_class.rs b/rust/candid/tests/assets/ok/recursive_class.rs index ca11a6b9..de08e12d 100644 --- a/rust/candid/tests/assets/ok/recursive_class.rs +++ b/rust/candid/tests/assets/ok/recursive_class.rs @@ -1,12 +1,15 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; candid::define_service!(pub s : { "next" : candid::func!(() -> (s)) }); -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn next(&self) -> CallResult<(s,)> { ic_cdk::call(self.0, "next", ()).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/service.rs b/rust/candid/tests/assets/ok/service.rs index de490904..98011fd3 100644 --- a/rust/candid/tests/assets/ok/service.rs +++ b/rust/candid/tests/assets/ok/service.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; candid::define_function!(pub Func : () -> (Service)); @@ -9,7 +9,7 @@ pub type Service2 = Box; #[derive(CandidType, Deserialize)] pub enum asVariant_ret0 { a(Service2), b{ f: Option } } -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn asArray(&self) -> CallResult<(Vec,Vec,)> { ic_cdk::call(self.0, "asArray", ()).await @@ -24,3 +24,6 @@ impl SERVICE{ ic_cdk::call(self.0, "asVariant", ()).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/assets/ok/unicode.rs b/rust/candid/tests/assets/ok/unicode.rs index d603a2df..eeef9f8f 100644 --- a/rust/candid/tests/assets/ok/unicode.rs +++ b/rust/candid/tests/assets/ok/unicode.rs @@ -1,6 +1,6 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. -use candid::{self, CandidType, Deserialize}; +use candid::{self, CandidType, Deserialize, Principal}; use ic_cdk::api::call::CallResult; #[derive(CandidType, Deserialize)] @@ -27,7 +27,7 @@ pub enum B { _3099250646_, } -pub struct SERVICE(pub candid::Principal); +pub struct SERVICE(pub Principal); impl SERVICE{ pub async fn _0_(&self, arg0: candid::Nat) -> CallResult<(candid::Nat,)> { ic_cdk::call(self.0, "", (arg0,)).await @@ -42,3 +42,6 @@ impl SERVICE{ (candid::Nat,) > { ic_cdk::call(self.0, "👀", (arg0,)).await } } +pub fn service() -> SERVICE { + SERVICE(Principal::from_text("aaaaa-aa").unwrap()) +} diff --git a/rust/candid/tests/parse_type.rs b/rust/candid/tests/parse_type.rs index baa0383d..7b863e97 100644 --- a/rust/candid/tests/parse_type.rs +++ b/rust/candid/tests/parse_type.rs @@ -61,8 +61,10 @@ fn compiler_test(resource: &str) { } } { + let mut config = rust::Config::new(); + config.canister_id = Some(candid::Principal::from_text("aaaaa-aa").unwrap()); let mut output = mint.new_goldenfile(filename.with_extension("rs")).unwrap(); - let content = rust::compile(&env, &actor); + let content = rust::compile(&config, &env, &actor); writeln!(output, "{content}").unwrap(); } { From 6ad0825e112818e15f9222504e20c7413caa408e Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Tue, 25 Apr 2023 13:45:12 -0700 Subject: [PATCH 3/6] fix blob --- rust/candid/src/bindings/motoko.rs | 3 ++- rust/candid/src/bindings/rust.rs | 1 + rust/candid/tests/assets/ok/example.mo | 2 +- rust/candid/tests/assets/ok/example.rs | 2 +- rust/candid/tests/assets/ok/keyword.mo | 4 ++-- rust/candid/tests/assets/ok/keyword.rs | 15 +++++++++------ tools/didc/src/main.rs | 5 ++++- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/rust/candid/src/bindings/motoko.rs b/rust/candid/src/bindings/motoko.rs index 978bf1e8..b87bdecd 100644 --- a/rust/candid/src/bindings/motoko.rs +++ b/rust/candid/src/bindings/motoko.rs @@ -111,7 +111,8 @@ fn pp_ty(ty: &Type) -> RcDoc { Var(ref s) => escape(s, false), Principal => str("Principal"), Opt(ref t) => str("?").append(pp_ty(t)), - Vec(ref t) => enclose("[", pp_ty(t), "]"), // TODO blob + Vec(ref t) if matches!(t.as_ref(), Nat8) => str("Blob"), + Vec(ref t) => enclose("[", pp_ty(t), "]"), Record(ref fs) => { if is_tuple(ty) { let tuple = concat(fs.iter().map(|f| pp_ty(&f.ty)), ","); diff --git a/rust/candid/src/bindings/rust.rs b/rust/candid/src/bindings/rust.rs index 48abaf18..d3ec937e 100644 --- a/rust/candid/src/bindings/rust.rs +++ b/rust/candid/src/bindings/rust.rs @@ -103,6 +103,7 @@ fn pp_ty<'a>(ty: &'a Type, recs: &RecPoints) -> RcDoc<'a> { } Principal => str("Principal"), Opt(ref t) => str("Option").append(enclose("<", pp_ty(t, recs), ">")), + Vec(ref t) if matches!(t.as_ref(), Nat8) => str("serde_bytes::ByteBuf"), Vec(ref t) => str("Vec").append(enclose("<", pp_ty(t, recs), ">")), Record(ref fs) => pp_record_fields(fs, recs), Variant(_) => unreachable!(), // not possible after rewriting diff --git a/rust/candid/tests/assets/ok/example.mo b/rust/candid/tests/assets/ok/example.mo index 5bf37e09..ef78f247 100644 --- a/rust/candid/tests/assets/ok/example.mo +++ b/rust/candid/tests/assets/ok/example.mo @@ -34,7 +34,7 @@ module { #leaf : Int; }; public type Self = actor { - f : shared (list, [Nat8], ?Bool) -> (); + f : shared (list, Blob, ?Bool) -> (); g : shared query (my_type, List, ?List, nested) -> async (Int, broker); h : shared ([?Text], { #A : Nat; #B : ?Text }, ?List) -> async { _42_ : {}; diff --git a/rust/candid/tests/assets/ok/example.rs b/rust/candid/tests/assets/ok/example.rs index b6f4eed2..edc14358 100644 --- a/rust/candid/tests/assets/ok/example.rs +++ b/rust/candid/tests/assets/ok/example.rs @@ -62,7 +62,7 @@ impl SERVICE{ pub async fn f( &self, arg0: list, - arg1: Vec, + arg1: serde_bytes::ByteBuf, arg2: Option, ) -> CallResult<()> { ic_cdk::call(self.0, "f", (arg0,arg1,arg2,)).await } pub async fn g( diff --git a/rust/candid/tests/assets/ok/keyword.mo b/rust/candid/tests/assets/ok/keyword.mo index 15cdeac1..2802968e 100644 --- a/rust/candid/tests/assets/ok/keyword.mo +++ b/rust/candid/tests/assets/ok/keyword.mo @@ -19,10 +19,10 @@ module { fieldnat : shared { _2_ : Int; _50_ : Nat } -> async { _0_ : Int }; oneway : shared Nat8 -> (); oneway__ : shared Nat8 -> (); - query_ : shared query [Nat8] -> async [Nat8]; + query_ : shared query Blob -> async Blob; return_ : shared o -> async o; service : t; - tuple : shared ((Int, [Nat8], Text)) -> async ((Int, Nat8)); + tuple : shared ((Int, Blob, Text)) -> async ((Int, Nat8)); variant : shared { #A; #B; #C; #D : Float } -> async (); } } diff --git a/rust/candid/tests/assets/ok/keyword.rs b/rust/candid/tests/assets/ok/keyword.rs index a33dc271..3a1f3184 100644 --- a/rust/candid/tests/assets/ok/keyword.rs +++ b/rust/candid/tests/assets/ok/keyword.rs @@ -66,18 +66,21 @@ impl SERVICE{ pub async fn oneway_(&self, arg0: u8) -> CallResult<()> { ic_cdk::call(self.0, "oneway_", (arg0,)).await } - pub async fn query(&self, arg0: Vec) -> CallResult<(Vec,)> { - ic_cdk::call(self.0, "query", (arg0,)).await - } + pub async fn query(&self, arg0: serde_bytes::ByteBuf) -> CallResult< + (serde_bytes::ByteBuf,) + > { ic_cdk::call(self.0, "query", (arg0,)).await } pub async fn r#return(&self, arg0: o) -> CallResult<(o,)> { ic_cdk::call(self.0, "return", (arg0,)).await } pub async fn service(&self, arg0: r#return) -> CallResult<()> { ic_cdk::call(self.0, "service", (arg0,)).await } - pub async fn tuple(&self, arg0: (candid::Int,Vec,String,)) -> CallResult< - ((candid::Int,u8,),) - > { ic_cdk::call(self.0, "tuple", (arg0,)).await } + pub async fn tuple( + &self, + arg0: (candid::Int,serde_bytes::ByteBuf,String,), + ) -> CallResult<((candid::Int,u8,),)> { + ic_cdk::call(self.0, "tuple", (arg0,)).await + } pub async fn variant(&self, arg0: variant_arg0) -> CallResult<()> { ic_cdk::call(self.0, "variant", (arg0,)).await } diff --git a/tools/didc/src/main.rs b/tools/didc/src/main.rs index bb39d7e3..e88cad5f 100644 --- a/tools/didc/src/main.rs +++ b/tools/didc/src/main.rs @@ -180,7 +180,10 @@ fn main() -> Result<()> { "ts" => candid::bindings::typescript::compile(&env, &actor), "did" => candid::bindings::candid::compile(&env, &actor), "mo" => candid::bindings::motoko::compile(&env, &actor), - "rs" => candid::bindings::rust::compile(&env, &actor), + "rs" => { + let config = candid::bindings::rust::Config::new(); + candid::bindings::rust::compile(&config, &env, &actor) + } _ => unreachable!(), }; println!("{content}"); From 388eafa314c6fa32a484e518c85e6b33cc4b66bf Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Wed, 26 Apr 2023 17:30:52 -0700 Subject: [PATCH 4/6] add codegen for agent --- rust/candid/src/bindings/rust.rs | 110 +++++- rust/candid/tests/assets/management.did | 151 +++++++ rust/candid/tests/assets/ok/actor.rs | 16 +- rust/candid/tests/assets/ok/class.rs | 12 +- rust/candid/tests/assets/ok/comment.rs | 2 +- rust/candid/tests/assets/ok/cyclic.rs | 10 +- rust/candid/tests/assets/ok/escape.rs | 10 +- rust/candid/tests/assets/ok/example.rs | 26 +- rust/candid/tests/assets/ok/fieldnat.rs | 26 +- rust/candid/tests/assets/ok/keyword.rs | 30 +- rust/candid/tests/assets/ok/management.d.ts | 172 ++++++++ rust/candid/tests/assets/ok/management.did | 127 ++++++ rust/candid/tests/assets/ok/management.js | 233 +++++++++++ rust/candid/tests/assets/ok/management.mo | 125 ++++++ rust/candid/tests/assets/ok/management.rs | 369 ++++++++++++++++++ rust/candid/tests/assets/ok/recursion.rs | 12 +- .../candid/tests/assets/ok/recursive_class.rs | 10 +- rust/candid/tests/assets/ok/service.rs | 20 +- rust/candid/tests/assets/ok/unicode.rs | 16 +- rust/candid/tests/parse_type.rs | 3 + tools/didc/src/main.rs | 7 +- 21 files changed, 1358 insertions(+), 129 deletions(-) create mode 100644 rust/candid/tests/assets/management.did create mode 100644 rust/candid/tests/assets/ok/management.d.ts create mode 100644 rust/candid/tests/assets/ok/management.did create mode 100644 rust/candid/tests/assets/ok/management.js create mode 100644 rust/candid/tests/assets/ok/management.mo create mode 100644 rust/candid/tests/assets/ok/management.rs diff --git a/rust/candid/src/bindings/rust.rs b/rust/candid/src/bindings/rust.rs index d3ec937e..8457e54c 100644 --- a/rust/candid/src/bindings/rust.rs +++ b/rust/candid/src/bindings/rust.rs @@ -5,6 +5,13 @@ use pretty::RcDoc; use std::collections::BTreeSet; use std::rc::Rc; +#[derive(Clone)] +pub enum Target { + CanisterCall, + Agent, + CanisterStub, +} + #[derive(Clone)] pub struct Config { pub candid_crate: String, @@ -14,6 +21,7 @@ pub struct Config { pub canister_id: Option, /// Service name when canister id is provided pub service_name: String, + pub target: Target, } impl Config { pub fn new() -> Self { @@ -22,9 +30,15 @@ impl Config { type_attributes: "".to_string(), canister_id: None, service_name: "service".to_string(), + target: Target::CanisterCall, } } } +impl Default for Config { + fn default() -> Self { + Self::new() + } +} type RecPoints<'a> = BTreeSet<&'a str>; // The definition of tuple is language specific. @@ -103,6 +117,7 @@ fn pp_ty<'a>(ty: &'a Type, recs: &RecPoints) -> RcDoc<'a> { } Principal => str("Principal"), Opt(ref t) => str("Option").append(enclose("<", pp_ty(t, recs), ">")), + // It's a bit tricky to use `deserialize_with = "serde_bytes"`. It's not working for `type t = blob` Vec(ref t) if matches!(t.as_ref(), Nat8) => str("serde_bytes::ByteBuf"), Vec(ref t) => str("Vec").append(enclose("<", pp_ty(t, recs), ">")), Record(ref fs) => pp_record_fields(fs, recs), @@ -255,11 +270,16 @@ fn pp_ty_service(serv: &[(String, Type)]) -> RcDoc { enclose_space("{", doc, "}") } -fn pp_function<'a>(id: &'a str, func: &'a Function) -> RcDoc<'a> { +fn pp_function<'a>(config: &Config, id: &'a str, func: &'a Function) -> RcDoc<'a> { let name = ident(id); let empty = BTreeSet::new(); + let arg_prefix = str(match config.target { + Target::CanisterCall => "&self", + Target::Agent => "&self, agent: &ic_agent::Agent", + Target::CanisterStub => unimplemented!(), + }); let args = concat( - std::iter::once(str("&self")).chain( + std::iter::once(arg_prefix).chain( func.args .iter() .enumerate() @@ -267,23 +287,62 @@ fn pp_function<'a>(id: &'a str, func: &'a Function) -> RcDoc<'a> { ), ",", ); - let rets = enclose( - "(", - RcDoc::concat(func.rets.iter().map(|ty| pp_ty(ty, &empty).append(","))), - ")", - ); + let rets = match config.target { + Target::CanisterCall => enclose( + "(", + RcDoc::concat(func.rets.iter().map(|ty| pp_ty(ty, &empty).append(","))), + ")", + ), + Target::Agent => match func.rets.len() { + 0 => str("()"), + 1 => pp_ty(&func.rets[0], &empty), + _ => enclose( + "(", + RcDoc::intersperse( + func.rets.iter().map(|ty| pp_ty(ty, &empty)), + RcDoc::text(", "), + ), + ")", + ), + }, + Target::CanisterStub => unimplemented!(), + }; let sig = kwd("pub async fn") .append(name) .append(enclose("(", args, ")")) .append(kwd(" ->")) - .append(enclose("CallResult<", rets, "> ")); - let args = RcDoc::concat((0..func.args.len()).map(|i| RcDoc::text(format!("arg{i},")))); + .append(enclose("Result<", rets, "> ")); let method = id.escape_debug().to_string(); - let body = str("ic_cdk::call(self.0, \"") - .append(method) - .append("\", ") - .append(enclose("(", args, ")")) - .append(").await"); + let body = match config.target { + Target::CanisterCall => { + let args = RcDoc::concat((0..func.args.len()).map(|i| RcDoc::text(format!("arg{i},")))); + str("ic_cdk::call(self.0, \"") + .append(method) + .append("\", ") + .append(enclose("(", args, ")")) + .append(").await") + } + Target::Agent => { + let is_query = func.is_query(); + let builder_method = if is_query { "query" } else { "update" }; + let call = if is_query { "call" } else { "call_and_wait" }; + let args = RcDoc::intersperse( + (0..func.args.len()).map(|i| RcDoc::text(format!("arg{i}"))), + RcDoc::text(", "), + ); + let blob = str("candid::Encode!").append(enclose("(", args, ")?;")); + let rets = RcDoc::concat( + func.rets + .iter() + .map(|ty| str(", ").append(pp_ty(ty, &empty))), + ); + str("let args = ").append(blob).append(RcDoc::hardline()) + .append(format!("let bytes = agent.{builder_method}(self.0, \"{method}\").with_arg(args).{call}().await?;")) + .append(RcDoc::hardline()) + .append("Ok(candid::Decode!(&bytes").append(rets).append(")?)") + } + Target::CanisterStub => unimplemented!(), + }; sig.append(enclose_space("{", body, "}")) } @@ -293,21 +352,25 @@ fn pp_actor<'a>(config: &'a Config, env: &'a TypeEnv, actor: &'a Type) -> RcDoc< let body = RcDoc::intersperse( serv.iter().map(|(id, func)| { let func = env.as_func(func).unwrap(); - pp_function(id, func) + pp_function(config, id, func) }), RcDoc::hardline(), ); let res = RcDoc::text("pub struct SERVICE(pub Principal);") .append(RcDoc::hardline()) - .append("impl SERVICE") + .append("impl SERVICE ") .append(enclose_space("{", body, "}")) .append(RcDoc::hardline()); if let Some(cid) = config.canister_id { + let slice = cid + .as_slice() + .iter() + .map(|b| b.to_string()) + .collect::>() + .join(", "); res.append(format!( - r#"pub fn {}() -> SERVICE {{ - SERVICE(Principal::from_text("{}").unwrap()) -}}"#, - config.service_name, cid + r#"pub const {}: SERVICE = SERVICE(Principal::from_slice(&[{}])); // {}"#, + config.service_name, slice, cid )) } else { res @@ -319,10 +382,15 @@ pub fn compile(config: &Config, env: &TypeEnv, actor: &Option) -> String { r#"// This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use {}::{{self, CandidType, Deserialize, Principal}}; -use ic_cdk::api::call::CallResult; "#, config.candid_crate ); + let header = header + + match &config.target { + Target::CanisterCall => "use ic_cdk::api::call::CallResult as Result;\n", + Target::Agent => "type Result = std::result::Result;", + Target::CanisterStub => "", + }; let (env, actor) = nominalize_all(env, actor); let def_list: Vec<_> = if let Some(actor) = &actor { chase_actor(&env, actor).unwrap() diff --git a/rust/candid/tests/assets/management.did b/rust/candid/tests/assets/management.did new file mode 100644 index 00000000..04f42522 --- /dev/null +++ b/rust/candid/tests/assets/management.did @@ -0,0 +1,151 @@ +type canister_id = principal; +type user_id = principal; +type wasm_module = blob; + +type canister_settings = record { + controllers : opt vec principal; + compute_allocation : opt nat; + memory_allocation : opt nat; + freezing_threshold : opt nat; +}; + +type definite_canister_settings = record { + controllers : vec principal; + compute_allocation : nat; + memory_allocation : nat; + freezing_threshold : nat; +}; + +type http_header = record { name: text; value: text }; + +type http_response = record { + status: nat; + headers: vec http_header; + body: blob; +}; + +type ecdsa_curve = variant { secp256k1; }; + +type satoshi = nat64; + +type bitcoin_network = variant { + mainnet; + testnet; +}; + +type bitcoin_address = text; + +type block_hash = blob; + +type outpoint = record { + txid : blob; + vout : nat32 +}; + +type utxo = record { + outpoint: outpoint; + value: satoshi; + height: nat32; +}; + +type get_utxos_request = record { + address : bitcoin_address; + network: bitcoin_network; + filter: opt variant { + min_confirmations: nat32; + page: blob; + }; +}; + +type get_current_fee_percentiles_request = record { + network: bitcoin_network; +}; + +type get_utxos_response = record { + utxos: vec utxo; + tip_block_hash: block_hash; + tip_height: nat32; + next_page: opt blob; +}; + +type get_balance_request = record { + address : bitcoin_address; + network: bitcoin_network; + min_confirmations: opt nat32; +}; + +type send_transaction_request = record { + transaction: blob; + network: bitcoin_network; +}; + +type millisatoshi_per_byte = nat64; + +service ic : { + create_canister : (record { + settings : opt canister_settings + }) -> (record {canister_id : canister_id}); + update_settings : (record { + canister_id : principal; + settings : canister_settings + }) -> (); + install_code : (record { + mode : variant {install; reinstall; upgrade}; + canister_id : canister_id; + wasm_module : wasm_module; + arg : blob; + }) -> (); + uninstall_code : (record {canister_id : canister_id}) -> (); + start_canister : (record {canister_id : canister_id}) -> (); + stop_canister : (record {canister_id : canister_id}) -> (); + canister_status : (record {canister_id : canister_id}) -> (record { + status : variant { running; stopping; stopped }; + settings: definite_canister_settings; + module_hash: opt blob; + memory_size: nat; + cycles: nat; + idle_cycles_burned_per_day: nat; + }); + delete_canister : (record {canister_id : canister_id}) -> (); + deposit_cycles : (record {canister_id : canister_id}) -> (); + raw_rand : () -> (blob); + http_request : (record { + url : text; + max_response_bytes: opt nat64; + method : variant { get; head; post }; + headers: vec http_header; + body : opt blob; + transform : opt record { + function : func (record {response : http_response; context : blob}) -> (http_response) query; + context : blob + }; + }) -> (http_response); + + // Threshold ECDSA signature + ecdsa_public_key : (record { + canister_id : opt canister_id; + derivation_path : vec blob; + key_id : record { curve: ecdsa_curve; name: text }; + }) -> (record { public_key : blob; chain_code : blob; }); + sign_with_ecdsa : (record { + message_hash : blob; + derivation_path : vec blob; + key_id : record { curve: ecdsa_curve; name: text }; + }) -> (record { signature : blob }); + + // bitcoin interface + bitcoin_get_balance: (get_balance_request) -> (satoshi); + bitcoin_get_utxos: (get_utxos_request) -> (get_utxos_response); + bitcoin_send_transaction: (send_transaction_request) -> (); + bitcoin_get_current_fee_percentiles: (get_current_fee_percentiles_request) -> (vec millisatoshi_per_byte); + + // provisional interfaces for the pre-ledger world + provisional_create_canister_with_cycles : (record { + amount: opt nat; + settings : opt canister_settings; + specified_id: opt canister_id; + }) -> (record {canister_id : canister_id}); + provisional_top_up_canister : + (record { canister_id: canister_id; amount: nat }) -> (); +} + diff --git a/rust/candid/tests/assets/ok/actor.rs b/rust/candid/tests/assets/ok/actor.rs index ff50732a..8bdb8b28 100644 --- a/rust/candid/tests/assets/ok/actor.rs +++ b/rust/candid/tests/assets/ok/actor.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; candid::define_function!(pub f : (i8) -> (i8)); candid::define_function!(pub h : (f) -> (f)); @@ -10,20 +10,18 @@ pub type g = f; pub struct o(Option>); pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn f(&self, arg0: candid::Nat) -> CallResult<(h,)> { +impl SERVICE { + pub async fn f(&self, arg0: candid::Nat) -> Result<(h,)> { ic_cdk::call(self.0, "f", (arg0,)).await } - pub async fn g(&self, arg0: i8) -> CallResult<(i8,)> { + pub async fn g(&self, arg0: i8) -> Result<(i8,)> { ic_cdk::call(self.0, "g", (arg0,)).await } - pub async fn h(&self, arg0: i8) -> CallResult<(i8,)> { + pub async fn h(&self, arg0: i8) -> Result<(i8,)> { ic_cdk::call(self.0, "h", (arg0,)).await } - pub async fn o(&self, arg0: o) -> CallResult<(o,)> { + pub async fn o(&self, arg0: o) -> Result<(o,)> { ic_cdk::call(self.0, "o", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/class.rs b/rust/candid/tests/assets/ok/class.rs index 9e6e828f..0a2b6bdb 100644 --- a/rust/candid/tests/assets/ok/class.rs +++ b/rust/candid/tests/assets/ok/class.rs @@ -1,20 +1,18 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct List(Option<(candid::Int,Box,)>); pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn get(&self) -> CallResult<(List,)> { +impl SERVICE { + pub async fn get(&self) -> Result<(List,)> { ic_cdk::call(self.0, "get", ()).await } - pub async fn set(&self, arg0: List) -> CallResult<(List,)> { + pub async fn set(&self, arg0: List) -> Result<(List,)> { ic_cdk::call(self.0, "set", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/comment.rs b/rust/candid/tests/assets/ok/comment.rs index bb885c00..d5cd1448 100644 --- a/rust/candid/tests/assets/ok/comment.rs +++ b/rust/candid/tests/assets/ok/comment.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; pub type id = u8; diff --git a/rust/candid/tests/assets/ok/cyclic.rs b/rust/candid/tests/assets/ok/cyclic.rs index 6fa1cc54..dbd62c0e 100644 --- a/rust/candid/tests/assets/ok/cyclic.rs +++ b/rust/candid/tests/assets/ok/cyclic.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; pub type C = Box; pub type B = Option; @@ -12,7 +12,7 @@ pub type Z = Box; pub type Y = Z; pub type X = Y; pub struct SERVICE(pub Principal); -impl SERVICE{ +impl SERVICE { pub async fn f( &self, arg0: A, @@ -21,10 +21,8 @@ impl SERVICE{ arg3: X, arg4: Y, arg5: Z, - ) -> CallResult<()> { + ) -> Result<()> { ic_cdk::call(self.0, "f", (arg0,arg1,arg2,arg3,arg4,arg5,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/escape.rs b/rust/candid/tests/assets/ok/escape.rs index 2cd6e30d..aa4ca474 100644 --- a/rust/candid/tests/assets/ok/escape.rs +++ b/rust/candid/tests/assets/ok/escape.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct t { @@ -16,11 +16,9 @@ pub struct t { } pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn _2635468193_(&self, arg0: t) -> CallResult<()> { +impl SERVICE { + pub async fn _2635468193_(&self, arg0: t) -> Result<()> { ic_cdk::call(self.0, "\n\'\"\'\'\"\"\r\t", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/example.rs b/rust/candid/tests/assets/ok/example.rs index edc14358..7b65ee05 100644 --- a/rust/candid/tests/assets/ok/example.rs +++ b/rust/candid/tests/assets/ok/example.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct node { head: candid::Nat, tail: Box } @@ -58,20 +58,20 @@ pub struct b (candid::Int,candid::Nat,); pub enum a { a, b(b) } pub struct SERVICE(pub Principal); -impl SERVICE{ +impl SERVICE { pub async fn f( &self, arg0: list, arg1: serde_bytes::ByteBuf, arg2: Option, - ) -> CallResult<()> { ic_cdk::call(self.0, "f", (arg0,arg1,arg2,)).await } + ) -> Result<()> { ic_cdk::call(self.0, "f", (arg0,arg1,arg2,)).await } pub async fn g( &self, arg0: my_type, arg1: List, arg2: Option, arg3: nested, - ) -> CallResult<(candid::Int,broker,)> { + ) -> Result<(candid::Int,broker,)> { ic_cdk::call(self.0, "g", (arg0,arg1,arg2,arg3,)).await } pub async fn h( @@ -79,16 +79,12 @@ impl SERVICE{ arg0: Vec>, arg1: h_arg1, arg2: Option, - ) -> CallResult<(h_ret0,)> { - ic_cdk::call(self.0, "h", (arg0,arg1,arg2,)).await + ) -> Result<(h_ret0,)> { ic_cdk::call(self.0, "h", (arg0,arg1,arg2,)).await } + pub async fn i(&self, arg0: List, arg1: f_arg1) -> Result<(Option,)> { + ic_cdk::call(self.0, "i", (arg0,arg1,)).await + } + pub async fn x(&self, arg0: a, arg1: b) -> Result<(Option,Option,)> { + ic_cdk::call(self.0, "x", (arg0,arg1,)).await } - pub async fn i(&self, arg0: List, arg1: f_arg1) -> CallResult< - (Option,) - > { ic_cdk::call(self.0, "i", (arg0,arg1,)).await } - pub async fn x(&self, arg0: a, arg1: b) -> CallResult< - (Option,Option,) - > { ic_cdk::call(self.0, "x", (arg0,arg1,)).await } -} -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) } +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/fieldnat.rs b/rust/candid/tests/assets/ok/fieldnat.rs index 1b2a457f..b3e973aa 100644 --- a/rust/candid/tests/assets/ok/fieldnat.rs +++ b/rust/candid/tests/assets/ok/fieldnat.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct bar_arg0 { #[serde(rename="2")] _50_: candid::Int } @@ -31,29 +31,27 @@ pub struct foo_arg0 { _2_: candid::Int } pub struct foo_ret0 { _2_: candid::Int, _2: candid::Int } pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn bab(&self, arg0: candid::Int, arg1: candid::Nat) -> CallResult< - () - > { ic_cdk::call(self.0, "bab", (arg0,arg1,)).await } - pub async fn bar(&self, arg0: bar_arg0) -> CallResult<(bar_ret0,)> { +impl SERVICE { + pub async fn bab(&self, arg0: candid::Int, arg1: candid::Nat) -> Result<()> { + ic_cdk::call(self.0, "bab", (arg0,arg1,)).await + } + pub async fn bar(&self, arg0: bar_arg0) -> Result<(bar_ret0,)> { ic_cdk::call(self.0, "bar", (arg0,)).await } - pub async fn bas(&self, arg0: (candid::Int,candid::Int,)) -> CallResult< + pub async fn bas(&self, arg0: (candid::Int,candid::Int,)) -> Result< ((String,candid::Nat,),) > { ic_cdk::call(self.0, "bas", (arg0,)).await } - pub async fn baz(&self, arg0: baz_arg0) -> CallResult<(baz_ret0,)> { + pub async fn baz(&self, arg0: baz_arg0) -> Result<(baz_ret0,)> { ic_cdk::call(self.0, "baz", (arg0,)).await } - pub async fn bba(&self, arg0: tuple) -> CallResult<(non_tuple,)> { + pub async fn bba(&self, arg0: tuple) -> Result<(non_tuple,)> { ic_cdk::call(self.0, "bba", (arg0,)).await } - pub async fn bib(&self, arg0: (candid::Int,)) -> CallResult<(bib_ret0,)> { + pub async fn bib(&self, arg0: (candid::Int,)) -> Result<(bib_ret0,)> { ic_cdk::call(self.0, "bib", (arg0,)).await } - pub async fn foo(&self, arg0: foo_arg0) -> CallResult<(foo_ret0,)> { + pub async fn foo(&self, arg0: foo_arg0) -> Result<(foo_ret0,)> { ic_cdk::call(self.0, "foo", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/keyword.rs b/rust/candid/tests/assets/ok/keyword.rs index 3a1f3184..f61a15ca 100644 --- a/rust/candid/tests/assets/ok/keyword.rs +++ b/rust/candid/tests/assets/ok/keyword.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct o(Option>); @@ -47,44 +47,42 @@ candid::define_function!(pub t : (r#return) -> ()); pub enum variant_arg0 { A, B, C, D(f64) } pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn Oneway(&self) -> CallResult<()> { +impl SERVICE { + pub async fn Oneway(&self) -> Result<()> { ic_cdk::call(self.0, "Oneway", ()).await } - pub async fn f_(&self, arg0: o) -> CallResult<(o,)> { + pub async fn f_(&self, arg0: o) -> Result<(o,)> { ic_cdk::call(self.0, "f_", (arg0,)).await } - pub async fn field(&self, arg0: field_arg0) -> CallResult<(field_ret0,)> { + pub async fn field(&self, arg0: field_arg0) -> Result<(field_ret0,)> { ic_cdk::call(self.0, "field", (arg0,)).await } - pub async fn fieldnat(&self, arg0: fieldnat_arg0) -> CallResult< + pub async fn fieldnat(&self, arg0: fieldnat_arg0) -> Result< ((candid::Int,),) > { ic_cdk::call(self.0, "fieldnat", (arg0,)).await } - pub async fn oneway(&self, arg0: u8) -> CallResult<()> { + pub async fn oneway(&self, arg0: u8) -> Result<()> { ic_cdk::call(self.0, "oneway", (arg0,)).await } - pub async fn oneway_(&self, arg0: u8) -> CallResult<()> { + pub async fn oneway_(&self, arg0: u8) -> Result<()> { ic_cdk::call(self.0, "oneway_", (arg0,)).await } - pub async fn query(&self, arg0: serde_bytes::ByteBuf) -> CallResult< + pub async fn query(&self, arg0: serde_bytes::ByteBuf) -> Result< (serde_bytes::ByteBuf,) > { ic_cdk::call(self.0, "query", (arg0,)).await } - pub async fn r#return(&self, arg0: o) -> CallResult<(o,)> { + pub async fn r#return(&self, arg0: o) -> Result<(o,)> { ic_cdk::call(self.0, "return", (arg0,)).await } - pub async fn service(&self, arg0: r#return) -> CallResult<()> { + pub async fn service(&self, arg0: r#return) -> Result<()> { ic_cdk::call(self.0, "service", (arg0,)).await } pub async fn tuple( &self, arg0: (candid::Int,serde_bytes::ByteBuf,String,), - ) -> CallResult<((candid::Int,u8,),)> { + ) -> Result<((candid::Int,u8,),)> { ic_cdk::call(self.0, "tuple", (arg0,)).await } - pub async fn variant(&self, arg0: variant_arg0) -> CallResult<()> { + pub async fn variant(&self, arg0: variant_arg0) -> Result<()> { ic_cdk::call(self.0, "variant", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/management.d.ts b/rust/candid/tests/assets/ok/management.d.ts new file mode 100644 index 00000000..b0f868cc --- /dev/null +++ b/rust/candid/tests/assets/ok/management.d.ts @@ -0,0 +1,172 @@ +import type { Principal } from '@dfinity/principal'; +import type { ActorMethod } from '@dfinity/agent'; + +export type bitcoin_address = string; +export type bitcoin_network = { 'mainnet' : null } | + { 'testnet' : null }; +export type block_hash = Uint8Array | number[]; +export type canister_id = Principal; +export interface canister_settings { + 'freezing_threshold' : [] | [bigint], + 'controllers' : [] | [Array], + 'memory_allocation' : [] | [bigint], + 'compute_allocation' : [] | [bigint], +} +export interface definite_canister_settings { + 'freezing_threshold' : bigint, + 'controllers' : Array, + 'memory_allocation' : bigint, + 'compute_allocation' : bigint, +} +export type ecdsa_curve = { 'secp256k1' : null }; +export interface get_balance_request { + 'network' : bitcoin_network, + 'address' : bitcoin_address, + 'min_confirmations' : [] | [number], +} +export interface get_current_fee_percentiles_request { + 'network' : bitcoin_network, +} +export interface get_utxos_request { + 'network' : bitcoin_network, + 'filter' : [] | [ + { 'page' : Uint8Array | number[] } | + { 'min_confirmations' : number } + ], + 'address' : bitcoin_address, +} +export interface get_utxos_response { + 'next_page' : [] | [Uint8Array | number[]], + 'tip_height' : number, + 'tip_block_hash' : block_hash, + 'utxos' : Array, +} +export interface http_header { 'value' : string, 'name' : string } +export interface http_response { + 'status' : bigint, + 'body' : Uint8Array | number[], + 'headers' : Array, +} +export type millisatoshi_per_byte = bigint; +export interface outpoint { 'txid' : Uint8Array | number[], 'vout' : number } +export type satoshi = bigint; +export interface send_transaction_request { + 'transaction' : Uint8Array | number[], + 'network' : bitcoin_network, +} +export type user_id = Principal; +export interface utxo { + 'height' : number, + 'value' : satoshi, + 'outpoint' : outpoint, +} +export type wasm_module = Uint8Array | number[]; +export interface _SERVICE { + 'bitcoin_get_balance' : ActorMethod<[get_balance_request], satoshi>, + 'bitcoin_get_current_fee_percentiles' : ActorMethod< + [get_current_fee_percentiles_request], + BigUint64Array | bigint[] + >, + 'bitcoin_get_utxos' : ActorMethod<[get_utxos_request], get_utxos_response>, + 'bitcoin_send_transaction' : ActorMethod< + [send_transaction_request], + undefined + >, + 'canister_status' : ActorMethod< + [{ 'canister_id' : canister_id }], + { + 'status' : { 'stopped' : null } | + { 'stopping' : null } | + { 'running' : null }, + 'memory_size' : bigint, + 'cycles' : bigint, + 'settings' : definite_canister_settings, + 'idle_cycles_burned_per_day' : bigint, + 'module_hash' : [] | [Uint8Array | number[]], + } + >, + 'create_canister' : ActorMethod< + [{ 'settings' : [] | [canister_settings] }], + { 'canister_id' : canister_id } + >, + 'delete_canister' : ActorMethod<[{ 'canister_id' : canister_id }], undefined>, + 'deposit_cycles' : ActorMethod<[{ 'canister_id' : canister_id }], undefined>, + 'ecdsa_public_key' : ActorMethod< + [ + { + 'key_id' : { 'name' : string, 'curve' : ecdsa_curve }, + 'canister_id' : [] | [canister_id], + 'derivation_path' : Array, + }, + ], + { + 'public_key' : Uint8Array | number[], + 'chain_code' : Uint8Array | number[], + } + >, + 'http_request' : ActorMethod< + [ + { + 'url' : string, + 'method' : { 'get' : null } | + { 'head' : null } | + { 'post' : null }, + 'max_response_bytes' : [] | [bigint], + 'body' : [] | [Uint8Array | number[]], + 'transform' : [] | [ + { + 'function' : [Principal, string], + 'context' : Uint8Array | number[], + } + ], + 'headers' : Array, + }, + ], + http_response + >, + 'install_code' : ActorMethod< + [ + { + 'arg' : Uint8Array | number[], + 'wasm_module' : wasm_module, + 'mode' : { 'reinstall' : null } | + { 'upgrade' : null } | + { 'install' : null }, + 'canister_id' : canister_id, + }, + ], + undefined + >, + 'provisional_create_canister_with_cycles' : ActorMethod< + [ + { + 'settings' : [] | [canister_settings], + 'specified_id' : [] | [canister_id], + 'amount' : [] | [bigint], + }, + ], + { 'canister_id' : canister_id } + >, + 'provisional_top_up_canister' : ActorMethod< + [{ 'canister_id' : canister_id, 'amount' : bigint }], + undefined + >, + 'raw_rand' : ActorMethod<[], Uint8Array | number[]>, + 'sign_with_ecdsa' : ActorMethod< + [ + { + 'key_id' : { 'name' : string, 'curve' : ecdsa_curve }, + 'derivation_path' : Array, + 'message_hash' : Uint8Array | number[], + }, + ], + { 'signature' : Uint8Array | number[] } + >, + 'start_canister' : ActorMethod<[{ 'canister_id' : canister_id }], undefined>, + 'stop_canister' : ActorMethod<[{ 'canister_id' : canister_id }], undefined>, + 'uninstall_code' : ActorMethod<[{ 'canister_id' : canister_id }], undefined>, + 'update_settings' : ActorMethod< + [{ 'canister_id' : Principal, 'settings' : canister_settings }], + undefined + >, +} diff --git a/rust/candid/tests/assets/ok/management.did b/rust/candid/tests/assets/ok/management.did new file mode 100644 index 00000000..4d28f784 --- /dev/null +++ b/rust/candid/tests/assets/ok/management.did @@ -0,0 +1,127 @@ +type bitcoin_address = text; +type bitcoin_network = variant { mainnet; testnet }; +type block_hash = vec nat8; +type canister_id = principal; +type canister_settings = record { + freezing_threshold : opt nat; + controllers : opt vec principal; + memory_allocation : opt nat; + compute_allocation : opt nat; +}; +type definite_canister_settings = record { + freezing_threshold : nat; + controllers : vec principal; + memory_allocation : nat; + compute_allocation : nat; +}; +type ecdsa_curve = variant { secp256k1 }; +type get_balance_request = record { + network : bitcoin_network; + address : bitcoin_address; + min_confirmations : opt nat32; +}; +type get_current_fee_percentiles_request = record { network : bitcoin_network }; +type get_utxos_request = record { + network : bitcoin_network; + filter : opt variant { page : vec nat8; min_confirmations : nat32 }; + address : bitcoin_address; +}; +type get_utxos_response = record { + next_page : opt vec nat8; + tip_height : nat32; + tip_block_hash : block_hash; + utxos : vec utxo; +}; +type http_header = record { value : text; name : text }; +type http_response = record { + status : nat; + body : vec nat8; + headers : vec http_header; +}; +type millisatoshi_per_byte = nat64; +type outpoint = record { txid : vec nat8; vout : nat32 }; +type satoshi = nat64; +type send_transaction_request = record { + transaction : vec nat8; + network : bitcoin_network; +}; +type user_id = principal; +type utxo = record { height : nat32; value : satoshi; outpoint : outpoint }; +type wasm_module = vec nat8; +service : { + bitcoin_get_balance : (get_balance_request) -> (satoshi); + bitcoin_get_current_fee_percentiles : ( + get_current_fee_percentiles_request, + ) -> (vec millisatoshi_per_byte); + bitcoin_get_utxos : (get_utxos_request) -> (get_utxos_response); + bitcoin_send_transaction : (send_transaction_request) -> (); + canister_status : (record { canister_id : canister_id }) -> ( + record { + status : variant { stopped; stopping; running }; + memory_size : nat; + cycles : nat; + settings : definite_canister_settings; + idle_cycles_burned_per_day : nat; + module_hash : opt vec nat8; + }, + ); + create_canister : (record { settings : opt canister_settings }) -> ( + record { canister_id : canister_id }, + ); + delete_canister : (record { canister_id : canister_id }) -> (); + deposit_cycles : (record { canister_id : canister_id }) -> (); + ecdsa_public_key : ( + record { + key_id : record { name : text; curve : ecdsa_curve }; + canister_id : opt canister_id; + derivation_path : vec vec nat8; + }, + ) -> (record { public_key : vec nat8; chain_code : vec nat8 }); + http_request : ( + record { + url : text; + method : variant { get; head; post }; + max_response_bytes : opt nat64; + body : opt vec nat8; + transform : opt record { + function : func ( + record { context : vec nat8; response : http_response }, + ) -> (http_response) query; + context : vec nat8; + }; + headers : vec http_header; + }, + ) -> (http_response); + install_code : ( + record { + arg : vec nat8; + wasm_module : wasm_module; + mode : variant { reinstall; upgrade; install }; + canister_id : canister_id; + }, + ) -> (); + provisional_create_canister_with_cycles : ( + record { + settings : opt canister_settings; + specified_id : opt canister_id; + amount : opt nat; + }, + ) -> (record { canister_id : canister_id }); + provisional_top_up_canister : ( + record { canister_id : canister_id; amount : nat }, + ) -> (); + raw_rand : () -> (vec nat8); + sign_with_ecdsa : ( + record { + key_id : record { name : text; curve : ecdsa_curve }; + derivation_path : vec vec nat8; + message_hash : vec nat8; + }, + ) -> (record { signature : vec nat8 }); + start_canister : (record { canister_id : canister_id }) -> (); + stop_canister : (record { canister_id : canister_id }) -> (); + uninstall_code : (record { canister_id : canister_id }) -> (); + update_settings : ( + record { canister_id : principal; settings : canister_settings }, + ) -> (); +} diff --git a/rust/candid/tests/assets/ok/management.js b/rust/candid/tests/assets/ok/management.js new file mode 100644 index 00000000..cb2b784b --- /dev/null +++ b/rust/candid/tests/assets/ok/management.js @@ -0,0 +1,233 @@ +export const idlFactory = ({ IDL }) => { + const bitcoin_network = IDL.Variant({ + 'mainnet' : IDL.Null, + 'testnet' : IDL.Null, + }); + const bitcoin_address = IDL.Text; + const get_balance_request = IDL.Record({ + 'network' : bitcoin_network, + 'address' : bitcoin_address, + 'min_confirmations' : IDL.Opt(IDL.Nat32), + }); + const satoshi = IDL.Nat64; + const get_current_fee_percentiles_request = IDL.Record({ + 'network' : bitcoin_network, + }); + const millisatoshi_per_byte = IDL.Nat64; + const get_utxos_request = IDL.Record({ + 'network' : bitcoin_network, + 'filter' : IDL.Opt( + IDL.Variant({ + 'page' : IDL.Vec(IDL.Nat8), + 'min_confirmations' : IDL.Nat32, + }) + ), + 'address' : bitcoin_address, + }); + const block_hash = IDL.Vec(IDL.Nat8); + const outpoint = IDL.Record({ + 'txid' : IDL.Vec(IDL.Nat8), + 'vout' : IDL.Nat32, + }); + const utxo = IDL.Record({ + 'height' : IDL.Nat32, + 'value' : satoshi, + 'outpoint' : outpoint, + }); + const get_utxos_response = IDL.Record({ + 'next_page' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'tip_height' : IDL.Nat32, + 'tip_block_hash' : block_hash, + 'utxos' : IDL.Vec(utxo), + }); + const send_transaction_request = IDL.Record({ + 'transaction' : IDL.Vec(IDL.Nat8), + 'network' : bitcoin_network, + }); + const canister_id = IDL.Principal; + const definite_canister_settings = IDL.Record({ + 'freezing_threshold' : IDL.Nat, + 'controllers' : IDL.Vec(IDL.Principal), + 'memory_allocation' : IDL.Nat, + 'compute_allocation' : IDL.Nat, + }); + const canister_settings = IDL.Record({ + 'freezing_threshold' : IDL.Opt(IDL.Nat), + 'controllers' : IDL.Opt(IDL.Vec(IDL.Principal)), + 'memory_allocation' : IDL.Opt(IDL.Nat), + 'compute_allocation' : IDL.Opt(IDL.Nat), + }); + const ecdsa_curve = IDL.Variant({ 'secp256k1' : IDL.Null }); + const http_header = IDL.Record({ 'value' : IDL.Text, 'name' : IDL.Text }); + const http_response = IDL.Record({ + 'status' : IDL.Nat, + 'body' : IDL.Vec(IDL.Nat8), + 'headers' : IDL.Vec(http_header), + }); + const wasm_module = IDL.Vec(IDL.Nat8); + return IDL.Service({ + 'bitcoin_get_balance' : IDL.Func([get_balance_request], [satoshi], []), + 'bitcoin_get_current_fee_percentiles' : IDL.Func( + [get_current_fee_percentiles_request], + [IDL.Vec(millisatoshi_per_byte)], + [], + ), + 'bitcoin_get_utxos' : IDL.Func( + [get_utxos_request], + [get_utxos_response], + [], + ), + 'bitcoin_send_transaction' : IDL.Func([send_transaction_request], [], []), + 'canister_status' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id })], + [ + IDL.Record({ + 'status' : IDL.Variant({ + 'stopped' : IDL.Null, + 'stopping' : IDL.Null, + 'running' : IDL.Null, + }), + 'memory_size' : IDL.Nat, + 'cycles' : IDL.Nat, + 'settings' : definite_canister_settings, + 'idle_cycles_burned_per_day' : IDL.Nat, + 'module_hash' : IDL.Opt(IDL.Vec(IDL.Nat8)), + }), + ], + [], + ), + 'create_canister' : IDL.Func( + [IDL.Record({ 'settings' : IDL.Opt(canister_settings) })], + [IDL.Record({ 'canister_id' : canister_id })], + [], + ), + 'delete_canister' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id })], + [], + [], + ), + 'deposit_cycles' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id })], + [], + [], + ), + 'ecdsa_public_key' : IDL.Func( + [ + IDL.Record({ + 'key_id' : IDL.Record({ 'name' : IDL.Text, 'curve' : ecdsa_curve }), + 'canister_id' : IDL.Opt(canister_id), + 'derivation_path' : IDL.Vec(IDL.Vec(IDL.Nat8)), + }), + ], + [ + IDL.Record({ + 'public_key' : IDL.Vec(IDL.Nat8), + 'chain_code' : IDL.Vec(IDL.Nat8), + }), + ], + [], + ), + 'http_request' : IDL.Func( + [ + IDL.Record({ + 'url' : IDL.Text, + 'method' : IDL.Variant({ + 'get' : IDL.Null, + 'head' : IDL.Null, + 'post' : IDL.Null, + }), + 'max_response_bytes' : IDL.Opt(IDL.Nat64), + 'body' : IDL.Opt(IDL.Vec(IDL.Nat8)), + 'transform' : IDL.Opt( + IDL.Record({ + 'function' : IDL.Func( + [ + IDL.Record({ + 'context' : IDL.Vec(IDL.Nat8), + 'response' : http_response, + }), + ], + [http_response], + ['query'], + ), + 'context' : IDL.Vec(IDL.Nat8), + }) + ), + 'headers' : IDL.Vec(http_header), + }), + ], + [http_response], + [], + ), + 'install_code' : IDL.Func( + [ + IDL.Record({ + 'arg' : IDL.Vec(IDL.Nat8), + 'wasm_module' : wasm_module, + 'mode' : IDL.Variant({ + 'reinstall' : IDL.Null, + 'upgrade' : IDL.Null, + 'install' : IDL.Null, + }), + 'canister_id' : canister_id, + }), + ], + [], + [], + ), + 'provisional_create_canister_with_cycles' : IDL.Func( + [ + IDL.Record({ + 'settings' : IDL.Opt(canister_settings), + 'specified_id' : IDL.Opt(canister_id), + 'amount' : IDL.Opt(IDL.Nat), + }), + ], + [IDL.Record({ 'canister_id' : canister_id })], + [], + ), + 'provisional_top_up_canister' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id, 'amount' : IDL.Nat })], + [], + [], + ), + 'raw_rand' : IDL.Func([], [IDL.Vec(IDL.Nat8)], []), + 'sign_with_ecdsa' : IDL.Func( + [ + IDL.Record({ + 'key_id' : IDL.Record({ 'name' : IDL.Text, 'curve' : ecdsa_curve }), + 'derivation_path' : IDL.Vec(IDL.Vec(IDL.Nat8)), + 'message_hash' : IDL.Vec(IDL.Nat8), + }), + ], + [IDL.Record({ 'signature' : IDL.Vec(IDL.Nat8) })], + [], + ), + 'start_canister' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id })], + [], + [], + ), + 'stop_canister' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id })], + [], + [], + ), + 'uninstall_code' : IDL.Func( + [IDL.Record({ 'canister_id' : canister_id })], + [], + [], + ), + 'update_settings' : IDL.Func( + [ + IDL.Record({ + 'canister_id' : IDL.Principal, + 'settings' : canister_settings, + }), + ], + [], + [], + ), + }); +}; +export const init = ({ IDL }) => { return []; }; diff --git a/rust/candid/tests/assets/ok/management.mo b/rust/candid/tests/assets/ok/management.mo new file mode 100644 index 00000000..0609c738 --- /dev/null +++ b/rust/candid/tests/assets/ok/management.mo @@ -0,0 +1,125 @@ +// This is a generated Motoko binding. +// Please use `import service "ic:canister_id"` instead to call canisters on the IC if possible. + +module { + public type bitcoin_address = Text; + public type bitcoin_network = { #mainnet; #testnet }; + public type block_hash = Blob; + public type canister_id = Principal; + public type canister_settings = { + freezing_threshold : ?Nat; + controllers : ?[Principal]; + memory_allocation : ?Nat; + compute_allocation : ?Nat; + }; + public type definite_canister_settings = { + freezing_threshold : Nat; + controllers : [Principal]; + memory_allocation : Nat; + compute_allocation : Nat; + }; + public type ecdsa_curve = { #secp256k1 }; + public type get_balance_request = { + network : bitcoin_network; + address : bitcoin_address; + min_confirmations : ?Nat32; + }; + public type get_current_fee_percentiles_request = { + network : bitcoin_network; + }; + public type get_utxos_request = { + network : bitcoin_network; + filter : ?{ #page : Blob; #min_confirmations : Nat32 }; + address : bitcoin_address; + }; + public type get_utxos_response = { + next_page : ?Blob; + tip_height : Nat32; + tip_block_hash : block_hash; + utxos : [utxo]; + }; + public type http_header = { value : Text; name : Text }; + public type http_response = { + status : Nat; + body : Blob; + headers : [http_header]; + }; + public type millisatoshi_per_byte = Nat64; + public type outpoint = { txid : Blob; vout : Nat32 }; + public type satoshi = Nat64; + public type send_transaction_request = { + transaction : Blob; + network : bitcoin_network; + }; + public type user_id = Principal; + public type utxo = { height : Nat32; value : satoshi; outpoint : outpoint }; + public type wasm_module = Blob; + public type Self = actor { + bitcoin_get_balance : shared get_balance_request -> async satoshi; + bitcoin_get_current_fee_percentiles : shared get_current_fee_percentiles_request -> async [ + millisatoshi_per_byte + ]; + bitcoin_get_utxos : shared get_utxos_request -> async get_utxos_response; + bitcoin_send_transaction : shared send_transaction_request -> async (); + canister_status : shared { canister_id : canister_id } -> async { + status : { #stopped; #stopping; #running }; + memory_size : Nat; + cycles : Nat; + settings : definite_canister_settings; + idle_cycles_burned_per_day : Nat; + module_hash : ?Blob; + }; + create_canister : shared { settings : ?canister_settings } -> async { + canister_id : canister_id; + }; + delete_canister : shared { canister_id : canister_id } -> async (); + deposit_cycles : shared { canister_id : canister_id } -> async (); + ecdsa_public_key : shared { + key_id : { name : Text; curve : ecdsa_curve }; + canister_id : ?canister_id; + derivation_path : [Blob]; + } -> async { public_key : Blob; chain_code : Blob }; + http_request : shared { + url : Text; + method : { #get; #head; #post }; + max_response_bytes : ?Nat64; + body : ?Blob; + transform : ?{ + function : shared query { + context : Blob; + response : http_response; + } -> async http_response; + context : Blob; + }; + headers : [http_header]; + } -> async http_response; + install_code : shared { + arg : Blob; + wasm_module : wasm_module; + mode : { #reinstall; #upgrade; #install }; + canister_id : canister_id; + } -> async (); + provisional_create_canister_with_cycles : shared { + settings : ?canister_settings; + specified_id : ?canister_id; + amount : ?Nat; + } -> async { canister_id : canister_id }; + provisional_top_up_canister : shared { + canister_id : canister_id; + amount : Nat; + } -> async (); + raw_rand : shared () -> async Blob; + sign_with_ecdsa : shared { + key_id : { name : Text; curve : ecdsa_curve }; + derivation_path : [Blob]; + message_hash : Blob; + } -> async { signature : Blob }; + start_canister : shared { canister_id : canister_id } -> async (); + stop_canister : shared { canister_id : canister_id } -> async (); + uninstall_code : shared { canister_id : canister_id } -> async (); + update_settings : shared { + canister_id : Principal; + settings : canister_settings; + } -> async (); + } +} diff --git a/rust/candid/tests/assets/ok/management.rs b/rust/candid/tests/assets/ok/management.rs new file mode 100644 index 00000000..c927f102 --- /dev/null +++ b/rust/candid/tests/assets/ok/management.rs @@ -0,0 +1,369 @@ +// This is an experimental feature to generate Rust binding from Candid. +// You may want to manually adjust some of the types. +use candid::{self, CandidType, Deserialize, Principal}; +type Result = std::result::Result; +#[derive(CandidType, Deserialize)] +pub enum bitcoin_network { mainnet, testnet } + +pub type bitcoin_address = String; +#[derive(CandidType, Deserialize)] +pub struct get_balance_request { + network: bitcoin_network, + address: bitcoin_address, + min_confirmations: Option, +} + +pub type satoshi = u64; +#[derive(CandidType, Deserialize)] +pub struct get_current_fee_percentiles_request { network: bitcoin_network } + +pub type millisatoshi_per_byte = u64; +#[derive(CandidType, Deserialize)] +pub enum get_utxos_request_filter_inner { + page(serde_bytes::ByteBuf), + min_confirmations(u32), +} + +#[derive(CandidType, Deserialize)] +pub struct get_utxos_request { + network: bitcoin_network, + filter: Option, + address: bitcoin_address, +} + +pub type block_hash = serde_bytes::ByteBuf; +#[derive(CandidType, Deserialize)] +pub struct outpoint { txid: serde_bytes::ByteBuf, vout: u32 } + +#[derive(CandidType, Deserialize)] +pub struct utxo { height: u32, value: satoshi, outpoint: outpoint } + +#[derive(CandidType, Deserialize)] +pub struct get_utxos_response { + next_page: Option, + tip_height: u32, + tip_block_hash: block_hash, + utxos: Vec, +} + +#[derive(CandidType, Deserialize)] +pub struct send_transaction_request { + transaction: serde_bytes::ByteBuf, + network: bitcoin_network, +} + +pub type canister_id = Principal; +#[derive(CandidType, Deserialize)] +pub struct canister_status_arg0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub enum canister_status_ret0_status { stopped, stopping, running } + +#[derive(CandidType, Deserialize)] +pub struct definite_canister_settings { + freezing_threshold: candid::Nat, + controllers: Vec, + memory_allocation: candid::Nat, + compute_allocation: candid::Nat, +} + +#[derive(CandidType, Deserialize)] +pub struct canister_status_ret0 { + status: canister_status_ret0_status, + memory_size: candid::Nat, + cycles: candid::Nat, + settings: definite_canister_settings, + idle_cycles_burned_per_day: candid::Nat, + module_hash: Option, +} + +#[derive(CandidType, Deserialize)] +pub struct canister_settings { + freezing_threshold: Option, + controllers: Option>, + memory_allocation: Option, + compute_allocation: Option, +} + +#[derive(CandidType, Deserialize)] +pub struct create_canister_arg0 { settings: Option } + +#[derive(CandidType, Deserialize)] +pub struct create_canister_ret0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub struct delete_canister_arg0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub struct deposit_cycles_arg0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub enum ecdsa_curve { secp256k1 } + +#[derive(CandidType, Deserialize)] +pub struct ecdsa_public_key_arg0_key_id { name: String, curve: ecdsa_curve } + +#[derive(CandidType, Deserialize)] +pub struct ecdsa_public_key_arg0 { + key_id: ecdsa_public_key_arg0_key_id, + canister_id: Option, + derivation_path: Vec, +} + +#[derive(CandidType, Deserialize)] +pub struct ecdsa_public_key_ret0 { + public_key: serde_bytes::ByteBuf, + chain_code: serde_bytes::ByteBuf, +} + +#[derive(CandidType, Deserialize)] +pub enum http_request_arg0_method { get, head, post } + +#[derive(CandidType, Deserialize)] +pub struct http_header { value: String, name: String } + +#[derive(CandidType, Deserialize)] +pub struct http_response { + status: candid::Nat, + body: serde_bytes::ByteBuf, + headers: Vec, +} + +#[derive(CandidType, Deserialize)] +pub struct http_request_arg0_transform_inner_function_arg0 { + context: serde_bytes::ByteBuf, + response: http_response, +} + +candid::define_function!(pub http_request_arg0_transform_inner_function : ( + http_request_arg0_transform_inner_function_arg0, + ) -> (http_response) query); +#[derive(CandidType, Deserialize)] +pub struct http_request_arg0_transform_inner { + function: http_request_arg0_transform_inner_function, + context: serde_bytes::ByteBuf, +} + +#[derive(CandidType, Deserialize)] +pub struct http_request_arg0 { + url: String, + method: http_request_arg0_method, + max_response_bytes: Option, + body: Option, + transform: Option, + headers: Vec, +} + +pub type wasm_module = serde_bytes::ByteBuf; +#[derive(CandidType, Deserialize)] +pub enum install_code_arg0_mode { reinstall, upgrade, install } + +#[derive(CandidType, Deserialize)] +pub struct install_code_arg0 { + arg: serde_bytes::ByteBuf, + wasm_module: wasm_module, + mode: install_code_arg0_mode, + canister_id: canister_id, +} + +#[derive(CandidType, Deserialize)] +pub struct provisional_create_canister_with_cycles_arg0 { + settings: Option, + specified_id: Option, + amount: Option, +} + +#[derive(CandidType, Deserialize)] +pub struct provisional_create_canister_with_cycles_ret0 { + canister_id: canister_id, +} + +#[derive(CandidType, Deserialize)] +pub struct provisional_top_up_canister_arg0 { + canister_id: canister_id, + amount: candid::Nat, +} + +#[derive(CandidType, Deserialize)] +pub struct sign_with_ecdsa_arg0_key_id { name: String, curve: ecdsa_curve } + +#[derive(CandidType, Deserialize)] +pub struct sign_with_ecdsa_arg0 { + key_id: sign_with_ecdsa_arg0_key_id, + derivation_path: Vec, + message_hash: serde_bytes::ByteBuf, +} + +#[derive(CandidType, Deserialize)] +pub struct sign_with_ecdsa_ret0 { signature: serde_bytes::ByteBuf } + +#[derive(CandidType, Deserialize)] +pub struct start_canister_arg0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub struct stop_canister_arg0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub struct uninstall_code_arg0 { canister_id: canister_id } + +#[derive(CandidType, Deserialize)] +pub struct update_settings_arg0 { + canister_id: Principal, + settings: canister_settings, +} + +pub struct SERVICE(pub Principal); +impl SERVICE { + pub async fn bitcoin_get_balance( + &self, agent: &ic_agent::Agent, + arg0: get_balance_request, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "bitcoin_get_balance").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, satoshi)?) + } + pub async fn bitcoin_get_current_fee_percentiles( + &self, agent: &ic_agent::Agent, + arg0: get_current_fee_percentiles_request, + ) -> Result> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "bitcoin_get_current_fee_percentiles").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, Vec)?) + } + pub async fn bitcoin_get_utxos( + &self, agent: &ic_agent::Agent, + arg0: get_utxos_request, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "bitcoin_get_utxos").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, get_utxos_response)?) + } + pub async fn bitcoin_send_transaction( + &self, agent: &ic_agent::Agent, + arg0: send_transaction_request, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "bitcoin_send_transaction").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn canister_status( + &self, agent: &ic_agent::Agent, + arg0: canister_status_arg0, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "canister_status").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, canister_status_ret0)?) + } + pub async fn create_canister( + &self, agent: &ic_agent::Agent, + arg0: create_canister_arg0, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "create_canister").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, create_canister_ret0)?) + } + pub async fn delete_canister( + &self, agent: &ic_agent::Agent, + arg0: delete_canister_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "delete_canister").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn deposit_cycles( + &self, agent: &ic_agent::Agent, + arg0: deposit_cycles_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "deposit_cycles").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn ecdsa_public_key( + &self, agent: &ic_agent::Agent, + arg0: ecdsa_public_key_arg0, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "ecdsa_public_key").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, ecdsa_public_key_ret0)?) + } + pub async fn http_request( + &self, agent: &ic_agent::Agent, + arg0: http_request_arg0, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "http_request").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, http_response)?) + } + pub async fn install_code( + &self, agent: &ic_agent::Agent, + arg0: install_code_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "install_code").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn provisional_create_canister_with_cycles( + &self, agent: &ic_agent::Agent, + arg0: provisional_create_canister_with_cycles_arg0, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "provisional_create_canister_with_cycles").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, provisional_create_canister_with_cycles_ret0)?) + } + pub async fn provisional_top_up_canister( + &self, agent: &ic_agent::Agent, + arg0: provisional_top_up_canister_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "provisional_top_up_canister").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn raw_rand(&self, agent: &ic_agent::Agent) -> Result< + serde_bytes::ByteBuf + > { + let args = candid::Encode!()?; + let bytes = agent.update(self.0, "raw_rand").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, serde_bytes::ByteBuf)?) + } + pub async fn sign_with_ecdsa( + &self, agent: &ic_agent::Agent, + arg0: sign_with_ecdsa_arg0, + ) -> Result { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "sign_with_ecdsa").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes, sign_with_ecdsa_ret0)?) + } + pub async fn start_canister( + &self, agent: &ic_agent::Agent, + arg0: start_canister_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "start_canister").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn stop_canister( + &self, agent: &ic_agent::Agent, + arg0: stop_canister_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "stop_canister").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn uninstall_code( + &self, agent: &ic_agent::Agent, + arg0: uninstall_code_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "uninstall_code").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } + pub async fn update_settings( + &self, agent: &ic_agent::Agent, + arg0: update_settings_arg0, + ) -> Result<()> { + let args = candid::Encode!(arg0)?; + let bytes = agent.update(self.0, "update_settings").with_arg(args).call_and_wait().await?; + Ok(candid::Decode!(&bytes)?) + } +} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/recursion.rs b/rust/candid/tests/assets/ok/recursion.rs index f140db9c..9660947c 100644 --- a/rust/candid/tests/assets/ok/recursion.rs +++ b/rust/candid/tests/assets/ok/recursion.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; candid::define_function!(pub t : (s) -> ()); #[derive(CandidType, Deserialize)] @@ -32,14 +32,12 @@ candid::define_service!(pub s : { "g" : candid::func!((list) -> (B, tree, stream)); }); pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn f(&self, arg0: s) -> CallResult<()> { +impl SERVICE { + pub async fn f(&self, arg0: s) -> Result<()> { ic_cdk::call(self.0, "f", (arg0,)).await } - pub async fn g(&self, arg0: list) -> CallResult<(B,tree,stream,)> { + pub async fn g(&self, arg0: list) -> Result<(B,tree,stream,)> { ic_cdk::call(self.0, "g", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/recursive_class.rs b/rust/candid/tests/assets/ok/recursive_class.rs index de08e12d..50c14176 100644 --- a/rust/candid/tests/assets/ok/recursive_class.rs +++ b/rust/candid/tests/assets/ok/recursive_class.rs @@ -1,15 +1,13 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; candid::define_service!(pub s : { "next" : candid::func!(() -> (s)) }); pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn next(&self) -> CallResult<(s,)> { +impl SERVICE { + pub async fn next(&self) -> Result<(s,)> { ic_cdk::call(self.0, "next", ()).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/service.rs b/rust/candid/tests/assets/ok/service.rs index 98011fd3..6050e8f4 100644 --- a/rust/candid/tests/assets/ok/service.rs +++ b/rust/candid/tests/assets/ok/service.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; candid::define_function!(pub Func : () -> (Service)); candid::define_service!(pub Service : { "f" : Func::ty() }); @@ -10,20 +10,18 @@ pub type Service2 = Box; pub enum asVariant_ret0 { a(Service2), b{ f: Option } } pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn asArray(&self) -> CallResult<(Vec,Vec,)> { +impl SERVICE { + pub async fn asArray(&self) -> Result<(Vec,Vec,)> { ic_cdk::call(self.0, "asArray", ()).await } - pub async fn asPrincipal(&self) -> CallResult<(Service2,Func,)> { + pub async fn asPrincipal(&self) -> Result<(Service2,Func,)> { ic_cdk::call(self.0, "asPrincipal", ()).await } - pub async fn asRecord(&self) -> CallResult< - ((Service2,Option,Func,),) - > { ic_cdk::call(self.0, "asRecord", ()).await } - pub async fn asVariant(&self) -> CallResult<(asVariant_ret0,)> { + pub async fn asRecord(&self) -> Result<((Service2,Option,Func,),)> { + ic_cdk::call(self.0, "asRecord", ()).await + } + pub async fn asVariant(&self) -> Result<(asVariant_ret0,)> { ic_cdk::call(self.0, "asVariant", ()).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/assets/ok/unicode.rs b/rust/candid/tests/assets/ok/unicode.rs index eeef9f8f..7c473496 100644 --- a/rust/candid/tests/assets/ok/unicode.rs +++ b/rust/candid/tests/assets/ok/unicode.rs @@ -1,7 +1,7 @@ // This is an experimental feature to generate Rust binding from Candid. // You may want to manually adjust some of the types. use candid::{self, CandidType, Deserialize, Principal}; -use ic_cdk::api::call::CallResult; +use ic_cdk::api::call::CallResult as Result; #[derive(CandidType, Deserialize)] pub struct A { @@ -28,20 +28,18 @@ pub enum B { } pub struct SERVICE(pub Principal); -impl SERVICE{ - pub async fn _0_(&self, arg0: candid::Nat) -> CallResult<(candid::Nat,)> { +impl SERVICE { + pub async fn _0_(&self, arg0: candid::Nat) -> Result<(candid::Nat,)> { ic_cdk::call(self.0, "", (arg0,)).await } - pub async fn _356566390_(&self) -> CallResult<()> { + pub async fn _356566390_(&self) -> Result<()> { ic_cdk::call(self.0, "✈️ 🚗 ⛱️ ", ()).await } - pub async fn _3300066460_(&self, arg0: A) -> CallResult<(B,)> { + pub async fn _3300066460_(&self, arg0: A) -> Result<(B,)> { ic_cdk::call(self.0, "函数名", (arg0,)).await } - pub async fn _2669435454_(&self, arg0: candid::Nat) -> CallResult< + pub async fn _2669435454_(&self, arg0: candid::Nat) -> Result< (candid::Nat,) > { ic_cdk::call(self.0, "👀", (arg0,)).await } } -pub fn service() -> SERVICE { - SERVICE(Principal::from_text("aaaaa-aa").unwrap()) -} +pub const service: SERVICE = SERVICE(Principal::from_slice(&[])); // aaaaa-aa diff --git a/rust/candid/tests/parse_type.rs b/rust/candid/tests/parse_type.rs index 7b863e97..85ec1362 100644 --- a/rust/candid/tests/parse_type.rs +++ b/rust/candid/tests/parse_type.rs @@ -63,6 +63,9 @@ fn compiler_test(resource: &str) { { let mut config = rust::Config::new(); config.canister_id = Some(candid::Principal::from_text("aaaaa-aa").unwrap()); + if filename.file_name().unwrap().to_str().unwrap() == "management.did" { + config.target = rust::Target::Agent; + } let mut output = mint.new_goldenfile(filename.with_extension("rs")).unwrap(); let content = rust::compile(&config, &env, &actor); writeln!(output, "{content}").unwrap(); diff --git a/tools/didc/src/main.rs b/tools/didc/src/main.rs index e88cad5f..393aaa33 100644 --- a/tools/didc/src/main.rs +++ b/tools/didc/src/main.rs @@ -23,7 +23,7 @@ enum Command { Bind { /// Specifies did file for code generation input: PathBuf, - #[clap(short, long, possible_values = &["js", "ts", "did", "mo", "rs"])] + #[clap(short, long, possible_values = &["js", "ts", "did", "mo", "rs", "rs-agent"])] /// Specifies target language target: String, }, @@ -184,6 +184,11 @@ fn main() -> Result<()> { let config = candid::bindings::rust::Config::new(); candid::bindings::rust::compile(&config, &env, &actor) } + "rs-agent" => { + let config = candid::bindings::rust::Config::new(); + config.target = candid: bindings::rust::Target::Agent; + candid::bindings::rust::compile(&config, &env, &actor) + } _ => unreachable!(), }; println!("{content}"); From 9a1fa8e7e1b4080495cbc84e15c29ee150f5a29a Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Wed, 3 May 2023 10:27:38 -0700 Subject: [PATCH 5/6] fix --- tools/didc/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/didc/src/main.rs b/tools/didc/src/main.rs index 393aaa33..49d8ba41 100644 --- a/tools/didc/src/main.rs +++ b/tools/didc/src/main.rs @@ -186,7 +186,7 @@ fn main() -> Result<()> { } "rs-agent" => { let config = candid::bindings::rust::Config::new(); - config.target = candid: bindings::rust::Target::Agent; + config.target = candid::bindings::rust::Target::Agent; candid::bindings::rust::compile(&config, &env, &actor) } _ => unreachable!(), From 3589190b34cdf08166a4439cfe0e3e26b244262c Mon Sep 17 00:00:00 2001 From: Yan Chen Date: Tue, 23 May 2023 16:00:10 -0700 Subject: [PATCH 6/6] fix --- tools/didc/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/didc/src/main.rs b/tools/didc/src/main.rs index 0494520e..608167d8 100644 --- a/tools/didc/src/main.rs +++ b/tools/didc/src/main.rs @@ -188,7 +188,7 @@ fn main() -> Result<()> { candid::bindings::rust::compile(&config, &env, &actor) } "rs-agent" => { - let config = candid::bindings::rust::Config::new(); + let mut config = candid::bindings::rust::Config::new(); config.target = candid::bindings::rust::Target::Agent; candid::bindings::rust::compile(&config, &env, &actor) }