Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add poem openapi Proposal and Ballot types implementation | NPG-8147 #579

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8b8b275
add health tests
Mr-Leshiy Sep 12, 2023
d20c45a
refactor
Mr-Leshiy Sep 12, 2023
27e596a
add get_voter endpoint
Mr-Leshiy Sep 12, 2023
98fa4e0
update
Mr-Leshiy Sep 12, 2023
ba891e3
fix
Mr-Leshiy Sep 12, 2023
d4ba8cb
add tests
Mr-Leshiy Sep 12, 2023
7ecff29
fix clippy
Mr-Leshiy Sep 12, 2023
d3147f9
return back Responses sections
Mr-Leshiy Sep 14, 2023
6499a49
update
Mr-Leshiy Sep 14, 2023
ed2939d
update
Mr-Leshiy Sep 14, 2023
b42867c
fix visibility
Mr-Leshiy Sep 18, 2023
bced403
fix
Mr-Leshiy Sep 18, 2023
6a8f3f4
update
Mr-Leshiy Sep 18, 2023
aed00f9
move axum types under the legacy_service module
Mr-Leshiy Sep 18, 2023
544e153
add `/delegations/` endpoint
Mr-Leshiy Sep 13, 2023
e41c497
add event types
Mr-Leshiy Sep 13, 2023
452aa3b
update
Mr-Leshiy Sep 13, 2023
5be6fd6
add Objective types
Mr-Leshiy Sep 13, 2023
94df3a3
add Proposal types
Mr-Leshiy Sep 13, 2023
727bf99
add reviews types
Mr-Leshiy Sep 13, 2023
260f683
add ballot types
Mr-Leshiy Sep 13, 2023
b3d02a2
fixes
Mr-Leshiy Sep 13, 2023
1f85f82
update
Mr-Leshiy Sep 13, 2023
4738b03
add objective summary and other types
Mr-Leshiy Sep 18, 2023
82ec594
add reward definition type
Mr-Leshiy Sep 18, 2023
9f969a6
add objective
Mr-Leshiy Sep 19, 2023
fe33350
Merge branch 'feature/poem-migration-start' into feature/poem-types
Mr-Leshiy Sep 19, 2023
2628a13
update
Mr-Leshiy Sep 19, 2023
3ffb57a
add docs
Mr-Leshiy Sep 19, 2023
e514e6a
update
Mr-Leshiy Sep 19, 2023
67b148f
update voting_token docs
Mr-Leshiy Sep 19, 2023
0d133bc
remove poem_types::objective module
Mr-Leshiy Sep 19, 2023
9745836
fix fmt
Mr-Leshiy Sep 19, 2023
6a8b0d9
remove poem_types module
Mr-Leshiy Sep 25, 2023
100fa19
fix clippy
Mr-Leshiy Sep 25, 2023
5d4651b
add proposal types
Mr-Leshiy Sep 26, 2023
d188702
fixes, add voteplan and ballot_type
Mr-Leshiy Sep 26, 2023
16a252c
add Ballot type
Mr-Leshiy Sep 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/cat-data-service/src/legacy_service/types/objective.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::SerdeType;
use event_db::types::{
objective::{
Objective, ObjectiveDetails, ObjectiveId, ObjectiveSummary, ObjectiveType, RewardDefintion,
VoterGroup,
Objective, ObjectiveDetails, ObjectiveId, ObjectiveSummary, ObjectiveType,
RewardDefinition, VoterGroup,
},
registration::VoterGroupId,
};
Expand Down Expand Up @@ -97,7 +97,7 @@ impl Serialize for SerdeType<ObjectiveSummary> {
}
}

impl Serialize for SerdeType<&RewardDefintion> {
impl Serialize for SerdeType<&RewardDefinition> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
Expand All @@ -115,7 +115,7 @@ impl Serialize for SerdeType<&RewardDefintion> {
}
}

