qudag_exchange/
lib.rs

1//! # QuDAG Exchange
2//!
3//! A modular, quantum-secure, multi-agent resource exchange protocol that enables
4//! trustless computational resource trading through rUv (Resource Utilization Voucher) tokens.
5//!
6//! ## Overview
7//!
8//! QuDAG Exchange provides a decentralized marketplace for computational resources,
9//! allowing providers to offer CPU, GPU, memory, storage, and bandwidth in exchange
10//! for rUv tokens. The system uses post-quantum cryptography to ensure long-term
11//! security and integrates with QuDAG's DAG-based consensus for fast transaction finality.
12//!
13//! ## Features
14//!
15//! - **Quantum-Resistant Security**: Uses ML-DSA signatures and ML-KEM encryption
16//! - **Resource Trading**: Trade computational resources for rUv tokens
17//! - **DAG Consensus**: Fast finality with QR-Avalanche consensus
18//! - **Cross-Platform**: Native, WASM, and API support
19//! - **Secure Vault**: Encrypted key storage with QuDAG Vault integration
20//!
21//! ## Quick Start
22//!
23//! ```rust
24//! use qudag_exchange::{Exchange, Account, Transaction};
25//!
26//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
27//! // Create exchange instance
28//! let exchange = Exchange::new("mainnet").await?;
29//!
30//! // Create account
31//! let account = exchange.create_account("alice", "secure_password").await?;
32//!
33//! // Transfer tokens
34//! let tx = Transaction::builder()
35//!     .from(&account)
36//!     .to("qd1recipient...")
37//!     .amount(100.0)
38//!     .memo("Payment for resources")
39//!     .build()?;
40//!
41//! let result = exchange.submit_transaction(tx).await?;
42//! # Ok(())
43//! # }
44//! ```
45
46#![warn(missing_docs)]
47#![warn(rustdoc::missing_crate_level_docs)]
48
49use std::collections::HashMap;
50use std::sync::Arc;
51
52pub mod error;
53
54// Re-export from core
55pub use error::{ExchangeError as Error, Result};
56pub use qudag_exchange_core::*;
57
58/// The main exchange interface for interacting with the QuDAG Exchange network.
59///
60/// The `Exchange` struct provides methods for account management, transaction submission,
61/// resource trading, and network interaction. It handles all the complexity of
62/// quantum-resistant cryptography, consensus participation, and P2P networking.
63///
64/// # Examples
65///
66/// ## Creating an Exchange Instance
67///
68/// ```rust
69/// use qudag_exchange::Exchange;
70///
71/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
72/// // Connect to mainnet
73/// let exchange = Exchange::new("mainnet").await?;
74///
75/// // Connect to testnet with custom config
76/// let config = ExchangeConfig {
77///     network: "testnet".to_string(),
78///     data_dir: Some("/custom/path".into()),
79///     ..Default::default()
80/// };
81/// let exchange = Exchange::with_config(config).await?;
82/// # Ok(())
83/// # }
84/// ```
85#[derive(Clone)]
86pub struct Exchange {
87    inner: Arc<ExchangeInner>,
88}
89
90struct ExchangeInner {
91    network: String,
92    consensus: ConsensusAdapter,
93    ledger: Ledger,
94    config: ExchangeConfig,
95}
96
97impl Exchange {
98    /// Creates a new Exchange instance connected to the specified network.
99    ///
100    /// # Arguments
101    ///
102    /// * `network` - The network to connect to ("mainnet", "testnet", or "local")
103    ///
104    /// # Returns
105    ///
106    /// Returns a new `Exchange` instance or an error if initialization fails.
107    ///
108    /// # Examples
109    ///
110    /// ```rust
111    /// # use qudag_exchange::Exchange;
112    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
113    /// let exchange = Exchange::new("mainnet").await?;
114    /// # Ok(())
115    /// # }
116    /// ```
117    pub async fn new(network: &str) -> Result<Self> {
118        let config = ExchangeConfig {
119            network: network.to_string(),
120            ..Default::default()
121        };
122
123        Self::with_config(config).await
124    }
125
126    /// Creates a new Exchange instance with custom configuration.
127    ///
128    /// # Arguments
129    ///
130    /// * `config` - Custom configuration for the exchange
131    ///
132    /// # Returns
133    ///
134    /// Returns a configured `Exchange` instance or an error if initialization fails.
135    ///
136    /// # Examples
137    ///
138    /// ```rust
139    /// # use qudag_exchange::{Exchange, ExchangeConfig};
140    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
141    /// let config = ExchangeConfig {
142    ///     network: "testnet".to_string(),
143    ///     bootstrap_peers: vec!["/ip4/1.2.3.4/tcp/8080".to_string()],
144    ///     consensus_config: ConsensusConfig {
145    ///         sample_size: 20,
146    ///         quorum_size: 14,
147    ///         ..Default::default()
148    ///     },
149    ///     ..Default::default()
150    /// };
151    ///
152    /// let exchange = Exchange::with_config(config).await?;
153    /// # Ok(())
154    /// # }
155    /// ```
156    pub async fn with_config(config: ExchangeConfig) -> Result<Self> {
157        // Implementation details...
158        todo!()
159    }
160
161    /// Creates a new account with quantum-resistant keys.
162    ///
163    /// This method generates a new ML-DSA key pair, creates an account,
164    /// and securely stores the private key in the QuDAG Vault.
165    ///
166    /// # Arguments
167    ///
168    /// * `name` - A human-readable name for the account
169    /// * `password` - The password to encrypt the private key
170    ///
171    /// # Returns
172    ///
173    /// Returns the newly created `Account` or an error if creation fails.
174    ///
175    /// # Security
176    ///
177    /// The password is used to derive an encryption key using Argon2id.
178    /// The private key is encrypted with ChaCha20-Poly1305 before storage.
179    ///
180    /// # Examples
181    ///
182    /// ```rust
183    /// # use qudag_exchange::Exchange;
184    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
185    /// # let exchange = Exchange::new("testnet").await?;
186    /// let account = exchange.create_account("alice", "secure_password").await?;
187    /// println!("Account address: {}", account.address());
188    /// # Ok(())
189    /// # }
190    /// ```
191    pub async fn create_account(&self, name: &str, password: &str) -> Result<Account> {
192        // Implementation details...
193        todo!()
194    }
195
196    /// Retrieves the current balance for an account.
197    ///
198    /// # Arguments
199    ///
200    /// * `account` - The account ID or address to query
201    ///
202    /// # Returns
203    ///
204    /// Returns the current `Balance` including available, staked, and pending amounts.
205    ///
206    /// # Examples
207    ///
208    /// ```rust
209    /// # use qudag_exchange::Exchange;
210    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
211    /// # let exchange = Exchange::new("testnet").await?;
212    /// # let account = exchange.create_account("alice", "password").await?;
213    /// let balance = exchange.get_balance(&account).await?;
214    /// println!("Available: {} rUv", balance.available);
215    /// println!("Staked: {} rUv", balance.staked);
216    /// # Ok(())
217    /// # }
218    /// ```
219    pub async fn get_balance<A: Into<AccountId>>(&self, account: A) -> Result<Balance> {
220        // Implementation details...
221        todo!()
222    }
223
224    /// Submits a transaction to the network.
225    ///
226    /// The transaction is validated, signed (if not already signed),
227    /// and submitted to the consensus layer for processing.
228    ///
229    /// # Arguments
230    ///
231    /// * `transaction` - The transaction to submit
232    ///
233    /// # Returns
234    ///
235    /// Returns a `TransactionResult` containing the transaction ID and initial status.
236    ///
237    /// # Errors
238    ///
239    /// Returns an error if:
240    /// - The transaction is invalid (missing fields, invalid signature)
241    /// - The sender has insufficient balance
242    /// - Network submission fails
243    ///
244    /// # Examples
245    ///
246    /// ```rust
247    /// # use qudag_exchange::{Exchange, Transaction};
248    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
249    /// # let exchange = Exchange::new("testnet").await?;
250    /// # let account = exchange.create_account("alice", "password").await?;
251    /// let tx = Transaction::builder()
252    ///     .from(&account)
253    ///     .to("qd1recipient...")
254    ///     .amount(50.0)
255    ///     .build()?;
256    ///
257    /// let result = exchange.submit_transaction(tx).await?;
258    /// println!("Transaction ID: {}", result.transaction_id);
259    /// # Ok(())
260    /// # }
261    /// ```
262    pub async fn submit_transaction(&self, transaction: Transaction) -> Result<TransactionResult> {
263        // Implementation details...
264        todo!()
265    }
266
267    /// Waits for a transaction to be confirmed.
268    ///
269    /// This method blocks until the transaction reaches the specified
270    /// number of confirmations or times out.
271    ///
272    /// # Arguments
273    ///
274    /// * `tx_id` - The transaction ID to monitor
275    /// * `confirmations` - Number of confirmations required (default: 6)
276    ///
277    /// # Returns
278    ///
279    /// Returns the final `TransactionStatus` or an error if timeout/rejection occurs.
280    ///
281    /// # Examples
282    ///
283    /// ```rust
284    /// # use qudag_exchange::Exchange;
285    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
286    /// # let exchange = Exchange::new("testnet").await?;
287    /// # let tx_id = TransactionId::from("tx_123");
288    /// // Wait for 6 confirmations (default)
289    /// let status = exchange.wait_for_confirmation(&tx_id, None).await?;
290    ///
291    /// // Wait for 1 confirmation (faster but less secure)
292    /// let status = exchange.wait_for_confirmation(&tx_id, Some(1)).await?;
293    /// # Ok(())
294    /// # }
295    /// ```
296    pub async fn wait_for_confirmation(
297        &self,
298        tx_id: &TransactionId,
299        confirmations: Option<u32>,
300    ) -> Result<TransactionStatus> {
301        // Implementation details...
302        todo!()
303    }
304}
305
306/// Configuration options for the Exchange.
307///
308/// # Examples
309///
310/// ```rust
311/// use qudag_exchange::{ExchangeConfig, ConsensusConfig};
312///
313/// let config = ExchangeConfig {
314///     network: "mainnet".to_string(),
315///     data_dir: Some("/var/lib/qudag".into()),
316///     bootstrap_peers: vec![
317///         "/ip4/1.2.3.4/tcp/8080".to_string(),
318///         "/ip4/5.6.7.8/tcp/8080".to_string(),
319///     ],
320///     consensus_config: ConsensusConfig {
321///         sample_size: 20,
322///         quorum_size: 14,
323///         decision_threshold: 20,
324///         ..Default::default()
325///     },
326///     ..Default::default()
327/// };
328/// ```
329#[derive(Clone, Debug)]
330pub struct ExchangeConfig {
331    /// Network to connect to ("mainnet", "testnet", "local")
332    pub network: String,
333
334    /// Data directory for storage (defaults to platform-specific location)
335    pub data_dir: Option<std::path::PathBuf>,
336
337    /// Bootstrap peer addresses for initial connection
338    pub bootstrap_peers: Vec<String>,
339
340    /// Maximum number of peer connections
341    pub max_peers: usize,
342
343    /// Consensus configuration
344    pub consensus_config: ConsensusConfig,
345
346    /// Enable debug logging
347    pub debug: bool,
348}
349
350impl Default for ExchangeConfig {
351    fn default() -> Self {
352        Self {
353            network: "mainnet".to_string(),
354            data_dir: None,
355            bootstrap_peers: vec![],
356            max_peers: 50,
357            consensus_config: ConsensusConfig::default(),
358            debug: false,
359        }
360    }
361}
362
363/// Consensus configuration parameters.
364///
365/// These parameters control the behavior of the QR-Avalanche consensus protocol.
366///
367/// # Examples
368///
369/// ```rust
370/// use qudag_exchange::ConsensusConfig;
371/// use std::time::Duration;
372///
373/// let config = ConsensusConfig {
374///     sample_size: 20,        // Query 20 validators
375///     quorum_size: 14,        // Need 14 positive responses
376///     decision_threshold: 20,  // 20 consecutive successes to decide
377///     query_timeout: Duration::from_millis(500),
378///     ..Default::default()
379/// };
380/// ```
381#[derive(Clone, Debug)]
382pub struct ConsensusConfig {
383    /// Number of validators to query (k parameter)
384    pub sample_size: usize,
385
386    /// Quorum threshold for positive responses (α parameter)
387    pub quorum_size: usize,
388
389    /// Consecutive successes needed for decision (β parameter)
390    pub decision_threshold: u32,
391
392    /// Timeout for each query round
393    pub query_timeout: std::time::Duration,
394
395    /// Maximum time to wait for consensus
396    pub max_consensus_time: std::time::Duration,
397}
398
399impl Default for ConsensusConfig {
400    fn default() -> Self {
401        Self {
402            sample_size: 20,
403            quorum_size: 14,
404            decision_threshold: 20,
405            query_timeout: std::time::Duration::from_millis(500),
406            max_consensus_time: std::time::Duration::from_secs(30),
407        }
408    }
409}
410
411/// Result of a transaction submission.
412///
413/// Contains the transaction ID and initial status information.
414///
415/// # Examples
416///
417/// ```rust
418/// # use qudag_exchange::{Exchange, Transaction, TransactionResult};
419/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
420/// # let exchange = Exchange::new("testnet").await?;
421/// # let tx = Transaction::test_transaction();
422/// let result: TransactionResult = exchange.submit_transaction(tx).await?;
423///
424/// println!("Transaction ID: {}", result.transaction_id);
425/// println!("Initial status: {:?}", result.status);
426///
427/// if let Some(fee) = result.estimated_fee {
428///     println!("Estimated fee: {} rUv", fee);
429/// }
430/// # Ok(())
431/// # }
432/// ```
433#[derive(Debug, Clone)]
434pub struct TransactionResult {
435    /// Unique identifier for the transaction
436    pub transaction_id: TransactionId,
437
438    /// Initial status of the transaction
439    pub status: TransactionStatus,
440
441    /// Estimated fee (if calculable)
442    pub estimated_fee: Option<f64>,
443
444    /// Estimated confirmation time
445    pub estimated_confirmation_time: Option<std::time::Duration>,
446}
447
448/// Resource provider interface for offering computational resources.
449///
450/// The `Provider` struct manages resource offerings, pricing, and job execution
451/// for nodes that want to contribute resources to the network.
452///
453/// # Examples
454///
455/// ```rust
456/// use qudag_exchange::{Provider};
457///
458/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
459/// # let exchange = Exchange::new("testnet").await?;
460/// # let account = exchange.create_account("provider", "password").await?;
461/// let provider = Provider::builder()
462///     .account(&account)
463///     .build()?;
464///
465/// // Start providing resources
466/// provider.start().await?;
467/// # Ok(())
468/// # }
469/// ```
470pub struct Provider {
471    inner: Arc<ProviderInner>,
472}
473
474struct ProviderInner {
475    account: Account,
476    // TODO: Add resource specification types
477    // resources: Vec<ResourceSpec>,
478    // pricing: PricingStrategy,
479}
480
481impl Provider {
482    /// Creates a new provider builder.
483    ///
484    /// # Returns
485    ///
486    /// Returns a `ProviderBuilder` for configuring the provider.
487    ///
488    /// # Examples
489    ///
490    /// ```rust
491    /// # use qudag_exchange::Provider;
492    /// let builder = Provider::builder();
493    /// ```
494    pub fn builder() -> ProviderBuilder {
495        ProviderBuilder::new()
496    }
497
498    /// Starts the resource provider.
499    ///
500    /// This method begins advertising resources and accepting jobs.
501    ///
502    /// # Returns
503    ///
504    /// Returns `Ok(())` on successful start or an error if startup fails.
505    ///
506    /// # Examples
507    ///
508    /// ```rust
509    /// # use qudag_exchange::Provider;
510    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
511    /// # let provider = Provider::builder().build()?;
512    /// provider.start().await?;
513    /// println!("Provider started, ready to accept jobs");
514    /// # Ok(())
515    /// # }
516    /// ```
517    pub async fn start(&self) -> Result<()> {
518        // Implementation details...
519        todo!()
520    }
521
522    /// Stops the resource provider gracefully.
523    ///
524    /// This method stops accepting new jobs and waits for active jobs to complete.
525    ///
526    /// # Arguments
527    ///
528    /// * `force` - If true, forcefully stops all jobs immediately
529    ///
530    /// # Returns
531    ///
532    /// Returns `Ok(())` when stopped or an error if shutdown fails.
533    ///
534    /// # Examples
535    ///
536    /// ```rust
537    /// # use qudag_exchange::Provider;
538    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
539    /// # let provider = Provider::builder().build()?;
540    /// // Graceful shutdown
541    /// provider.stop(false).await?;
542    ///
543    /// // Force shutdown
544    /// provider.stop(true).await?;
545    /// # Ok(())
546    /// # }
547    /// ```
548    pub async fn stop(&self, force: bool) -> Result<()> {
549        // Implementation details...
550        todo!()
551    }
552
553    /// Gets current provider statistics.
554    ///
555    /// # Returns
556    ///
557    /// Returns `ProviderStats` with performance metrics and earnings.
558    ///
559    /// # Examples
560    ///
561    /// ```rust
562    /// # use qudag_exchange::Provider;
563    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
564    /// # let provider = Provider::builder().build()?;
565    /// let stats = provider.get_stats().await?;
566    /// println!("Jobs completed: {}", stats.jobs_completed);
567    /// println!("Total earned: {} rUv", stats.total_earned);
568    /// println!("Uptime: {:?}", stats.uptime);
569    /// # Ok(())
570    /// # }
571    /// ```
572    pub async fn get_stats(&self) -> Result<ProviderStats> {
573        // Implementation details...
574        todo!()
575    }
576}
577
578/// Builder for creating a Provider instance.
579///
580/// # Examples
581///
582/// ```rust
583/// # use qudag_exchange::{Provider, ProviderBuilder, ResourceSpec, PricingStrategy};
584/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
585/// # let account = Account::test_account();
586/// let provider = Provider::builder()
587///     .account(&account)
588///     .add_resource(ResourceSpec::cpu(16))
589///     .add_resource(ResourceSpec::gpu("A100", 4))
590///     .pricing_strategy(PricingStrategy::fixed(50.0))
591///     .min_job_duration(std::time::Duration::from_secs(3600))
592///     .build()?;
593/// # Ok(())
594/// # }
595/// ```
596pub struct ProviderBuilder {
597    account: Option<Account>,
598    // TODO: Add resource specification types
599    // resources: Vec<ResourceSpec>,
600    // pricing: Option<PricingStrategy>,
601    min_job_duration: Option<std::time::Duration>,
602}
603
604impl ProviderBuilder {
605    /// Creates a new provider builder.
606    pub fn new() -> Self {
607        Self {
608            account: None,
609            // resources: vec![],
610            // pricing: None,
611            min_job_duration: None,
612        }
613    }
614
615    /// Sets the account for the provider.
616    ///
617    /// # Arguments
618    ///
619    /// * `account` - The account that will receive payments
620    ///
621    /// # Returns
622    ///
623    /// Returns the builder for chaining.
624    pub fn account(mut self, account: &Account) -> Self {
625        self.account = Some(account.clone());
626        self
627    }
628
629    // TODO: Re-enable when ResourceSpec is implemented
630    // /// Adds a resource to offer.
631    // ///
632    // /// # Arguments
633    // ///
634    // /// * `resource` - The resource specification to add
635    // ///
636    // /// # Returns
637    // ///
638    // /// Returns the builder for chaining.
639    // pub fn add_resource(mut self, resource: ResourceSpec) -> Self {
640    //     self.resources.push(resource);
641    //     self
642    // }
643
644    // TODO: Re-enable when PricingStrategy is implemented
645    // /// Sets the pricing strategy.
646    // ///
647    // /// # Arguments
648    // ///
649    // /// * `strategy` - The pricing strategy to use
650    // ///
651    // /// # Returns
652    // ///
653    // /// Returns the builder for chaining.
654    // pub fn pricing_strategy(mut self, strategy: PricingStrategy) -> Self {
655    //     self.pricing = Some(strategy);
656    //     self
657    // }
658
659    /// Builds the Provider instance.
660    ///
661    /// # Returns
662    ///
663    /// Returns the configured `Provider` or an error if configuration is invalid.
664    ///
665    /// # Errors
666    ///
667    /// Returns an error if:
668    /// - No account is specified
669    /// - No resources are configured
670    /// - Invalid configuration parameters
671    pub fn build(self) -> Result<Provider> {
672        // Implementation details...
673        todo!()
674    }
675}
676
677// TODO: Implement pricing strategy types
678// /// Pricing strategy for resource offerings.
679// #[derive(Clone, Debug)]
680// pub enum PricingStrategy {
681//     /// Fixed price per resource unit
682//     Fixed(f64),
683//
684//     /// Market-based dynamic pricing
685//     MarketBased,
686//
687//     /// Custom pricing rules
688//     Custom(CustomPricing),
689// }
690
691/// Statistics for a resource provider.
692///
693/// Contains performance metrics, earnings, and resource utilization data.
694#[derive(Debug, Clone)]
695pub struct ProviderStats {
696    /// Number of jobs completed
697    pub jobs_completed: u64,
698
699    /// Number of jobs failed
700    pub jobs_failed: u64,
701
702    /// Total rUv earned
703    pub total_earned: f64,
704
705    /// Average job completion time
706    pub avg_completion_time: std::time::Duration,
707
708    /// Provider uptime
709    pub uptime: std::time::Duration,
710
711    /// Resource utilization percentage
712    pub utilization: f64,
713
714    /// Customer satisfaction rating (0-5)
715    pub satisfaction_rating: f64,
716}
717
718/// Market interface for searching and trading resources.
719///
720/// The `Market` struct provides methods for discovering available resources,
721/// comparing prices, and executing trades.
722///
723/// # Examples
724///
725/// ```rust
726/// use qudag_exchange::{Market, ResourceQuery};
727///
728/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
729/// # let exchange = Exchange::new("testnet").await?;
730/// let market = exchange.market();
731///
732/// // Search for GPU resources
733/// let query = ResourceQuery::new()
734///     .resource_type(ResourceType::Gpu)
735///     .min_memory_gb(40)
736///     .max_price(100.0);
737///
738/// let offers = market.search(query).await?;
739///
740/// for offer in offers {
741///     println!("Provider: {}", offer.provider);
742///     println!("Price: {} rUv/hour", offer.price_per_hour);
743/// }
744/// # Ok(())
745/// # }
746/// ```
747pub struct Market {
748    exchange: Exchange,
749}
750
751impl Market {
752    // TODO: Implement when ResourceQuery and Offer types are available
753    // /// Searches for resource offers matching the query.
754    // pub async fn search(&self, query: ResourceQuery) -> Result<Vec<Offer>> {
755    //     // Implementation details...
756    //     todo!()
757    // }
758
759    /// Gets current market statistics.
760    ///
761    /// # Returns
762    ///
763    /// Returns `MarketStats` with pricing and availability information.
764    ///
765    /// # Examples
766    ///
767    /// ```rust
768    /// # use qudag_exchange::Market;
769    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
770    /// # let market = Market::test_market();
771    /// let stats = market.get_stats().await?;
772    ///
773    /// println!("Active offers: {}", stats.active_offers);
774    /// println!("24h volume: {} rUv", stats.volume_24h);
775    /// println!("Avg GPU price: {} rUv/hour", stats.avg_gpu_price);
776    /// # Ok(())
777    /// # }
778    /// ```
779    pub async fn get_stats(&self) -> Result<MarketStats> {
780        // Implementation details...
781        todo!()
782    }
783
784    // TODO: Implement when OfferId and Reservation types are available
785    // /// Reserves resources from an offer.
786    // pub async fn reserve_resources(
787    //     &self,
788    //     offer_id: &OfferId,
789    //     duration: std::time::Duration,
790    // ) -> Result<Reservation> {
791    //     // Implementation details...
792    //     todo!()
793    // }
794}
795
796/// Market statistics and metrics.
797#[derive(Debug, Clone)]
798pub struct MarketStats {
799    /// Number of active resource offers
800    pub active_offers: u64,
801
802    /// Total providers in the market
803    pub total_providers: u64,
804
805    /// 24-hour trading volume in rUv
806    pub volume_24h: f64,
807
808    /// Average CPU price per hour
809    pub avg_cpu_price: f64,
810
811    /// Average GPU price per hour
812    pub avg_gpu_price: f64,
813
814    /// Average storage price per GB per month
815    pub avg_storage_price: f64,
816
817    /// Market liquidity score (0-100)
818    pub liquidity_score: f64,
819}
820
821/// A reservation for computational resources.
822#[derive(Debug, Clone)]
823pub struct Reservation {
824    /// Unique reservation identifier
825    pub id: String,
826
827    /// Resource access endpoint
828    pub access_endpoint: String,
829
830    /// Authentication credentials
831    pub auth_token: String,
832
833    /// Reservation expiration time
834    pub expires_at: std::time::SystemTime,
835
836    /// Total cost in rUv
837    pub total_cost: f64,
838}
839
840#[cfg(test)]
841mod tests {
842    use super::*;
843
844    #[tokio::test]
845    async fn test_exchange_creation() {
846        let exchange = Exchange::new("testnet").await.unwrap();
847        // Add test assertions
848    }
849
850    #[tokio::test]
851    async fn test_account_creation() {
852        let exchange = Exchange::new("testnet").await.unwrap();
853        let account = exchange.create_account("test", "password").await.unwrap();
854        assert!(!account.address().is_empty());
855    }
856}