calimero_context_primitives/client/external/
proxy.rs1use 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}