mithril_common/era/adapters/
builder.rs1use serde::{Deserialize, Serialize};
2use std::{fmt::Display, path::PathBuf, sync::Arc};
3use thiserror::Error;
4
5use crate::{
6 chain_observer::{ChainAddress, ChainObserver},
7 crypto_helper::EraMarkersVerifierVerificationKey,
8 era::{
9 adapters::{
10 EraReaderBootstrapAdapter, EraReaderCardanoChainAdapter, EraReaderDummyAdapter,
11 EraReaderFileAdapter,
12 },
13 EraMarker, EraReaderAdapter,
14 },
15 StdError,
16};
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
20#[serde(rename_all = "lowercase")]
21pub enum AdapterType {
22 #[serde(rename = "cardano-chain")]
24 CardanoChain,
25 File,
27 Dummy,
29 Bootstrap,
31}
32
33impl Display for AdapterType {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 Self::Bootstrap => write!(f, "bootstrap"),
37 Self::CardanoChain => write!(f, "cardano chain"),
38 Self::Dummy => write!(f, "dummy"),
39 Self::File => write!(f, "file"),
40 }
41 }
42}
43
44#[derive(Error, Debug)]
46pub enum AdapterBuilderError {
47 #[error("era reader adapter parameters are missing")]
49 MissingParameters(),
50
51 #[error("era reader adapter parameters parse error")]
53 ParseParameters(#[source] serde_json::Error),
54
55 #[error("era reader adapter parameters decode error")]
57 Decode(#[source] StdError),
58}
59
60pub struct AdapterBuilder {
62 adapter_type: AdapterType,
63 adapter_params: Option<String>,
64}
65
66impl AdapterBuilder {
67 pub fn new(adapter_type: &AdapterType, adapter_params: &Option<String>) -> Self {
69 Self {
70 adapter_type: adapter_type.to_owned(),
71 adapter_params: adapter_params.to_owned(),
72 }
73 }
74
75 pub fn build(
77 &self,
78 chain_observer: Arc<dyn ChainObserver>,
79 ) -> Result<Arc<dyn EraReaderAdapter>, AdapterBuilderError> {
80 match self.adapter_type {
81 AdapterType::CardanoChain => {
82 #[derive(Deserialize)]
83 struct CardanoChainAdapterConfig {
84 address: ChainAddress,
85 verification_key: EraMarkersVerifierVerificationKey,
86 }
87
88 let adapter_config: CardanoChainAdapterConfig = serde_json::from_str(
89 self.adapter_params
90 .as_ref()
91 .ok_or_else(AdapterBuilderError::MissingParameters)?,
92 )
93 .map_err(AdapterBuilderError::ParseParameters)?;
94
95 Ok(Arc::new(EraReaderCardanoChainAdapter::new(
96 adapter_config.address,
97 chain_observer,
98 adapter_config.verification_key,
99 )))
100 }
101 AdapterType::File => {
102 #[derive(Deserialize)]
103 struct EraReaderFileAdapterConfig {
104 markers_file: PathBuf,
105 }
106
107 let adapter_config: EraReaderFileAdapterConfig = serde_json::from_str(
108 self.adapter_params
109 .as_ref()
110 .ok_or_else(AdapterBuilderError::MissingParameters)?,
111 )
112 .map_err(AdapterBuilderError::ParseParameters)?;
113 let file_adapter = EraReaderFileAdapter::new(adapter_config.markers_file);
114
115 Ok(Arc::new(file_adapter))
116 }
117 AdapterType::Dummy => {
118 #[derive(Deserialize)]
119 struct EraReaderDummyAdapterConfig {
120 markers: Vec<EraMarker>,
121 }
122
123 let adapter_config: EraReaderDummyAdapterConfig = serde_json::from_str(
124 self.adapter_params
125 .as_ref()
126 .ok_or_else(AdapterBuilderError::MissingParameters)?,
127 )
128 .map_err(AdapterBuilderError::ParseParameters)?;
129 let dummy_adapter = EraReaderDummyAdapter::default();
130 dummy_adapter.set_markers(adapter_config.markers);
131
132 Ok(Arc::new(dummy_adapter))
133 }
134 AdapterType::Bootstrap => Ok(Arc::new(EraReaderBootstrapAdapter)),
135 }
136 }
137}
138
139#[cfg(test)]
140mod test {
141 use crate::chain_observer::MockChainObserver;
142
143 use super::*;
144
145 const GOLDEN_ADAPTER_PARAMS: &str = r#"{
146 "address":"addr_test1qrv5xfwh043mlc3vk5d97s4nmhxu7cmleyssvhx37gkfyejfe8d38v3vsfgetjafgrsdc49krug8wf04h5rmtengtejqlxrksk",
147 "verification_key":"5b35352c3232382c3134342c38372c3133382c3133362c34382c382c31342c3138372c38352c3134382c39372c3233322c3235352c3232392c33382c3234342c3234372c3230342c3139382c31332c33312c3232322c32352c3136342c35322c3130322c39312c3132302c3230382c3134375d"
148 }"#;
149
150 #[test]
151 fn golden_test_for_cardano_chain() {
152 AdapterBuilder::new(
153 &AdapterType::CardanoChain,
154 &Some(GOLDEN_ADAPTER_PARAMS.to_owned()),
155 )
156 .build(Arc::new(MockChainObserver::new()))
157 .expect("building an cardano chain era reader with golden params should not fail");
158 }
159}