concordium_rust_sdk/
cis3.rs1use crate::{
4 contract_client::{ContractClient, ContractTransactionMetadata},
5 types::{self as sdk_types, transactions},
6 v2::{self, IntoBlockIdentifier},
7};
8use concordium_base::{
9 base::Energy,
10 cis3_types::{
11 NewSupportsPermitQueryParamsError, PermitParams, SupportsPermitQueryParams,
12 SupportsPermitRepsonse,
13 },
14 contracts_common::{Address, Amount, OwnedEntrypointName},
15 smart_contracts::OwnedParameter,
16 transactions::{AccountTransaction, EncodedPayload},
17};
18use sdk_types::smart_contracts;
19use smart_contracts::concordium_contracts_common;
20use thiserror::Error;
21
22#[derive(Debug, Clone, Copy)]
23pub enum Cis3Type {}
26
27pub type Cis3Contract = ContractClient<Cis3Type>;
35
36#[derive(Error, Debug)]
38pub enum Cis3PermitError {
39 #[error("Invalid receive name: {0}")]
41 InvalidReceiveName(#[from] concordium_contracts_common::NewReceiveNameError),
42
43 #[error("RPC error: {0}")]
45 RPCError(#[from] crate::endpoints::RPCError),
46}
47
48#[derive(Error, Debug)]
50pub enum Cis3PermitDryRunError {
51 #[error("Invalid receive name: {0}")]
53 InvalidReceiveName(#[from] concordium_contracts_common::NewReceiveNameError),
54
55 #[error("RPC error: {0}")]
57 RPCError(#[from] crate::endpoints::RPCError),
58
59 #[error("RPC error: {0}")]
61 QueryError(#[from] crate::endpoints::QueryError),
62
63 #[error("Rejected by the node: {0:?}.")]
65 NodeRejected(v2::Upward<sdk_types::RejectReason>),
66}
67
68#[derive(Debug, Error)]
71pub enum Cis3SupportsPermitError {
72 #[error("Invalid receive name: {0}")]
74 InvalidReceiveName(#[from] concordium_contracts_common::NewReceiveNameError),
75
76 #[error("Invalid supportsPermit parameter: {0}")]
78 InvalidParams(#[from] NewSupportsPermitQueryParamsError),
79
80 #[error("RPC error: {0}")]
82 RPCError(#[from] super::v2::QueryError),
83
84 #[error("Failed parsing the response.")]
86 ResponseParseError(#[from] concordium_contracts_common::ParseError),
87
88 #[error("Rejected by the node: {0:?}.")]
90 NodeRejected(v2::Upward<sdk_types::RejectReason>),
91}
92
93impl From<v2::Upward<sdk_types::RejectReason>> for Cis3SupportsPermitError {
96 fn from(err: v2::Upward<sdk_types::RejectReason>) -> Self {
97 Self::NodeRejected(err)
98 }
99}
100impl From<sdk_types::RejectReason> for Cis3SupportsPermitError {
101 fn from(err: sdk_types::RejectReason) -> Self {
102 Self::NodeRejected(v2::Upward::Known(err))
103 }
104}
105
106impl From<v2::Upward<sdk_types::RejectReason>> for Cis3PermitDryRunError {
109 fn from(err: v2::Upward<sdk_types::RejectReason>) -> Self {
110 Self::NodeRejected(err)
111 }
112}
113impl From<sdk_types::RejectReason> for Cis3PermitDryRunError {
114 fn from(err: sdk_types::RejectReason) -> Self {
115 Self::NodeRejected(v2::Upward::Known(err))
116 }
117}
118
119impl Cis3Contract {
120 pub async fn permit_dry_run(
133 &mut self,
134 bi: impl IntoBlockIdentifier,
135 sender: Address,
136 params: PermitParams,
137 ) -> Result<Energy, Cis3PermitDryRunError> {
138 let parameter = OwnedParameter::from_serial(¶ms)
139 .expect("A PermitParams should always be serializable");
140 let ir = self
141 .invoke_raw::<Cis3PermitDryRunError>(
142 "permit",
143 Amount::zero(),
144 Some(sender),
145 parameter,
146 bi,
147 )
148 .await?;
149 match ir {
150 smart_contracts::InvokeContractResult::Success { used_energy, .. } => Ok(used_energy),
151 smart_contracts::InvokeContractResult::Failure { reason, .. } => Err(reason.into()),
152 }
153 }
154
155 pub async fn permit(
169 &mut self,
170 signer: &impl transactions::ExactSizeTransactionSigner,
171 metadata: &ContractTransactionMetadata,
172 params: PermitParams,
173 ) -> Result<sdk_types::hashes::TransactionHash, Cis3PermitError> {
174 let permit = self.make_permit(signer, metadata, params)?;
175 let hash = self.client.send_account_transaction(permit).await?;
176 Ok(hash)
177 }
178
179 pub fn make_permit(
193 &mut self,
194 signer: &impl transactions::ExactSizeTransactionSigner,
195 metadata: &ContractTransactionMetadata,
196 params: PermitParams,
197 ) -> Result<AccountTransaction<EncodedPayload>, Cis3PermitError> {
198 let message = smart_contracts::OwnedParameter::from_serial(¶ms)
199 .expect("A PermitParams should always be serializable");
200 self.make_update_raw(signer, metadata, "permit", message)
201 }
202
203 pub async fn supports_permit(
215 &mut self,
216 bi: impl IntoBlockIdentifier,
217 entrypoints: Vec<OwnedEntrypointName>,
218 ) -> Result<SupportsPermitRepsonse, Cis3SupportsPermitError> {
219 let parameter = SupportsPermitQueryParams::new(entrypoints)?;
220 let message = OwnedParameter::from_serial(¶meter).map_err(|_| {
221 Cis3SupportsPermitError::InvalidParams(NewSupportsPermitQueryParamsError)
222 })?;
223 self.view_raw("supportsPermit", message, bi).await
224 }
225
226 pub async fn supports_permit_single(
230 &mut self,
231 bi: impl IntoBlockIdentifier,
232 entrypoint: OwnedEntrypointName,
233 ) -> Result<bool, Cis3SupportsPermitError> {
234 only_one(self.supports_permit(bi, vec![entrypoint]).await?)
235 }
236}
237
238fn only_one<A, V: AsRef<Vec<A>>>(res: V) -> Result<A, Cis3SupportsPermitError>
241where
242 Vec<A>: From<V>,
243{
244 let err =
245 Cis3SupportsPermitError::ResponseParseError(concordium_contracts_common::ParseError {});
246 if res.as_ref().len() > 1 {
247 Err(err)
248 } else {
249 Vec::from(res).pop().ok_or(err)
250 }
251}