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}