Skip to content

Commit

Permalink
auction: define schedule action and AH validation scaffold (#4210)
Browse files Browse the repository at this point in the history
## Describe your changes

Create the action definition module and adds the
`ActionDutchAuctionSchedule` domain + pb message.

## Issue ticket number and link

Part of #4206. 

## Checklist before requesting a review

- [x] If this code contains consensus-breaking changes, I have added the
"consensus-breaking" label. Otherwise, I declare my belief that there
are not consensus-breaking changes, for the following reason:

> Internal and the auction component is not hooked to the rest of the
app yet
  • Loading branch information
erwanor authored Apr 15, 2024
1 parent 2aa7094 commit 333e8db
Show file tree
Hide file tree
Showing 12 changed files with 363 additions and 2 deletions.
4 changes: 3 additions & 1 deletion crates/core/component/auction/src/auction/dutch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use penumbra_num::Amount;
use penumbra_proto::{core::component::auction::v1alpha1 as pb, DomainType};
use serde::{Deserialize, Serialize};

pub mod actions;

/// A deployed Dutch Auction, containing an immutable description
/// and stateful data about its current state.
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -47,7 +49,7 @@ impl TryFrom<pb::DutchAuction> for DutchAuction {
/* ********************************** */

/// A description of the immutable parts of a dutch auction.
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
#[serde(
try_from = "pb::DutchAuctionDescription",
into = "pb::DutchAuctionDescription"
Expand Down
40 changes: 40 additions & 0 deletions crates/core/component/auction/src/auction/dutch/actions/end.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use anyhow::anyhow;
use penumbra_proto::{core::component::auction::v1alpha1 as pb, DomainType};
use serde::{Deserialize, Serialize};

use crate::auction::id::AuctionId;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(
try_from = "pb::ActionDutchAuctionEnd",
into = "pb::ActionDutchAuctionEnd"
)]
pub struct ActionDutchAuctionEnd {
pub auction_id: AuctionId,
}

/* Protobuf impls */
impl DomainType for ActionDutchAuctionEnd {
type Proto = pb::ActionDutchAuctionEnd;
}

impl From<ActionDutchAuctionEnd> for pb::ActionDutchAuctionEnd {
fn from(domain: ActionDutchAuctionEnd) -> Self {
pb::ActionDutchAuctionEnd {
auction_id: Some(domain.auction_id.into()),
}
}
}

impl TryFrom<pb::ActionDutchAuctionEnd> for ActionDutchAuctionEnd {
type Error = anyhow::Error;

fn try_from(msg: pb::ActionDutchAuctionEnd) -> Result<Self, Self::Error> {
Ok(ActionDutchAuctionEnd {
auction_id: msg
.auction_id
.ok_or_else(|| anyhow!("ActionDutchAuctionEnd message is missing an auction_id"))?
.try_into()?,
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod schedule;
pub use schedule::ActionDutchAuctionSchedule;

pub mod end;
pub use end::ActionDutchAuctionEnd;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::auction::dutch::DutchAuctionDescription;
use anyhow::anyhow;
use penumbra_proto::{core::component::auction::v1alpha1 as pb, DomainType};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(
try_from = "pb::ActionDutchAuctionSchedule",
into = "pb::ActionDutchAuctionSchedule"
)]
pub struct ActionDutchAuctionSchedule {
pub description: DutchAuctionDescription,
}

/* Protobuf impls */
impl DomainType for ActionDutchAuctionSchedule {
type Proto = pb::ActionDutchAuctionSchedule;
}

impl From<ActionDutchAuctionSchedule> for pb::ActionDutchAuctionSchedule {
fn from(domain: ActionDutchAuctionSchedule) -> Self {
pb::ActionDutchAuctionSchedule {
description: Some(domain.description.into()),
}
}
}

impl TryFrom<pb::ActionDutchAuctionSchedule> for ActionDutchAuctionSchedule {
type Error = anyhow::Error;

fn try_from(msg: pb::ActionDutchAuctionSchedule) -> Result<Self, Self::Error> {
Ok(ActionDutchAuctionSchedule {
description: msg
.description
.ok_or_else(|| {
anyhow!("ActionDutchAuctionSchedule message is missing a description")
})?
.try_into()?,
})
}
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
// use cnidarium_component::ActionHandler;
pub mod dutch;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use anyhow::Result;
use async_trait::async_trait;
use cnidarium::StateWrite;
use cnidarium_component::ActionHandler;

use crate::auction::dutch::actions::ActionDutchAuctionEnd;

#[async_trait]
impl ActionHandler for ActionDutchAuctionEnd {
type CheckStatelessContext = ();
async fn check_stateless(&self, _context: ()) -> Result<()> {
Ok(())
}

async fn check_and_execute<S: StateWrite>(&self, mut _state: S) -> Result<()> {
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod end;
mod schedule;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use anyhow::Result;
use async_trait::async_trait;
use cnidarium::StateWrite;
use cnidarium_component::ActionHandler;

use crate::auction::dutch::actions::ActionDutchAuctionSchedule;

#[async_trait]
impl ActionHandler for ActionDutchAuctionSchedule {
type CheckStatelessContext = ();
async fn check_stateless(&self, _context: ()) -> Result<()> {
Ok(())
}

async fn check_and_execute<S: StateWrite>(&self, mut _state: S) -> Result<()> {
Ok(())
}
}
33 changes: 33 additions & 0 deletions crates/proto/src/gen/penumbra.core.component.auction.v1alpha1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,39 @@ impl ::prost::Name for DutchAuction {
)
}
}
/// Initiates a Dutch auction using protocol-controlled liquidity.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ActionDutchAuctionSchedule {
#[prost(message, optional, tag = "1")]
pub description: ::core::option::Option<DutchAuctionDescription>,
}
impl ::prost::Name for ActionDutchAuctionSchedule {
const NAME: &'static str = "ActionDutchAuctionSchedule";
const PACKAGE: &'static str = "penumbra.core.component.auction.v1alpha1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!(
"penumbra.core.component.auction.v1alpha1.{}", Self::NAME
)
}
}
/// Terminate the auction associated with the specified `auction_id`
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ActionDutchAuctionEnd {
/// The auction to end.
#[prost(message, optional, tag = "1")]
pub auction_id: ::core::option::Option<AuctionId>,
}
impl ::prost::Name for ActionDutchAuctionEnd {
const NAME: &'static str = "ActionDutchAuctionEnd";
const PACKAGE: &'static str = "penumbra.core.component.auction.v1alpha1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!(
"penumbra.core.component.auction.v1alpha1.{}", Self::NAME
)
}
}
/// Generated client implementations.
#[cfg(feature = "rpc")]
pub mod query_service_client {
Expand Down
191 changes: 191 additions & 0 deletions crates/proto/src/gen/penumbra.core.component.auction.v1alpha1.serde.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,194 @@
impl serde::Serialize for ActionDutchAuctionEnd {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut len = 0;
if self.auction_id.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.core.component.auction.v1alpha1.ActionDutchAuctionEnd", len)?;
if let Some(v) = self.auction_id.as_ref() {
struct_ser.serialize_field("auctionId", v)?;
}
struct_ser.end()
}
}
impl<'de> serde::Deserialize<'de> for ActionDutchAuctionEnd {
#[allow(deprecated)]
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &[
"auction_id",
"auctionId",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
AuctionId,
__SkipField__,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct GeneratedVisitor;

impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = GeneratedField;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "expected one of: {:?}", &FIELDS)
}

