Skip to main content

dash_sdk/platform/
identities_contract_keys_query.rs

1use dapi_grpc::platform::v0::get_identities_contract_keys_request::GetIdentitiesContractKeysRequestV0;
2use dapi_grpc::platform::v0::get_identities_contract_keys_request::Version::V0;
3use dapi_grpc::platform::v0::GetIdentitiesContractKeysRequest;
4use dpp::identity::Purpose;
5use rs_dapi_client::transport::{
6    AppliedRequestSettings, BoxFuture, TransportError, TransportRequest,
7};
8
9use crate::platform::query::Query;
10use crate::platform::Identifier;
11use crate::Error;
12
13/// Request that is used to query identities' contract keys
14#[derive(Debug, Clone, dash_platform_macros::Mockable)]
15#[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))]
16pub struct IdentitiesContractKeysQuery {
17    /// The identities' identifiers that we want to query
18    pub identities_ids: Vec<Identifier>,
19    /// The contract identifier
20    pub contract_id: Identifier,
21    /// An optional document type if the keys are on a document type instead of the contract
22    pub document_type_name: Option<String>,
23    /// The purposes we want to query for
24    pub purposes: Vec<Purpose>,
25}
26
27impl IdentitiesContractKeysQuery {
28    /// Create new IdentitiesContractKeysQuery for provided identities ids, contract id, the document
29    /// type (if we want to make the query on the document type level), and purposes
30    pub fn new(
31        identities_ids: Vec<Identifier>,
32        contract_id: Identifier,
33        document_type_name: Option<String>,
34        purposes: Vec<Purpose>,
35    ) -> Result<Self, Error> {
36        Ok(Self {
37            identities_ids,
38            contract_id,
39            document_type_name,
40            purposes,
41        })
42    }
43}
44
45impl TryFrom<IdentitiesContractKeysQuery> for GetIdentitiesContractKeysRequest {
46    type Error = Error;
47    fn try_from(dapi_request: IdentitiesContractKeysQuery) -> Result<Self, Self::Error> {
48        let IdentitiesContractKeysQuery {
49            identities_ids,
50            contract_id,
51            document_type_name,
52            purposes,
53        } = dapi_request;
54        //todo: transform this into PlatformVersionedTryFrom
55        Ok(GetIdentitiesContractKeysRequest {
56            version: Some(V0(GetIdentitiesContractKeysRequestV0 {
57                identities_ids: identities_ids.into_iter().map(|a| a.to_vec()).collect(),
58                contract_id: contract_id.to_vec(),
59                document_type_name,
60                purposes: purposes.into_iter().map(|purpose| purpose as i32).collect(),
61                prove: true,
62            })),
63        })
64    }
65}
66
67impl Query<GetIdentitiesContractKeysRequest> for IdentitiesContractKeysQuery {
68    fn query(
69        &self,
70        settings: &crate::platform::QuerySettings<'_>,
71    ) -> Result<GetIdentitiesContractKeysRequest, Error> {
72        let prove = settings.prove;
73        let IdentitiesContractKeysQuery {
74            identities_ids,
75            contract_id,
76            document_type_name,
77            purposes,
78        } = self;
79        Ok(GetIdentitiesContractKeysRequest {
80            version: Some(V0(GetIdentitiesContractKeysRequestV0 {
81                identities_ids: identities_ids.iter().map(|a| a.to_vec()).collect(),
82                contract_id: contract_id.to_vec(),
83                document_type_name: document_type_name.clone(),
84                purposes: purposes.iter().map(|purpose| *purpose as i32).collect(),
85                prove,
86            })),
87        })
88    }
89}
90
91impl crate::platform::query::WireQuery for IdentitiesContractKeysQuery {}
92
93impl TransportRequest for IdentitiesContractKeysQuery {
94    type Client = <GetIdentitiesContractKeysRequest as TransportRequest>::Client;
95    type Response = <GetIdentitiesContractKeysRequest as TransportRequest>::Response;
96    const SETTINGS_OVERRIDES: rs_dapi_client::RequestSettings =
97        <GetIdentitiesContractKeysRequest as TransportRequest>::SETTINGS_OVERRIDES;
98
99    fn request_name(&self) -> &'static str {
100        "getIdentitiesContractKeysRequest"
101    }
102
103    fn method_name(&self) -> &'static str {
104        "get_identities_contract_keys"
105    }
106
107    fn names_nothing(&self) -> Option<&'static str> {
108        GetIdentitiesContractKeysRequest::try_from(self.clone())
109            .ok()
110            .and_then(|request| request.names_nothing())
111    }
112
113    fn needs_protocol_version(&self) -> Option<u32> {
114        GetIdentitiesContractKeysRequest::try_from(self.clone())
115            .ok()
116            .and_then(|request| request.needs_protocol_version())
117    }
118
119    fn execute_transport<'c>(
120        self,
121        client: &'c mut Self::Client,
122        settings: &AppliedRequestSettings,
123    ) -> BoxFuture<'c, Result<Self::Response, TransportError>> {
124        let request: GetIdentitiesContractKeysRequest = self
125            .try_into()
126            .expect("IdentitiesContractKeysQuery should always be valid");
127        request.execute_transport(client, settings)
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134
135    #[test]
136    fn should_name_nothing_like_the_request_it_sends() {
137        let query = |identities_ids: Vec<Identifier>, purposes: Vec<Purpose>| {
138            IdentitiesContractKeysQuery::new(
139                identities_ids,
140                Identifier::from([2; 32]),
141                None,
142                purposes,
143            )
144            .expect("valid query")
145        };
146
147        assert_eq!(
148            query(vec![], vec![Purpose::AUTHENTICATION]).names_nothing(),
149            Some("identities_ids must contain at least one identifier when requesting a proof")
150        );
151        assert_eq!(
152            query(vec![Identifier::from([1; 32])], vec![]).names_nothing(),
153            Some("purposes must contain at least one purpose when requesting a proof")
154        );
155        assert_eq!(
156            query(
157                vec![Identifier::from([1; 32])],
158                vec![Purpose::AUTHENTICATION]
159            )
160            .names_nothing(),
161            None
162        );
163    }
164}