use crate::client::{ApiError, Transport, info, info_request};
use crate::deploy::outcomes::actions::{Fraction, Settlement};
use crate::markets::outcomes::coin::Coin;
use crate::utils::{Address, Dec, OutcomeSide};
use serde::Deserialize;
#[must_use]
pub fn outcome_meta_request() -> String {
info_request("outcomeMeta", &[])
}
pub async fn outcome_meta(transport: &impl Transport) -> Result<OutcomeMeta, ApiError> {
info(transport, outcome_meta_request()).await
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OutcomeMeta {
#[serde(default)]
pub outcomes: Vec<Outcome>,
#[serde(default)]
pub questions: Vec<Question>,
#[serde(default)]
pub deployers: Vec<Deployer>,
#[serde(default)]
pub fee_scale: Option<Dec>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Outcome {
pub outcome: u32,
#[serde(default)]
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub side_specs: Vec<SideSpec>,
#[serde(default)]
pub quote_token: Option<String>,
#[serde(default)]
pub venue: Option<String>,
#[serde(default)]
pub deployer_fee_scale: Option<Dec>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct SideSpec {
#[serde(default)]
pub name: String,
}
impl Outcome {
#[must_use]
pub const fn coin(&self, side: OutcomeSide) -> Coin {
Coin::new(self.outcome, side)
}
#[must_use]
pub fn settlement(&self, fraction: Fraction) -> Option<Settlement> {
let [first, second] = self.side_specs.as_slice() else {
return None;
};
Some(Settlement {
outcome: self.outcome,
fraction,
name: self.name.clone(),
description: self.description.clone(),
sides: [first.name.clone(), second.name.clone()],
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Question {
pub question: u32,
#[serde(default)]
pub name: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub fallback_outcome: Option<u32>,
#[serde(default)]
pub named_outcomes: Vec<u32>,
#[serde(default)]
pub settled_named_outcomes: Vec<u32>,
}
impl Question {
pub fn unsettled(&self) -> impl Iterator<Item = u32> + '_ {
self.named_outcomes.iter().copied().filter(|outcome| !self.settled_named_outcomes.contains(outcome))
}
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Deployer {
pub deployer: Address,
#[serde(default)]
pub venue: Option<String>,
#[serde(default)]
pub sub_deployers: Vec<(String, Vec<Address>)>,
}
impl OutcomeMeta {
#[must_use]
pub fn outcome(&self, outcome: u32) -> Option<&Outcome> {
self.outcomes.iter().find(|listed| listed.outcome == outcome)
}
#[must_use]
pub fn question(&self, question: u32) -> Option<&Question> {
self.questions.iter().find(|listed| listed.question == question)
}
#[must_use]
pub fn question_of(&self, outcome: u32) -> Option<&Question> {
self.questions
.iter()
.find(|question| question.fallback_outcome == Some(outcome) || question.named_outcomes.contains(&outcome))
}
#[must_use]
pub fn deployer(&self, venue: &str) -> Option<&Deployer> {
self.deployers.iter().find(|deployer| deployer.venue.as_deref() == Some(venue))
}
}
#[cfg(test)]
#[path = "tests/meta.rs"]
mod tests;