-
Notifications
You must be signed in to change notification settings - Fork 305
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
auction: define main dutch auction messages (#4208)
## Describe your changes This PR adds the main domain types and protobuf definitions for dutch auction support. ## 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: > Component is not hooked to the app yet and this just adds messages/types. --------- Signed-off-by: Erwan Or <[email protected]> Co-authored-by: Henry de Valence <[email protected]> Co-authored-by: katelyn martin <[email protected]>
- Loading branch information
1 parent
2d9c784
commit 2aa7094
Showing
6 changed files
with
890 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pub mod dutch; | ||
pub mod id; | ||
pub mod nft; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
use anyhow::anyhow; | ||
use penumbra_asset::{asset, Value}; | ||
use penumbra_dex::lp::position::{self}; | ||
use penumbra_num::Amount; | ||
use penumbra_proto::{core::component::auction::v1alpha1 as pb, DomainType}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// A deployed Dutch Auction, containing an immutable description | ||
/// and stateful data about its current state. | ||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)] | ||
#[serde(try_from = "pb::DutchAuction", into = "pb::DutchAuction")] | ||
pub struct DutchAuction { | ||
pub description: DutchAuctionDescription, | ||
pub state: DutchAuctionState, | ||
} | ||
|
||
/* Protobuf impls for `DutchAuction` */ | ||
impl DomainType for DutchAuction { | ||
type Proto = pb::DutchAuction; | ||
} | ||
|
||
impl From<DutchAuction> for pb::DutchAuction { | ||
fn from(domain: DutchAuction) -> Self { | ||
pb::DutchAuction { | ||
description: Some(domain.description.into()), | ||
state: Some(domain.state.into()), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<pb::DutchAuction> for DutchAuction { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(msg: pb::DutchAuction) -> Result<Self, Self::Error> { | ||
Ok(DutchAuction { | ||
description: msg | ||
.description | ||
.ok_or_else(|| anyhow!("DutchAuction is missing description"))? | ||
.try_into()?, | ||
state: msg | ||
.state | ||
.ok_or_else(|| anyhow!("DutchAuction is missing a state field"))? | ||
.try_into()?, | ||
}) | ||
} | ||
} | ||
/* ********************************** */ | ||
|
||
/// A description of the immutable parts of a dutch auction. | ||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)] | ||
#[serde( | ||
try_from = "pb::DutchAuctionDescription", | ||
into = "pb::DutchAuctionDescription" | ||
)] | ||
pub struct DutchAuctionDescription { | ||
pub input: Value, | ||
pub output_id: asset::Id, | ||
pub max_output: Amount, | ||
pub min_output: Amount, | ||
pub start_height: u64, | ||
pub end_height: u64, | ||
pub step_count: u64, | ||
pub nonce: [u8; 32], | ||
} | ||
|
||
/* Protobuf impls */ | ||
impl DomainType for DutchAuctionDescription { | ||
type Proto = pb::DutchAuctionDescription; | ||
} | ||
|
||
impl From<DutchAuctionDescription> for pb::DutchAuctionDescription { | ||
fn from(domain: DutchAuctionDescription) -> Self { | ||
Self { | ||
input: Some(domain.input.into()), | ||
output_id: Some(domain.output_id.into()), | ||
max_output: Some(domain.max_output.into()), | ||
min_output: Some(domain.min_output.into()), | ||
start_height: domain.start_height, | ||
end_height: domain.end_height, | ||
step_count: domain.step_count, | ||
nonce: domain.nonce.as_slice().to_vec(), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<pb::DutchAuctionDescription> for DutchAuctionDescription { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(msg: pb::DutchAuctionDescription) -> Result<Self, Self::Error> { | ||
let d = DutchAuctionDescription { | ||
input: msg | ||
.input | ||
.ok_or_else(|| anyhow!("DutchAuctionDescription message is missing input"))? | ||
.try_into()?, | ||
output_id: msg | ||
.output_id | ||
.ok_or_else(|| { | ||
anyhow!("DutchAuctionDescription message is missing an output identifier") | ||
})? | ||
.try_into()?, | ||
max_output: msg | ||
.max_output | ||
.ok_or_else(|| anyhow!("DutchAuctionDescription message is missing max output"))? | ||
.try_into()?, | ||
min_output: msg | ||
.min_output | ||
.ok_or_else(|| anyhow!("DutchAuctionDescription message is missing min output"))? | ||
.try_into()?, | ||
start_height: msg.start_height, | ||
end_height: msg.end_height, | ||
step_count: msg.step_count, | ||
nonce: msg.nonce.as_slice().try_into()?, | ||
}; | ||
Ok(d) | ||
} | ||
} | ||
/* ********************************** */ | ||
|
||
/// A stateful description of a dutch auction, recording its state (via a sequence number), | ||
/// the current position id associated to it (if any), and its amount IO. | ||
/// # State | ||
/// We record the state of the dutch auction via an untyped `u64` instead of an enum. | ||
/// This futureproof support for auction types that have a richer state machine e.g. allows | ||
/// claiming a withdrawn auction multiple times, burning and minting a new withdrawn auction | ||
/// with an incremented sequence number. | ||
/// | ||
/// For Dutch auctions: | ||
/// | ||
/// ┌───┐ ┌───┐ ┌───┐ | ||
/// │ 0 │───Closed──▶│ 1 │──Withdrawn─▶│ 2 │ | ||
/// └───┘ └───┘ └───┘ | ||
/// ▲ | ||
/// │ | ||
/// Opened | ||
/// │ | ||
/// | ||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)] | ||
#[serde(try_from = "pb::DutchAuctionState", into = "pb::DutchAuctionState")] | ||
pub struct DutchAuctionState { | ||
pub sequence: u64, | ||
pub current_position: Option<position::Id>, | ||
pub next_trigger: u64, | ||
pub input_reserves: Amount, | ||
pub output_reserves: Amount, | ||
} | ||
|
||
/* Protobuf impls for `DutchAuctionState` */ | ||
impl DomainType for DutchAuctionState { | ||
type Proto = pb::DutchAuctionState; | ||
} | ||
|
||
impl From<DutchAuctionState> for pb::DutchAuctionState { | ||
fn from(domain: DutchAuctionState) -> Self { | ||
Self { | ||
seq: domain.sequence, | ||
current_position: domain.current_position.map(Into::into), | ||
next_trigger: domain.next_trigger, | ||
input_reserves: Some(domain.input_reserves.into()), | ||
output_reserves: Some(domain.output_reserves.into()), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<pb::DutchAuctionState> for DutchAuctionState { | ||
type Error = anyhow::Error; | ||
|
||
fn try_from(msg: pb::DutchAuctionState) -> Result<Self, Self::Error> { | ||
Ok(DutchAuctionState { | ||
sequence: msg.seq, | ||
current_position: msg.current_position.map(TryInto::try_into).transpose()?, | ||
next_trigger: msg.next_trigger, | ||
input_reserves: msg | ||
.input_reserves | ||
.ok_or_else(|| anyhow!("DutchAuctionState message is missing input reserves"))? | ||
.try_into()?, | ||
output_reserves: msg | ||
.output_reserves | ||
.ok_or_else(|| anyhow!("DutchAuctionState message is missing output reserves"))? | ||
.try_into()?, | ||
}) | ||
} | ||
} | ||
/* ********************************** */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.