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}