cat_gateway/service/api/cardano/cip36/
response.rs

1//! Cip36 Registration Query Endpoint Response
2
3use catalyst_types::problem_report::ProblemReport;
4use derive_more::{From, Into};
5use poem_openapi::{
6    ApiResponse, NewType, Object,
7    payload::Json,
8    types::{Example, ToJSON},
9};
10
11use crate::service::common::{self, types::array_types::impl_array_types};
12
13// ToDo: The examples of this response should be taken from representative data from a
14// response generated on pre-prod.
15
16/// Endpoint responses.
17#[derive(ApiResponse)]
18pub(crate) enum Cip36Registration {
19    /// All CIP36 registrations associated with the same Voting Key.
20    #[oai(status = 200)]
21    Ok(Json<Cip36RegistrationList>),
22    /// No valid registration.
23    #[oai(status = 404)]
24    NotFound,
25}
26
27/// All responses to a cip36 registration query
28pub(crate) type AllRegistration = common::responses::WithErrorResponses<Cip36Registration>;
29
30/// List of CIP36 Registration Data as found on-chain.
31#[derive(Object)]
32#[oai(example = true)]
33pub(crate) struct Cip36RegistrationList {
34    /// The Slot the Registrations are valid up until.
35    ///
36    /// Any registrations that occurred after this Slot are not included in the list.
37    /// Errors are reported only if they fall between the last valid registration and this
38    /// slot number.
39    /// Earlier errors are never reported.
40    pub slot: common::types::cardano::slot_no::SlotNo,
41    /// List of registrations associated with the query.
42    pub voting_key: Cip36RegistrationsForVotingPublicKeyList,
43    /// List of latest invalid registrations that were found, for the requested filter.
44    #[oai(skip_serializing_if_is_empty)]
45    pub invalid: common::types::cardano::registration_list::RegistrationCip36List,
46    /// Current Page
47    #[oai(skip_serializing_if_is_none)]
48    pub page: Option<Cip36RegistrationListPage>,
49}
50
51impl Example for Cip36RegistrationList {
52    fn example() -> Self {
53        Self {
54            slot: (common::types::cardano::slot_no::EXAMPLE + 635)
55                .try_into()
56                .unwrap_or_default(),
57            voting_key: Example::example(),
58            invalid: vec![Cip36Details::invalid_example()].into(),
59            page: Some(Example::example()),
60        }
61    }
62}
63
64/// The Page of CIP-36 Registration List.
65#[derive(NewType, From, Into)]
66#[oai(
67    from_multipart = false,
68    from_parameter = false,
69    to_header = false,
70    example = true
71)]
72pub(crate) struct Cip36RegistrationListPage(common::objects::generic::pagination::CurrentPage);
73
74impl Example for Cip36RegistrationListPage {
75    fn example() -> Self {
76        Self(Example::example())
77    }
78}
79
80// List of CIP-36 Registrations for voting public key
81impl_array_types!(
82    Cip36RegistrationsForVotingPublicKeyList,
83    Cip36RegistrationsForVotingPublicKey,
84    Some(poem_openapi::registry::MetaSchema {
85        example: Self::example().to_json(),
86        max_items: Some(100),
87        items: Some(Box::new(Cip36RegistrationsForVotingPublicKey::schema_ref())),
88        ..poem_openapi::registry::MetaSchema::ANY
89    })
90);
91
92impl Example for Cip36RegistrationsForVotingPublicKeyList {
93    fn example() -> Self {
94        Self(vec![Example::example()])
95    }
96}
97
98/// List of CIP36 Registration Data for a Voting Key.
99#[derive(Object, Debug, Clone)]
100#[oai(example = true)]
101pub(crate) struct Cip36RegistrationsForVotingPublicKey {
102    /// Voting Public Key
103    pub vote_pub_key: common::types::generic::ed25519_public_key::Ed25519HexEncodedPublicKey,
104    /// List of Registrations associated with this Voting Key
105    pub registrations: common::types::cardano::registration_list::RegistrationCip36List,
106}
107
108impl Example for Cip36RegistrationsForVotingPublicKey {
109    fn example() -> Self {
110        Self {
111            vote_pub_key: Example::example(),
112            registrations: Example::example(),
113        }
114    }
115}
116
117/// CIP36 Registration Data as found on-chain.
118#[derive(Object, Debug, Clone)]
119#[oai(example = true)]
120pub(crate) struct Cip36Details {
121    /// Blocks Slot Number that the registration certificate is in.
122    pub slot_no: common::types::cardano::slot_no::SlotNo,
123    /// Full Stake Address (not hashed, 32 byte ED25519 Public key).
124    #[oai(skip_serializing_if_is_none)]
125    pub stake_pub_key:
126        Option<common::types::generic::ed25519_public_key::Ed25519HexEncodedPublicKey>,
127    /// Voting Public Key (Ed25519 Public key).
128    #[oai(skip_serializing_if_is_none)]
129    pub vote_pub_key:
130        Option<common::types::generic::ed25519_public_key::Ed25519HexEncodedPublicKey>,
131    #[allow(clippy::missing_docs_in_private_items)] // Type is pre documented.
132    #[oai(skip_serializing_if_is_none)]
133    pub nonce: Option<common::types::cardano::nonce::Nonce>,
134    #[allow(clippy::missing_docs_in_private_items)] // Type is pre documented.
135    #[oai(skip_serializing_if_is_none)]
136    pub txn: Option<common::types::cardano::txn_index::TxnIndex>,
137    /// Cardano Cip-19 Formatted Shelley Payment Address.
138    #[oai(skip_serializing_if_is_none)]
139    pub payment_address: Option<common::types::cardano::cip19_shelley_address::Cip19ShelleyAddress>,
140    /// If the payment address is a script, then it can not be payed rewards.
141    pub is_payable: common::types::generic::boolean::BooleanFlag,
142    /// If this field is set, then the registration was in CIP15 format.
143    pub cip15: common::types::generic::boolean::BooleanFlag,
144    /// If there are errors with this registration, they are listed here.
145    /// This field is *NEVER* returned for a valid registration.
146    #[oai(skip_serializing_if_is_none)]
147    pub errors: Option<common::objects::generic::problem_report::ProblemReport>,
148}
149
150impl Example for Cip36Details {
151    /// Example of a valid registration
152    fn example() -> Self {
153        Self {
154            slot_no: common::types::cardano::slot_no::SlotNo::example(),
155            stake_pub_key: Some(
156                common::types::generic::ed25519_public_key::Ed25519HexEncodedPublicKey::examples(0),
157            ),
158            vote_pub_key: Some(
159                common::types::generic::ed25519_public_key::Ed25519HexEncodedPublicKey::example(),
160            ),
161            nonce: Some(common::types::cardano::nonce::Nonce::example()),
162            txn: Some(common::types::cardano::txn_index::TxnIndex::example()),
163            payment_address: Some(
164                common::types::cardano::cip19_shelley_address::Cip19ShelleyAddress::example(),
165            ),
166            is_payable: true.into(),
167            cip15: false.into(),
168            errors: None,
169        }
170    }
171}
172
173impl Cip36Details {
174    /// Example of an invalid registration
175    fn invalid_example() -> Self {
176        let problem_report = ProblemReport::new("Cip36");
177        problem_report.other("Error occurred", "Cip36 decoding error");
178
179        Self {
180            slot_no: (common::types::cardano::slot_no::EXAMPLE + 135)
181                .try_into()
182                .unwrap_or_default(),
183            stake_pub_key: None,
184            vote_pub_key: Some(
185                common::types::generic::ed25519_public_key::Ed25519HexEncodedPublicKey::example(),
186            ),
187            nonce: Some((common::types::cardano::nonce::EXAMPLE + 97).into()),
188            txn: Some(common::types::cardano::txn_index::TxnIndex::example()),
189            payment_address: None,
190            is_payable: false.into(),
191            cip15: true.into(),
192            errors: Some(
193                common::objects::generic::problem_report::ProblemReport::from(problem_report),
194            ),
195        }
196    }
197}