{"id":13523684,"url":"https://github.com/bitfinity-network/canister-sdk","last_synced_at":"2026-01-17T04:32:13.896Z","repository":{"id":36955226,"uuid":"436962608","full_name":"bitfinity-network/canister-sdk","owner":"bitfinity-network","description":"🛠 SDK for writing and testing canisters for the Internet Computer in Rust","archived":false,"fork":false,"pushed_at":"2025-06-10T08:04:23.000Z","size":1925,"stargazers_count":38,"open_issues_count":0,"forks_count":10,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-12-29T21:45:01.541Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitfinity-network.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-10T11:57:54.000Z","updated_at":"2025-12-13T09:40:44.000Z","dependencies_parsed_at":"2023-10-01T21:45:48.399Z","dependency_job_id":"ce3edd1d-79cf-4de0-82b3-fe48cb750992","html_url":"https://github.com/bitfinity-network/canister-sdk","commit_stats":null,"previous_names":["bitfinity-network/canister-sdk"],"tags_count":96,"template":false,"template_full_name":null,"purl":"pkg:github/bitfinity-network/canister-sdk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinity-network%2Fcanister-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinity-network%2Fcanister-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinity-network%2Fcanister-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinity-network%2Fcanister-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitfinity-network","download_url":"https://codeload.github.com/bitfinity-network/canister-sdk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitfinity-network%2Fcanister-sdk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28495160,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T06:01:02.662Z","updated_at":"2026-01-17T04:32:13.884Z","avatar_url":"https://github.com/bitfinity-network.png","language":"Rust","funding_links":[],"categories":["Canister Development Kits (CDKs)"],"sub_categories":["Rust"],"readme":"# Canister SDK\n\nSDK for writing and testing canisters for the Internet Computer in Rust. This repo includes a few crates that help to\nsimplify the tricky aspects of IC canisters development:\n\n- [Canister SDK](#canister-sdk)\n  - [Crates](#crates)\n  - [canister-sdk](#canister-sdk-1)\n    - [ic-exports](#ic-exports)\n    - [ic-canister](#ic-canister)\n      - [Inter-canister calls and testing](#inter-canister-calls-and-testing)\n      - [Canister traits and composition](#canister-traits-and-composition)\n      - [Dependencies between canisters](#dependencies-between-canisters)\n    - [ic-factory](#ic-factory)\n    - [ic-helpers](#ic-helpers)\n    - [ic-storage](#ic-storage)\n      - [In-memory storage](#in-memory-storage)\n      - [Versioned state](#versioned-state)\n      - [Canister state and upgrades](#canister-state-and-upgrades)\n    - [ic-metrics](#ic-metrics)\n    - [ic-auction](#ic-auction)\n    - [ic-log](#ic-log)\n\nThis project builds on top of `ic-cdk` and `ic-kit` crates. It is not intended to replace them, but adds some types and\nmacros to simplify things that are not dealt with by those crates.\n\n## Crates\n\nThe following crates are included in this repo:\n\n- `ic-auction` - This crate provides an API trait for auction canisters. This crate is optional.\n- `ic-canister` - This crate provides a set of macros and types to simplify the development of canisters.\n- `ic-export` - This crate mainly re-exports commonly used dependencies from `ic` dependencies.\n- `ic-log` - This crate provides a simple logger implementation of the `log` crate. Log records are saved into memory and can be inspected with a canister query.\n- `ic-metrics` - This crate provides an API trait to simplify the collection of metrics from canisters.\n- `ic-storage` - This crate provides a simple in-memory storage for canisters.\n\n## canister-sdk\n\nA wrapper crate among all the canisters in this repository with all the necessary re-exports. It some features for\nexporting factory and auction traits as well as their APIs.\n\nNote: Currently we require each canister to have its own `export-api` feature that will export the wasm definitions of\nthe canister (and hide them if this canister is used as a dependency). This is not the case with trait canisters as rust\nfeatures are additive even in transitive dependencies we're forced to introduce different `export-api` features for\ndifferent traits in this repo (`auction-api` and `factory-api` respectively). The best approach will be to\nuse `canister-sdk` dependency with dependent features that will trigger the necessary APIs transitively, e.g.\n\n```yaml\n[ package ]\n  edition = \"2021\"\n  name = \"awesome-canister\"\n  version = \"0.1.0\"\n\n  [ features ]\n  default = []\n  export-api = [\"canister-sdk/auction-api\"]\n  auction = [\"canister-sdk/auction\"]\n\n  [ dependencies ]\n  canister-sdk = { git = \"https://github.com/infinity-swap/canister-sdk\", package = \"canister-sdk\" }\n```\n\nThere's an example crate on how to use the `export-api` feature in the [canister-e](./ic-canister/tests/canister-e/) directory. This crate shows how to use the `export-api` features to export the methods in the canister and how to generate the idl for the canister with the methods included.\n\n### ic-exports\n\nThe `ic-exports` crate re-exports commonly used `ic` dependencies. This means that you can use the `ic-exports` crate to\nimport the `ic` dependencies without having to specify the version of the `ic` dependencies in your `Cargo.toml` file.\n\n```rust\nuse ic_exports::*;\n```\n\nThe common `ic` dependencies that are re-exported are:\n\n- `ic-cdk`\n- `ic-cdk-macros`\n- `ic-kit`\n- `ic-agent`\n- `ic-icrc1`\n- `ic-icrc1-index`\n- `ledger-canister`\n- `ic-ledger-core`\n- `ic-stable-structures`\n- `cycles-minting-canister`\n- `ic-base-types`\n- `ic-ic00-types`\n\n### ic-canister\n\nThis crate introduces a framework to write easily testable canisters, including testing inter-canister calls,\nas well as a way to compose canister APIs using rust traits. There are few examples below, but for the details\nyou can check out the [crate documentation](./ic-canister/ic-canister/src/lib.rs).\n\n#### Inter-canister calls and testing\n\nFor example, you can have a canister with simple API:\n\n```rust\n#[derive(Clone, Canister)]\nstruct MyCanister {\n    #[id]\n    principal: Principal,\n\n    #[state]\n    state: Rc\u003cRefCell\u003cMyCanisterState\u003e\u003e,\n}\n\nimpl MyCanister {\n    #[query]\n    fn get_counter(\u0026self) -\u003e u64 {\n        self.state.borrow().counter\n    }\n\n    #[update]\n    fn add(\u0026self, value: u64) {\n        self.state.borrow_mut().counter += value;\n    }\n}\n```\n\nNow instead of using `ic_cdk::api::call` to query these APIs from another canister doing manual\nserialization/deserialization:\n\n```rust\n\nimpl MyOtherCanister {\n    #[update]\n    async fn increment_get(\u0026self, id: Principal) -\u003e u64 {\n        let my_canister = MyCanister::from_principal(id);\n        canister_call!(my_canister.add(1), ()).await.unwrap();\n        let updated_value = canister_call!(my_canister.get_counter(), u64).await.unwrap();\n\n        updated_value\n    }\n}\n```\n\nNow, if you want to test the `increment_get` method of you canister, all you need to do is to write a unit test:\n\n```rust\n#[tokio::test]\nasync fn test_increment_get() {\n    let my_canister = MyCanister::init_instance();\n    let my_other_canister = MyOtherCanister::init_instance();\n\n    assert_eq!(my_other_canister.increment_get(my_canister.principal()), 1);\n    assert_eq!(my_other_canister.increment_get(my_canister.principal()), 2);\n}\n```\n\nEven though the canisters use statics internally to store the canister state, the tests can initialize multiple\ninstances of\ncanisters with `init_instance` method, and each one of them will have a separate state.\n\n#### Canister traits and composition\n\nIt is also possible to write a trait to store some part of the canister API that can be reused in different canisters.\nThis also allows to compose a canister from different\ntraits just by implementing the needed traits for your canister Struct:\n\n```rust\nimpl Factory for MyCanister {\n    fn state(\u0026self) -\u003e Rc\u003cRefCell\u003cFactoryState\u003e\u003e {\n        \u003cSelf as Factory\u003e::FactoryStateState::get()\n    }\n}\n\nimpl OtherCanisterTrait for MyCanister {\n    // impl\n}\n```\n\nFor other examples you can look into\nthe [tests](https://github.com/infinity-swap/canister-sdk/blob/f835312e13b567ca2cb1d75cc3a1647da5d41204/ic-canister/tests/canister_a/src/lib.rs#L21-L46)\n\n#### Dependencies between canisters\n\nIf you use `ic-cdk` to create your canister's API's, you cannot simply use a canister as a rust dependency for another\ncanister, because all the APIs of that dependency will not be included into the canister you're implementing. If you\ncreate a canister using `canister-sdk`, don't forget to add a `export-api` feature to the dependency so that it will\nexport all the wasm from the canister trait definition (more specifically from one that is auto-generated\nby `generate_exports!` macro).\n\n\n### ic-helpers\n\nSome helpers and wrappers over principals we use on day-to-day basis for ledger and management canister calls.\n\n### ic-storage\n\nIntroduces traits `IcStorage` and `Versioned` for in-memory and stable storage management respectively.\n\n#### In-memory storage\n\nIn the past, the `ic-cdk` crate provided methods in the `ic_cdk::storage` module to store and get structs from the\ncanister's memory, but they were removed in version `0.5.0` (for a good reason). The recommended way to store the data\nin the canister\nmemory is to use `thread_local` storage with `RefCell` controlling access to the struct.\n\nThe `ic_storage::IcStorage` deriving macro does exactly that, but saving you some boilerplate. Using it is quite\nstraightforward:\n\n```rust\nuse ic_storage::IcStorage;\n\n#[derive(IcStorage, Default)]\nstruct MyCanisterState {\n    value: u32,\n}\n\nlet local_state = MyCanisterState::get();\nassert_eq!(local_state.borrow().value, 0);\nlocal_state.borrow_mut().value = 42;\nassert_eq!(local_state.borrow().value, 42);\n```\n\nIt also allows having generic state structures. For detailed information, check out\nthe [crate level documentation](./ic-storage/src/lib.rs).\n\n#### Versioned state\n\nThe `ic_storage::stable` module introduces `Versioned` trait that allows transparent upgrades for the state during\ncanister upgrades (even over several versions of state at once). When using this trait, the state structure can\nbe serialized into the stable storage using `ic_storage::stable::write` method. Then after the upgrade, simply use\n`ic_storage::stable::read::\u003cNewStateType\u003e()`. This will read the serialized previous version of the state, check its\nversion and run the upgrade methods until the current version of the type (the `NewStateType` struct) is reached.\n\nCheck out the [module level documentation](./ic-storage/src/stable.rs) for more details.\n\n#### Canister state and upgrades\n\nWhen using `Canister` deriving macro, the fields that are marked with `#[state]` attribute are all preserved over\ncanister upgrades. This is done using `Versioned` trait. This means that at this moment you can have only one `#[state]`\nin a canister. If the state type is changed, the new state must have the previous state type as\nits `Versioned::Previous` type. The `Canister` deriving macro takes care of generating the `pre_upgrade`\nand `post_upgrade` functions and updating the state to the new type when needed.\n\nIf a canister needs to have a state that is not preserved during the upgrade process (like caches or some other\ntemporary data), `#[state(stable_store = false)]` can be used in addition to the `#[state]` field. Any number of\nnon-stable state fields can be added to a canister.\n\n### ic-metrics\n\nMetrics trait that the canister can implement to store a history of necessary metrics (stored\nin [MetricsData](https://github.com/infinity-swap/canister-sdk/blob/f835312e13b567ca2cb1d75cc3a1647da5d41204/ic-metrics/src/map.rs#L14-L18))\nfor the canister that also\nallows to overwrite the `update_metrics` call to store custom metrics for a canister. For an example you can refer to\nthe [tests](https://github.com/infinity-swap/canister-sdk/blob/main/ic-canister/tests/canister-c/src/lib.rs#L43-L49).\n\nThis crate currently provides two APIs for metrics, these are :-\n\n- `get_metrics` - This API returns the metrics data for the canister. It returns snapshot of the metrics data over a\n  certain period of the interval.\n- `get_curr_metrics` - This API returns the current metrics data for the canister.\n\n### ic-auction\n\nThe IC canisters needs cycles to run and as well as to pay for the storage. This crate provides a mechanism of cycle\nauctions, that doesn't require owner's attention for the canister cycle management. Cycle auctions are run in a set of\nintervals, and allow any user to add cycles to the canister and retrieve a reward set up via `disburse_rewards` call as\na reward for doing so. You can find more information about the cycle auctions in the [README](./ic-auction/README.md).\n\nThis crate is optional and can be used by adding the feature `auction` to your `Cargo.toml` file.\n\n```yaml\n[ dependencies ]\n  canister-sdk = { git = \"https://github.com/infinity-swap/canister-sdk\", features = [\"auction\"] tag = \"vx.x.xx\"}\n```\n\nNote: When you're using the `canister-sdk` with these crates, make sure to include `export-api` feature as well, and\nwhen building the canister, make sure to include the `--export-api` flag.\n\n### ic-log\n\nIC log is a log library for IC canisters. It allows you to use the `log` crate macros (`debug!`, `info!`, `error!`...) into a canister. The records are written into memory with a configurable history size and can be later be retrieved by a query to the canister.\n\nYou can see ic-log in action in the [examples](./ic-log/examples/log_canister.rs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitfinity-network%2Fcanister-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitfinity-network%2Fcanister-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitfinity-network%2Fcanister-sdk/lists"}