impl Serialize for SerdeType<RewardDefintion> {
impl Serialize for SerdeType<RewardDefinition> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
Expand Down Expand Up @@ -162,7 +162,7 @@ impl Serialize for SerdeType<&ObjectiveDetails> {
struct ObjectiveDetailsSerde<'a> {
groups: Vec<SerdeType<&'a VoterGroup>>,
#[serde(skip_serializing_if = "Option::is_none")]
reward: Option<SerdeType<&'a RewardDefintion>>,
reward: Option<SerdeType<&'a RewardDefinition>>,
#[serde(skip_serializing_if = "Option::is_none")]
supplemental: &'a Option<Value>,
}
Expand Down Expand Up @@ -284,7 +284,7 @@ mod tests {

#[test]
fn reward_definition_json_test() {
let reward_definition = SerdeType(RewardDefintion {
let reward_definition = SerdeType(RewardDefinition {
currency: "ADA".to_string(),
value: 100,
});
Expand Down Expand Up @@ -327,7 +327,7 @@ mod tests {
group: Some(VoterGroupId("group".to_string())),
voting_token: Some("token".to_string()),
}],
reward: Some(RewardDefintion {
reward: Some(RewardDefinition {
currency: "ADA".to_string(),
value: 100,
}),
Expand Down Expand Up @@ -373,7 +373,7 @@ mod tests {
group: Some(VoterGroupId("group".to_string())),
voting_token: Some("token".to_string()),
}],
reward: Some(RewardDefintion {
reward: Some(RewardDefinition {
currency: "ADA".to_string(),
value: 100,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ impl Serialize for SerdeType<&RewardAddress> {
reward_payable: bool,
}
RewardAddressSerde {
reward_address: self.reward_address(),
reward_address: &self.reward_address(),
reward_payable: self.reward_payable(),
}
.serialize(serializer)
Expand Down
3 changes: 3 additions & 0 deletions src/cat-data-service/src/service/api/health/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! Health endpoints, which return the status of the service.
//! Mostly used by Grafana.
//!
use crate::service::common::tags::ApiTags;
use poem_openapi::OpenApi;

Expand Down
12 changes: 7 additions & 5 deletions src/cat-data-service/src/service/api/registration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Registration endpoints, which return relevant voter's registration information.
//!
use crate::service::common::objects::{
event_id::EventId, voter_registration::VoterRegistration, voting_public_key::VotingPublicKey,
};
Expand All @@ -19,11 +21,6 @@ pub(crate) struct RegistrationApi;

#[OpenApi(prefix_path = "/registration", tag = "ApiTags::Registration")]
impl RegistrationApi {
#[oai(
path = "/voter/:voting_key",
method = "get",
operation_id = "getVoterInfo"
)]
/// Voter's info
///
/// Get the voter's registration and voting power by their Public Voting Key.
Expand All @@ -32,6 +29,11 @@ impl RegistrationApi {
/// If the `event_id` query parameter is omitted, then the latest voting power is retrieved.
/// If the `with_delegators` query parameter is ommitted, then `delegator_addresses` field of `VoterInfo` type does not provided.
///
#[oai(
path = "/voter/:voting_key",
method = "get",
operation_id = "getVoterInfo"
)]
async fn get_voter_info(
&self,
pool: Data<&Arc<State>>,
Expand Down
44 changes: 44 additions & 0 deletions src/cat-data-service/src/service/common/objects/ballot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! Defines the Ballot type.
//!
use super::vote_plan::VotePlan;
use poem_openapi::{types::Example, Object};

/// Details necessary to complete a ballot for the specific proposal and objective.
#[derive(Object)]
#[oai(example = true)]
pub struct Ballot {
/// Ballot Choices present for all proposals in this Objective.
///
/// Ordered list of choices available for all proposals in this Objective.
/// The offset into the array is the index of the choice.
choices: Vec<String>,

/// List of groups and the voteplans they use when voting on this proposal.
/// Each valid group for this Objective:
/// * Must be listed.
/// * Must not be repeated.
voteplans: Vec<VotePlan>,
}

impl Example for Ballot {
fn example() -> Self {
Self {
choices: vec!["yes".to_string(), "no".to_string(), "abstain".to_string()],
voteplans: vec![VotePlan::example()],
}
}
}

impl TryFrom<event_db::types::ballot::Ballot> for Ballot {
type Error = String;
fn try_from(value: event_db::types::ballot::Ballot) -> Result<Self, Self::Error> {
let mut voteplans = Vec::new();
for voteplan in value.voteplans.0 {
voteplans.push(voteplan.try_into()?);
}
Ok(Self {
choices: value.choices.0,
voteplans,
})
}
}
37 changes: 37 additions & 0 deletions src/cat-data-service/src/service/common/objects/ballot_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Defines the ballot type.
//!
use poem_openapi::{types::Example, Enum};

/// The kind of ballot to be cast on this Objective.
#[derive(Enum)]
pub(crate) enum BallotType {
/// All Ballots are public when cast.
#[oai(rename = "public")]
Public,

/// All Ballots are private.
#[oai(rename = "private")]
Private,

/// All Ballots are cast privately but become public after the tally.
#[oai(rename = "cast-private")]
CastPrivate,
}

impl Example for BallotType {
fn example() -> Self {
Self::Public
}
}

impl TryFrom<event_db::types::ballot::BallotType> for BallotType {
type Error = String;
fn try_from(value: event_db::types::ballot::BallotType) -> Result<Self, Self::Error> {
match value.0.as_str() {
"public" => Ok(Self::Public),
"private" => Ok(Self::Private),
"cast-private" => Ok(Self::CastPrivate),
_ => Err(format!("Unknown ballot type: {}", value.0)),
}
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
//! Define the Public Key used by a Delegate.
//! Defines the Public Key used by a Delegate.
//!
use poem_openapi::{types::Example, Object};

/// A Delegate Public ED25519 Key (as registered in their most recent valid
/// [CIP-36](https://cips.cardano.org/cips/cip36) registration).
#[derive(Object)]
#[oai(example = true)]
pub(crate) struct DelegePublicKey {
pub(crate) struct DelegatePublicKey {
#[oai(validator(pattern = "0x[0-9a-f]{64}"))]
address: String,
}

impl From<String> for DelegePublicKey {
impl From<String> for DelegatePublicKey {
fn from(address: String) -> Self {
Self { address }
}
}

impl Example for DelegePublicKey {
impl Example for DelegatePublicKey {
fn example() -> Self {
Self {
address: "0xad4b948699193634a39dd56f779a2951a24779ad52aa7916f6912b8ec4702cee"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Define the ID of an Event
//! Defines the ID of an Event.
//!
use poem_openapi::{types::Example, NewType};
use serde::Deserialize;
Expand Down
19 changes: 18 additions & 1 deletion src/cat-data-service/src/service/common/objects/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
//! This module contains common and re-usable objects.
pub(crate) mod delege_public_key;
pub(crate) mod ballot;
pub(crate) mod ballot_type;
pub(crate) mod delegate_public_key;
pub(crate) mod event_id;
pub(crate) mod objective;
pub(crate) mod objective_details;
pub(crate) mod objective_id;
pub(crate) mod objective_summary;
pub(crate) mod objective_type;
pub(crate) mod objective_types;
pub(crate) mod proposal;
pub(crate) mod proposal_details;
pub(crate) mod proposal_id;
pub(crate) mod proposal_summary;
pub(crate) mod proposer_details;
pub(crate) mod reward_currency;
pub(crate) mod reward_definition;
pub(crate) mod stake_public_key;
pub(crate) mod vote_plan;
pub(crate) mod voter_group;
pub(crate) mod voter_group_id;
pub(crate) mod voter_info;
pub(crate) mod voter_registration;
Expand Down
33 changes: 33 additions & 0 deletions src/cat-data-service/src/service/common/objects/objective.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//! Defines the full objective information.
//!
use super::{objective_details::ObjectiveDetails, objective_summary::ObjectiveSummary};
use poem_openapi::{types::Example, Object};

/// Full Objective info.
#[derive(Object)]
#[oai(example = true)]
pub(crate) struct Objective {
#[oai(flatten)]
summary: ObjectiveSummary,
#[oai(flatten)]
details: ObjectiveDetails,
}

impl Example for Objective {
fn example() -> Self {
Self {
summary: ObjectiveSummary::example(),
details: ObjectiveDetails::example(),
}
}
}

impl TryFrom<event_db::types::objective::Objective> for Objective {
type Error = String;
fn try_from(value: event_db::types::objective::Objective) -> Result<Self, Self::Error> {
Ok(Self {
summary: value.summary.try_into()?,
details: value.details.try_into()?,
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! Defines the objective details.
//!
use super::{reward_definition::RewardDefiniton, voter_group::VoterGroup};
use poem_openapi::{types::Example, Object};
use serde_json::Value;

#[derive(Object)]
#[oai(example = true)]
pub(crate) struct ObjectiveDetails {
/// The valid voter groups for this voting event.
groups: Vec<VoterGroup>,

/// The Total Reward being offered for this Objective.
/// Distribution of the Reward is determined under the rules of this Objective.
/// If this field is not present there is no reward being offered for the Objective.
#[oai(skip_serializing_if_is_none = true)]
reward: Option<RewardDefiniton>,

/// Objective Supplemental Data
///
/// Extra Data which can be used to enrich the information shared about the Objective.
/// All Information here is optional.
/// If there is no supplemental information for the Objective this field is omitted.
#[oai(skip_serializing_if_is_none = true)]
supplemental: Option<Value>,
}

impl Example for ObjectiveDetails {
fn example() -> Self {
Self {
groups: vec![VoterGroup::example()],
reward: Some(RewardDefiniton::example()),
supplemental: None,
}
}
}

impl TryFrom<event_db::types::objective::ObjectiveDetails> for ObjectiveDetails {
type Error = String;
fn try_from(value: event_db::types::objective::ObjectiveDetails) -> Result<Self, Self::Error> {
let mut groups = Vec::new();
for group in value.groups {
groups.push(group.try_into()?);
}
let reward = if let Some(reward) = value.reward {
Some(reward.try_into()?)
} else {
None
};
Ok(Self {
groups,
reward,
supplemental: value.supplemental,
})
}
}
21 changes: 21 additions & 0 deletions src/cat-data-service/src/service/common/objects/objective_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Defines the ID of an objective.
//!
use poem_openapi::{types::Example, NewType};
use serde::Deserialize;

/// The Numeric ID of an Objective to be decided in a Voting Event.
#[derive(NewType, Deserialize)]
#[oai(example = true)]
pub(crate) struct ObjectiveId(i32);

impl Example for ObjectiveId {
fn example() -> Self {
Self(1)
}
}

impl From<event_db::types::objective::ObjectiveId> for ObjectiveId {
fn from(value: event_db::types::objective::ObjectiveId) -> Self {
Self(value.0)
}
}
Loading