cap_sdk_core/
root.rs

1//! Methods for dealing with a root bucket.
2//!
3//! For more information on the purpose of a root bucket, see the documentation on
4//! [`RootBucket`].
5
6use crate::Bucket;
7use cap_common::transaction::IndefiniteEvent;
8use cap_common::{GetBucketResponse, WithIdArg};
9use ic_kit::candid::CandidType;
10use ic_kit::{ic::call, Principal, RejectionCode};
11use serde::{Deserialize, Serialize};
12
13/// A root bucket.
14///
15/// Every token contract has a root bucket. This bucket is used for the main inserting transactions
16/// into history, and organizing fetching the bucket that corresponds to a given transaction.
17///
18/// A root bucket implements the same interface as [`Bucket`], but with 3 additional methods.
19///
20/// Use [`RootBucket`]'s [`Into<Bucket>`] implementation to use a [`RootBucket`] as a [`Bucket`].
21#[derive(Copy, Clone, Serialize, Deserialize, CandidType)]
22pub struct RootBucket(pub Principal);
23
24impl RootBucket {
25    /// Returns a bucket that be used to query for the given transaction ID.
26    pub async fn get_bucket_for(&self, id: u64) -> Result<Bucket, (RejectionCode, String)> {
27        let result: (GetBucketResponse,) = call(
28            self.0,
29            "get_bucket_for",
30            (WithIdArg { id, witness: false },),
31        )
32        .await?;
33
34        Ok(Bucket(result.0.canister))
35    }
36
37    /// Inserts the given transaction and returns it's issued transaction ID.
38    pub async fn insert(&self, event: &IndefiniteEvent) -> Result<u64, (RejectionCode, String)> {
39        let result: (u64,) = call(self.0, "insert", (event,)).await?;
40
41        Ok(result.0)
42    }
43
44    /// Inserts the given transactions.
45    pub async fn insert_many(
46        &self,
47        events: &[IndefiniteEvent],
48    ) -> Result<u64, (RejectionCode, String)> {
49        let result: (u64,) = call(self.0, "insert_many", (events,)).await?;
50
51        Ok(result.0)
52    }
53
54    /// The time on the canister.
55    ///
56    /// The time can be used to check if this bucket is on the same subnet as the caller.
57    pub async fn time(&self) -> Result<u64, (RejectionCode, String)> {
58        let result: (u64,) = call(self.0, "time", ()).await?;
59
60        Ok(result.0)
61    }
62}