canic_core/macros/endpoints/
root.rs

1// Generate the endpoint surface for the root orchestrator canister.
2#[macro_export]
3macro_rules! canic_endpoints_root {
4    () => {
5        // canic_app
6        // modify app-level state
7        // eventually this will cascade down from an orchestrator canister
8        #[::canic::cdk::update]
9        async fn canic_app(
10            cmd: ::canic::core::ops::model::memory::state::AppCommand,
11        ) -> Result<(), ::canic::Error> {
12            $crate::auth_require_any!(::canic::core::auth::is_controller)?;
13
14            ::canic::core::ops::model::memory::state::AppStateOps::command(cmd)?;
15
16            let bundle = ::canic::core::ops::sync::state::StateBundle::new().with_app_state();
17            ::canic::core::ops::sync::state::cascade_root_state(bundle).await?;
18
19            Ok(())
20        }
21
22        // canic_canister_upgrade
23        #[::canic::cdk::update]
24        async fn canic_canister_upgrade(
25            canister_pid: ::candid::Principal,
26        ) -> Result<::canic::core::ops::request::UpgradeCanisterResponse, ::canic::Error> {
27            $crate::auth_require_any!(::canic::core::auth::is_controller)?;
28
29            let res = $crate::ops::request::upgrade_canister_request(canister_pid).await?;
30
31            Ok(res)
32        }
33
34        // canic_response
35        // root's way to respond to a generic request from another canister
36        // has to come from a direct child canister
37        #[::canic::cdk::update]
38        async fn canic_response(
39            request: ::canic::core::ops::request::Request,
40        ) -> Result<::canic::core::ops::request::Response, ::canic::Error> {
41            $crate::auth_require_any!(::canic::core::auth::is_registered_to_subnet)?;
42
43            let response = $crate::ops::request::response(request).await?;
44
45            Ok(response)
46        }
47
48        // canic_canister_status
49        // this can be called via root as root is the master controller
50        #[::canic::cdk::update]
51        async fn canic_canister_status(
52            pid: ::canic::cdk::candid::Principal,
53        ) -> Result<::canic::cdk::mgmt::CanisterStatusResult, ::canic::Error> {
54            auth_require_any!(
55                ::canic::core::auth::is_root,
56                ::canic::core::auth::is_controller
57            )?;
58
59            $crate::interface::ic::canister_status(pid).await
60        }
61
62        //
63        // CONFIG
64        //
65
66        #[::canic::cdk::query]
67        async fn canic_config() -> Result<String, ::canic::Error> {
68            $crate::auth_require_any!(::canic::core::auth::is_controller)?;
69
70            $crate::config::Config::to_toml()
71        }
72
73        //
74        // REGISTRIES
75        //
76
77        #[::canic::cdk::query]
78        fn canic_app_subnet_registry()
79        -> ::canic::core::ops::model::memory::topology::AppSubnetRegistryView {
80            $crate::ops::model::memory::topology::AppSubnetRegistryOps::export()
81        }
82
83        #[::canic::cdk::query]
84        fn canic_subnet_canister_registry()
85        -> ::canic::core::ops::model::memory::topology::subnet::SubnetCanisterRegistryView {
86            $crate::ops::model::memory::topology::SubnetCanisterRegistryOps::export()
87        }
88
89        //
90        // CANISTER RESERVE
91        //
92
93        #[::canic::cdk::query]
94        async fn canic_reserve_list()
95        -> Result<::canic::core::ops::model::memory::reserve::CanisterReserveView, ::canic::Error> {
96            Ok($crate::ops::model::memory::reserve::CanisterReserveOps::export())
97        }
98
99        #[::canic::cdk::update]
100        async fn canic_reserve_create_empty()
101        -> Result<::canic::cdk::candid::Principal, ::canic::Error> {
102            $crate::auth_require_any!(::canic::core::auth::is_controller)?;
103
104            ::canic::core::ops::model::memory::reserve::reserve_create_canister().await
105        }
106
107        #[::canic::cdk::update]
108        async fn canic_reserve_recycle(
109            pid: ::canic::cdk::candid::Principal,
110        ) -> Result<(), ::canic::Error> {
111            $crate::auth_require_any!(::canic::core::auth::is_controller)?;
112
113            ::canic::core::ops::model::memory::reserve::recycle_via_orchestrator(pid).await
114        }
115
116        #[::canic::cdk::update]
117        async fn canic_reserve_import(
118            pid: ::canic::cdk::candid::Principal,
119        ) -> Result<(), ::canic::Error> {
120            $crate::auth_require_any!(::canic::core::auth::is_controller)?;
121
122            ::canic::core::ops::model::memory::reserve::reserve_import_canister(pid)
123                .await
124                .map(|_| ())
125        }
126    };
127}
128
129// Generate the endpoint surface for non-root canisters.
130#[macro_export]
131macro_rules! canic_endpoints_nonroot {
132    () => {
133        //
134        // SYNC
135        //
136
137        #[::canic::cdk::update]
138        async fn canic_sync_state(
139            bundle: ::canic::core::ops::sync::state::StateBundle,
140        ) -> Result<(), ::canic::Error> {
141            $crate::auth_require_any!(::canic::core::auth::is_parent)?;
142
143            $crate::ops::sync::state::nonroot_cascade_state(&bundle).await
144        }
145
146        #[::canic::cdk::update]
147        async fn canic_sync_topology(
148            bundle: ::canic::core::ops::sync::topology::TopologyBundle,
149        ) -> Result<(), ::canic::Error> {
150            $crate::auth_require_any!(::canic::core::auth::is_parent)?;
151
152            $crate::ops::sync::topology::nonroot_cascade_topology(&bundle).await
153        }
154    };
155}