#[allow(unused_variables)]
fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
where
E: serde::de::Error,
{
match value {
"auctionId" | "auction_id" => Ok(GeneratedField::AuctionId),
_ => Ok(GeneratedField::__SkipField__),
}
}
}
deserializer.deserialize_identifier(GeneratedVisitor)
}
}
struct GeneratedVisitor;
impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = ActionDutchAuctionEnd;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("struct penumbra.core.component.auction.v1alpha1.ActionDutchAuctionEnd")
}

fn visit_map<V>(self, mut map_: V) -> std::result::Result<ActionDutchAuctionEnd, V::Error>
where
V: serde::de::MapAccess<'de>,
{
let mut auction_id__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::AuctionId => {
if auction_id__.is_some() {
return Err(serde::de::Error::duplicate_field("auctionId"));
}
auction_id__ = map_.next_value()?;
}
GeneratedField::__SkipField__ => {
let _ = map_.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(ActionDutchAuctionEnd {
auction_id: auction_id__,
})
}
}
deserializer.deserialize_struct("penumbra.core.component.auction.v1alpha1.ActionDutchAuctionEnd", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for ActionDutchAuctionSchedule {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut len = 0;
if self.description.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.core.component.auction.v1alpha1.ActionDutchAuctionSchedule", len)?;
if let Some(v) = self.description.as_ref() {
struct_ser.serialize_field("description", v)?;
}
struct_ser.end()
}
}
impl<'de> serde::Deserialize<'de> for ActionDutchAuctionSchedule {
#[allow(deprecated)]
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &[
"description",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
Description,
__SkipField__,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
where
D: serde::Deserializer<'de>,
{
struct GeneratedVisitor;

impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = GeneratedField;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "expected one of: {:?}", &FIELDS)
}

#[allow(unused_variables)]
fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
where
E: serde::de::Error,
{
match value {
"description" => Ok(GeneratedField::Description),
_ => Ok(GeneratedField::__SkipField__),
}
}
}
deserializer.deserialize_identifier(GeneratedVisitor)
}
}
struct GeneratedVisitor;
impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = ActionDutchAuctionSchedule;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("struct penumbra.core.component.auction.v1alpha1.ActionDutchAuctionSchedule")
}

fn visit_map<V>(self, mut map_: V) -> std::result::Result<ActionDutchAuctionSchedule, V::Error>
where
V: serde::de::MapAccess<'de>,
{
let mut description__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::Description => {
if description__.is_some() {
return Err(serde::de::Error::duplicate_field("description"));
}
description__ = map_.next_value()?;
}
GeneratedField::__SkipField__ => {
let _ = map_.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(ActionDutchAuctionSchedule {
description: description__,
})
}
}
deserializer.deserialize_struct("penumbra.core.component.auction.v1alpha1.ActionDutchAuctionSchedule", FIELDS, GeneratedVisitor)
}
}
impl serde::Serialize for AuctionId {
#[allow(deprecated)]
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
Expand Down
Binary file modified crates/proto/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
Loading

0 comments on commit 333e8db

Please sign in to comment.