delta_domain_sdk/
domain.rs

1//! # Domain
2//!
3//! The main entry point for building and running a [`Domain`].
4//!
5//! ```rust,no_run
6//! use delta_domain_sdk::{Domain, Config};
7//!
8//! async fn example() -> Result<(), Box<dyn std::error::Error>> {
9//!     let config = Config::load()?;
10//!     let Domain { runner, client, views } = Domain::from_config(config)
11//!         .build()
12//!         .await?;
13//!
14//!     // Spawn the event loop
15//!     let handle = tokio::spawn(runner.run());
16//!
17//!     // Use client and views from other tasks
18//!     // client.apply(messages).await?;
19//!     // let vault = views.domain_view().get_vault(&address)?;
20//!     Ok(())
21//! }
22//! ```
23
24use crate::{
25    base_layer::BaseLayer,
26    client::DomainClient,
27    proving::Proving,
28    runner::Runner,
29    storage::{
30        Database,
31        DefaultStorage,
32        KeyValueStorage,
33        StorageError,
34    },
35    views::Views,
36};
37use base_sdk::vaults::{
38    OwnerId,
39    Vault,
40};
41use domain_runtime::{
42    config::RuntimeConfig,
43    storage::ColumnFamilies,
44};
45use std::{
46    collections::HashMap,
47    net::SocketAddr,
48};
49
50/// A delta domain
51///
52/// This struct gives access to all domain operations:
53/// - the [runner](Self::runner) to run the domain's event processing
54/// - the [client](Self::client) to perform actions on the domain
55/// - the [views](Self::views) to read data and state from the domain
56///
57/// The struct is generic over:
58/// - `S`: the storage back-end, defaults to the storage back-end defined by the
59///   cargo features (see below)
60///
61/// Storage back-ends can be enabled via cargo features:
62/// - in-memory storage by default
63/// - RocksDB storage if feature `rocksdb` is set
64///
65/// Create a new domain with a [builder](crate::builder::DomainBuilder):
66/// - by reading from configuration with [Self::from_config], or
67/// - manually by calling [Self::builder].
68///
69/// Destructuring into the three components is recommended upon creation:
70/// ```rust,no_run
71/// use delta_domain_sdk::{Domain, Config};
72///
73/// async fn example() -> Result<(), Box<dyn std::error::Error>> {
74///     let config = Config::load()?;
75///     let Domain {
76///         runner,
77///         client,
78///         views,
79///     } = Domain::from_config(config).build().await?;
80///     Ok(())
81/// }
82/// ```
83#[derive(Debug)]
84pub struct Domain<S = DefaultStorage>
85where
86    S: KeyValueStorage<ColumnFamilyIdentifier = ColumnFamilies, Error = StorageError>
87        + Send
88        + Sync
89        + 'static,
90{
91    /// Runner to start the domain.
92    ///
93    /// The runner must be used _once_ to launch the domain's event loop with
94    /// [Runner::run]. It's not cloneable.
95    pub runner: Runner<S>,
96
97    /// Client to performing actions on a running domain.
98    pub client: DomainClient,
99
100    /// Read-only views of the domain's state and data.
101    pub views: Views<S>,
102}
103
104impl<S> Domain<S>
105where
106    S: KeyValueStorage<ColumnFamilyIdentifier = ColumnFamilies, Error = StorageError>
107        + Send
108        + Sync
109        + 'static,
110{
111    pub(crate) fn new(
112        config: RuntimeConfig,
113        prover: Box<dyn Proving>,
114        db: Database<S>,
115        base_layer: BaseLayer,
116        seed_vaults: HashMap<OwnerId, Vault>,
117        admin_api_address: SocketAddr,
118    ) -> Self {
119        let local_laws_vkey = prover.local_laws_vkey();
120        let runner = Runner::new(
121            config,
122            prover,
123            db.clone(),
124            base_layer.clone(),
125            seed_vaults,
126            admin_api_address,
127        );
128        let endpoint = runner.endpoint();
129        Self {
130            runner,
131            client: DomainClient::new(config.shard, local_laws_vkey, endpoint, base_layer.clone()),
132            views: Views::new(config.shard, db, base_layer),
133        }
134    }
135}