use std::error::Error;
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use bitcoin::Txid;
use bitcoin::secp256k1::PublicKey;
use crate::common::error::AnyaResult;
use super::oracle::{OracleInfo, OracleAnnouncement};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContractState {
Draft,
Offered,
Accepted,
Signed,
Funded,
Executed,
Closed,
Refunded,
Error(String),
}
#[derive(Debug, Clone)]
pub struct Contract {
pub id: String,
pub descriptor: ContractDescriptor,
pub state: ContractState,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub funding_txid: Option<Txid>,
pub execution_txid: Option<Txid>,
pub refund_txid: Option<Txid>,
pub oracle_announcements: Vec<OracleAnnouncement>,
pub execution_paths: HashMap<String, ContractExecutionPath>,
pub metadata: HashMap<String, String>,
}
impl Contract {
pub fn new(descriptor: ContractDescriptor) -> Self -> Result<(), Box<dyn Error>> {
let id = uuid::Uuid::new_v4().to_string();
let now = Utc::now();
Self {
id,
descriptor,
state: ContractState::Draft,
created_at: now,
updated_at: now,
funding_txid: None,
execution_txid: None,
refund_txid: None,
oracle_announcements: Vec::new(),
execution_paths: HashMap::new(),
metadata: HashMap::new(),
}
}
pub fn validate(&self) -> AnyaResult<()> -> Result<(), Box<dyn Error>> {
Ok(())
}
pub fn add_oracle_announcement(&mut self, announcement: OracleAnnouncement) -> Result<(), Box<dyn Error>> {
self.oracle_announcements.push(announcement);
self.updated_at = Utc::now();
}
pub fn update_state(&mut self, new_state: ContractState) -> Result<(), Box<dyn Error>> {
self.state = new_state;
self.updated_at = Utc::now();
}
pub fn is_ready_for_execution(&self) -> bool -> Result<(), Box<dyn Error>> {
self.state == ContractState::Funded && !self.oracle_announcements.is_empty()
}
pub fn total_collateral(&self) -> u64 -> Result<(), Box<dyn Error>> {
self.descriptor.offer_collateral + self.descriptor.accept_collateral
}
}
#[derive(Debug, Clone)]
pub struct ContractDescriptor {
pub title: String,
pub description: String,
pub offer_public_key: PublicKey,
pub offer_collateral: u64,
pub accept_public_key: Option<PublicKey>,
pub accept_collateral: u64,
pub fee_rate: f64,
pub refund_locktime: u32,
pub payout_function: PayoutFunction,
pub oracle_info: Vec<OracleInfo>,
}
#[derive(Debug, Clone)]
pub struct ContractExecutionPath {
pub outcome: String,
pub cet_hex: String,
pub offer_payout: u64,
pub accept_payout: u64,
}
#[derive(Debug, Clone)]
pub enum PayoutFunction {
Binary {
win_condition: String,
offer_win_amount: u64,
accept_win_amount: u64,
},
Numeric {
unit: String,
range: (i64, i64),
curve_points: Vec<(i64, u8)>,
},
Enumerated {
outcomes: HashMap<String, (u64, u64)>,
},
}
#[derive(Debug, Clone)]
pub struct ContractParameters {
pub title: String,
pub description: String,
pub offer_collateral: u64,
pub accept_collateral: u64,
pub payout_function: PayoutFunction,
pub oracle_urls: Vec<String>,
pub refund_locktime: Option<u32>,
pub fee_rate: Option<f64>,
pub metadata: HashMap<String, String>,
}