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}