Skip to main content

calimero_context_primitives/client/external/
proxy.rs

1use calimero_context_config::client::env::proxy::ContextProxy;
2use calimero_context_config::repr::{ReprBytes, ReprTransmute};
3use calimero_context_config::types::{ContextStorageEntry, ProposalId};
4use calimero_context_config::{Proposal, ProposalAction};
5use calimero_primitives::identity::PublicKey;
6use eyre::OptionExt;
7
8use super::ExternalClient;
9
10#[derive(Debug)]
11pub struct ExternalProxyClient<'a> {
12    client: &'a ExternalClient<'a>,
13}
14
15impl ExternalClient<'_> {
16    #[must_use]
17    pub const fn proxy(&self) -> ExternalProxyClient<'_> {
18        ExternalProxyClient { client: self }
19    }
20}
21
22impl ExternalProxyClient<'_> {
23    pub async fn propose(
24        &self,
25        public_key: &PublicKey,
26        proposal_id: &ProposalId,
27        actions: Vec<ProposalAction>,
28    ) -> eyre::Result<()> {
29        let signer_id = public_key.rt().expect("infallible conversion");
30
31        let identity = self
32            .client
33            .context_client()
34            .get_identity(&self.client.context_id, public_key)?
35            .ok_or_eyre("identity not found")?;
36
37        let private_key = identity.private_key()?;
38
39        let client = self.client.mutate::<ContextProxy>(
40            self.client.config.protocol.as_ref().into(),
41            self.client.config.network_id.as_ref().into(),
42            self.client.config.proxy_contract.as_ref().into(),
43        );
44
45        let _ignored = client
46            .propose(*proposal_id, signer_id, actions)
47            .send(**private_key)
48            .await?;
49
50        Ok(())
51    }
52
53    pub async fn approve(
54        &self,
55        public_key: &PublicKey,
56        proposal_id: &ProposalId,
57    ) -> eyre::Result<()> {
58        let signer_id = public_key.rt().expect("infallible conversion");
59
60        let identity = self
61            .client
62            .context_client()
63            .get_identity(&self.client.context_id, public_key)?
64            .ok_or_eyre("identity not found")?;
65
66        let private_key = identity.private_key()?;
67
68        let client = self.client.mutate::<ContextProxy>(
69            self.client.config.protocol.as_ref().into(),
70            self.client.config.network_id.as_ref().into(),
71            self.client.config.proxy_contract.as_ref().into(),
72        );
73
74        let _ignored = client
75            .approve(signer_id, *proposal_id)
76            .send(**private_key)
77            .await?;
78
79        Ok(())
80    }
81
82    pub async fn active_proposals(&self) -> eyre::Result<u16> {
83        let client = self.client.query::<ContextProxy>(
84            self.client.config.protocol.as_ref().into(),
85            self.client.config.network_id.as_ref().into(),
86            self.client.config.proxy_contract.as_ref().into(),
87        );
88
89        let proposals = client.get_number_of_active_proposals().await?;
90
91        Ok(proposals)
92    }
93
94    pub async fn get_external_proxy_contract(&self) -> eyre::Result<String> {
95        Ok(self.client.config.proxy_contract.clone().into_owned())
96    }
97
98    pub async fn get_external_value(&self, stored_key: Vec<u8>) -> eyre::Result<Vec<u8>> {
99        let client = self.client.query::<ContextProxy>(
100            self.client.config.protocol.as_ref().into(),
101            self.client.config.network_id.as_ref().into(),
102            self.client.config.proxy_contract.as_ref().into(),
103        );
104
105        let value = client.get_context_value(stored_key).await?;
106
107        Ok(value)
108    }
109
110    pub async fn get_proposal(&self, proposal_id: &ProposalId) -> eyre::Result<Option<Proposal>> {
111        let client = self.client.query::<ContextProxy>(
112            self.client.config.protocol.as_ref().into(),
113            self.client.config.network_id.as_ref().into(),
114            self.client.config.proxy_contract.as_ref().into(),
115        );
116
117        let proposal = client.proposal(*proposal_id).await?;
118
119        Ok(proposal)
120    }
121
122    pub async fn get_proposal_approvers(
123        &self,
124        proposal_id: &ProposalId,
125    ) -> eyre::Result<impl Iterator<Item = PublicKey>> {
126        let client = self.client.query::<ContextProxy>(
127            self.client.config.protocol.as_ref().into(),
128            self.client.config.network_id.as_ref().into(),
129            self.client.config.proxy_contract.as_ref().into(),
130        );
131
132        let approvers = client.get_proposal_approvers(*proposal_id).await?;
133
134        let approvers = approvers
135            .into_iter()
136            .map(|identity| identity.as_bytes().into());
137
138        Ok(approvers)
139    }
140
141    pub async fn get_proposals(&self, offset: usize, limit: usize) -> eyre::Result<Vec<Proposal>> {
142        let client = self.client.query::<ContextProxy>(
143            self.client.config.protocol.as_ref().into(),
144            self.client.config.network_id.as_ref().into(),
145            self.client.config.proxy_contract.as_ref().into(),
146        );
147
148        let proposals = client.proposals(offset, limit).await?;
149
150        Ok(proposals)
151    }
152
153    pub async fn proposal_approvals(&self, proposal_id: &ProposalId) -> eyre::Result<usize> {
154        let client = self.client.query::<ContextProxy>(
155            self.client.config.protocol.as_ref().into(),
156            self.client.config.network_id.as_ref().into(),
157            self.client.config.proxy_contract.as_ref().into(),
158        );
159
160        let approvals = client
161            .get_number_of_proposal_approvals(*proposal_id)
162            .await?;
163
164        Ok(approvals.num_approvals)
165    }
166
167    pub async fn get_external_storage_entries(
168        &self,
169        offset: usize,
170        limit: usize,
171    ) -> eyre::Result<Vec<ContextStorageEntry>> {
172        let client = self.client.query::<ContextProxy>(
173            self.client.config.protocol.as_ref().into(),
174            self.client.config.network_id.as_ref().into(),
175            self.client.config.proxy_contract.as_ref().into(),
176        );
177
178        let entries = client.get_context_storage_entries(offset, limit).await?;
179
180        Ok(entries)
181    }
182}