anya-core 1.2.0

Enterprise-grade Bitcoin Infrastructure Platform
Documentation
use std::error::Error;
// src/bitcoin/dlc/contract.rs

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};

/// Represents the current state of a contract
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContractState {
    /// Contract is being drafted
    Draft,
    
    /// Contract has been offered to counterparty
    Offered,
    
    /// Contract has been accepted by counterparty
    Accepted,
    
    /// Contract has been signed by all parties
    Signed,
    
    /// Contract has been funded with a funding transaction
    Funded,
    
    /// Contract has been executed (outcome determined)
    Executed,
    
    /// Contract has been closed
    Closed,
    
    /// Contract has been refunded (after timeout)
    Refunded,
    
    /// Contract has an error
    Error(String),
}

/// Describes a DLC contract with all necessary parameters
#[derive(Debug, Clone)]
pub struct Contract {
    /// Unique identifier for the contract
    pub id: String,
    
    /// Contract descriptor with terms
    pub descriptor: ContractDescriptor,
    
    /// Current state of the contract
    pub state: ContractState,
    
    /// Timestamp when the contract was created
    pub created_at: DateTime<Utc>,
    
    /// Timestamp when the contract was last updated
    pub updated_at: DateTime<Utc>,
    
    /// Transaction ID of the funding transaction
    pub funding_txid: Option<Txid>,
    
    /// Transaction ID of the execution transaction
    pub execution_txid: Option<Txid>,
    
    /// Transaction ID of the refund transaction
    pub refund_txid: Option<Txid>,
    
    /// Oracle announcements for this contract
    pub oracle_announcements: Vec<OracleAnnouncement>,
    
    /// Computed contract execution paths
    pub execution_paths: HashMap<String, ContractExecutionPath>,
    
    /// Additional contract metadata
    pub metadata: HashMap<String, String>,
}

impl Contract {
    /// Creates a new contract from the given parameters
    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(),
        }
    }
    
    /// Validates that the contract is well-formed
    pub fn validate(&self) -> AnyaResult<()>  -> Result<(), Box<dyn Error>> {
        // Check if the contract has valid parameters
        // Implementation goes here
        Ok(())
    }
    
    /// Adds an oracle announcement to the contract
    pub fn add_oracle_announcement(&mut self, announcement: OracleAnnouncement)  -> Result<(), Box<dyn Error>> {
        self.oracle_announcements.push(announcement);
        self.updated_at = Utc::now();
    }
    
    /// Updates the state of the contract
    pub fn update_state(&mut self, new_state: ContractState)  -> Result<(), Box<dyn Error>> {
        self.state = new_state;
        self.updated_at = Utc::now();
    }
    
    /// Checks if the contract is ready for execution
    pub fn is_ready_for_execution(&self) -> bool  -> Result<(), Box<dyn Error>> {
        self.state == ContractState::Funded && !self.oracle_announcements.is_empty()
    }
    
    /// Gets the total collateral amount in satoshis
    pub fn total_collateral(&self) -> u64  -> Result<(), Box<dyn Error>> {
        self.descriptor.offer_collateral + self.descriptor.accept_collateral
    }
}

/// Represents the descriptor of a contract with all its terms
#[derive(Debug, Clone)]
pub struct ContractDescriptor {
    /// Title of the contract
    pub title: String,
    
    /// Description of the contract
    pub description: String,
    
    /// Public key of the offering party
    pub offer_public_key: PublicKey,
    
    /// Collateral amount in satoshis by the offering party
    pub offer_collateral: u64,
    
    /// Public key of the accepting party
    pub accept_public_key: Option<PublicKey>,
    
    /// Collateral amount in satoshis by the accepting party
    pub accept_collateral: u64,
    
    /// Fee rate in sat/vbyte
    pub fee_rate: f64,
    
    /// Locktime block height for the refund
    pub refund_locktime: u32,
    
    /// Payout function defining how funds should be distributed
    pub payout_function: PayoutFunction,
    
    /// Oracle information for this contract
    pub oracle_info: Vec<OracleInfo>,
}

/// Represents a DLC execution path with associated CET
#[derive(Debug, Clone)]
pub struct ContractExecutionPath {
    /// Outcome value
    pub outcome: String,
    
    /// CET transaction (hex)
    pub cet_hex: String,
    
    /// Offering party payout amount
    pub offer_payout: u64,
    
    /// Accepting party payout amount
    pub accept_payout: u64,
}

/// Defines how funds should be distributed based on oracle outcomes
#[derive(Debug, Clone)]
pub enum PayoutFunction {
    /// Binary outcome (win/lose)
    Binary {
        /// The winning condition description
        win_condition: String,
        
        /// The offer party winning amount (sats)
        offer_win_amount: u64,
        
        /// The accept party winning amount (sats)
        accept_win_amount: u64,
    },
    
    /// Numeric outcome within a range
    Numeric {
        /// Unit of the numeric value
        unit: String,
        
        /// Range of possible values
        range: (i64, i64),
        
        /// Payout curve points: (outcome_value, offer_payout_percentage)
        /// Accept party gets 100% - offer_payout_percentage
        curve_points: Vec<(i64, u8)>,
    },
    
    /// Enumerated outcomes with specific payouts
    Enumerated {
        /// Map of outcome -> (offer_payout, accept_payout) in sats
        outcomes: HashMap<String, (u64, u64)>,
    },
}

/// Parameters for creating a new contract
#[derive(Debug, Clone)]
pub struct ContractParameters {
    /// Title of the contract
    pub title: String,
    
    /// Description of the contract
    pub description: String,
    
    /// Amount (in sats) offered as collateral
    pub offer_collateral: u64,
    
    /// Amount (in sats) required from counterparty
    pub accept_collateral: u64,
    
    /// Payout function
    pub payout_function: PayoutFunction,
    
    /// Oracle URLs to use
    pub oracle_urls: Vec<String>,
    
    /// Timelock for refund in blocks
    pub refund_locktime: Option<u32>,
    
    /// Fee rate in sat/vbyte
    pub fee_rate: Option<f64>,
    
    /// Additional metadata
    pub metadata: HashMap<String, String>,
}