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        KeyValueStorageWithColumnFamilies,
33        StorageError,
34    },
35    views::Views,
36};
37use base_sdk::{
38    core::Shard,
39    vaults::{
40        OwnerId,
41        Vault,
42    },
43};
44use domain_runtime::storage::ColumnFamilies;
45#[cfg(feature = "admin-api")]
46use std::net::SocketAddr;
47use std::{
48    collections::HashMap,
49    num::NonZero,
50};
51
52/// A delta domain
53///
54/// This struct gives access to all domain operations:
55/// - the [runner](Self::runner) to run the domain's event processing
56/// - the [client](Self::client) to perform actions on the domain
57/// - the [views](Self::views) to read data and state from the domain
58///
59/// The struct is generic over:
60/// - `P`: the proving client
61/// - `S`: the storage back-end, defaults to the storage back-end defined by the
62///   cargo features (see below)
63///
64/// Storage back-ends can be enabled via cargo features:
65/// - in-memory storage by default
66/// - RocksDB storage if feature `rocksdb` is set
67///
68/// Create a new domain with a [builder](crate::builder::DomainBuilder):
69/// - by reading from configuration with [Self::from_config], or
70/// - manually by calling [Self::builder].
71///
72/// Destructuring into the three components is recommended upon creation:
73/// ```rust,no_run
74/// use delta_domain_sdk::{Domain, Config};
75///
76/// async fn example() -> Result<(), Box<dyn std::error::Error>> {
77///     let config = Config::load()?;
78///     let Domain {
79///         runner,
80///         client,
81///         views,
82///     } = Domain::from_config(config).build().await?;
83///     Ok(())
84/// }
85/// ```
86#[derive(Debug)]
87pub struct Domain<P, S = DefaultStorage>
88where
89    P: Proving,
90    S: KeyValueStorageWithColumnFamilies<
91            ColumnFamilyIdentifier = ColumnFamilies,
92            Error = StorageError,
93        > + Send
94        + Sync
95        + 'static,
96{
97    /// Runner to start the domain.
98    ///
99    /// The runner must be used _once_ to launch the domain's event loop with
100    /// [Runner::run]. It's not cloneable.
101    pub runner: Runner<P, S>,
102
103    /// Client to performing actions on a running domain.
104    pub client: DomainClient,
105
106    /// Read-only views of the domain's state and data.
107    pub views: Views<S>,
108}
109
110impl<P, S> Domain<P, S>
111where
112    P: Proving,
113    S: KeyValueStorageWithColumnFamilies<
114            ColumnFamilyIdentifier = ColumnFamilies,
115            Error = StorageError,
116        > + Send
117        + Sync
118        + 'static,
119{
120    pub(crate) fn new(
121        shard: NonZero<Shard>,
122        prover: P,
123        storage: S,
124        base_layer: BaseLayer,
125        seed_vaults: HashMap<OwnerId, Vault>,
126        #[cfg(feature = "admin-api")] admin_api_address: SocketAddr,
127    ) -> Self {
128        let local_laws_vkey = prover.local_laws_vkey();
129        let db = Database::new(storage);
130        let runner = Runner::new(
131            shard,
132            prover,
133            db.clone(),
134            base_layer.clone(),
135            seed_vaults,
136            #[cfg(feature = "admin-api")]
137            admin_api_address,
138        );
139        let endpoint = runner.endpoint();
140        Self {
141            runner,
142            client: DomainClient::new(shard, local_laws_vkey, endpoint, base_layer.clone()),
143            views: Views::new(shard, db, base_layer),
144        }
145    }
146}