iota_graphql_rpc/types/
protocol_config.rs1use std::collections::BTreeMap;
6
7use async_graphql::*;
8use diesel::{ExpressionMethods, QueryDsl};
9use iota_indexer::schema::{epochs, feature_flags, protocol_configs};
10
11use crate::{
12 data::{Db, DbConnection, QueryExecutor},
13 error::Error,
14 types::uint53::UInt53,
15};
16
17#[derive(Clone, Debug, SimpleObject)]
19pub(crate) struct ProtocolConfigAttr {
20 pub key: String,
21 pub value: Option<String>,
22}
23
24#[derive(Clone, Debug, SimpleObject)]
26pub(crate) struct ProtocolConfigFeatureFlag {
27 pub key: String,
28 pub value: bool,
29}
30
31#[derive(Clone, Debug)]
32pub(crate) struct ProtocolConfigs {
33 version: u64,
34 configs: BTreeMap<String, Option<String>>,
35 feature_flags: BTreeMap<String, bool>,
36}
37
38#[Object]
43impl ProtocolConfigs {
44 async fn protocol_version(&self) -> UInt53 {
48 self.version.into()
49 }
50
51 async fn feature_flags(&self) -> Vec<ProtocolConfigFeatureFlag> {
56 self.feature_flags
57 .clone()
58 .into_iter()
59 .map(|(key, value)| ProtocolConfigFeatureFlag { key, value })
60 .collect()
61 }
62
63 async fn configs(&self) -> Vec<ProtocolConfigAttr> {
67 self.configs
68 .clone()
69 .into_iter()
70 .map(|(key, value)| ProtocolConfigAttr { key, value })
71 .collect()
72 }
73
74 async fn config(&self, key: String) -> Option<ProtocolConfigAttr> {
76 self.configs.get(&key).map(|value| ProtocolConfigAttr {
77 key,
78 value: value.as_ref().map(|v| v.to_string()),
79 })
80 }
81
82 async fn feature_flag(&self, key: String) -> Option<ProtocolConfigFeatureFlag> {
84 self.feature_flags
85 .get(&key)
86 .map(|value| ProtocolConfigFeatureFlag { key, value: *value })
87 }
88}
89
90impl ProtocolConfigs {
91 pub(crate) async fn query(db: &Db, protocol_version: Option<u64>) -> Result<Self, Error> {
92 use epochs::dsl as e;
93 use feature_flags::dsl as f;
94 use protocol_configs::dsl as p;
95
96 let version = if let Some(version) = protocol_version {
97 version
98 } else {
99 let latest_version: i64 = db
100 .execute(move |conn| {
101 conn.first(move || {
102 e::epochs
103 .select(e::protocol_version)
104 .order_by(e::epoch.desc())
105 })
106 })
107 .await
108 .map_err(|e| {
109 Error::Internal(format!(
110 "Failed to fetch latest protocol version in db: {e}"
111 ))
112 })?;
113 latest_version as u64
114 };
115
116 let configs: BTreeMap<String, Option<String>> = db
119 .execute(move |conn| {
120 conn.results(move || {
121 p::protocol_configs
122 .select((p::config_name, p::config_value))
123 .filter(p::protocol_version.eq(version as i64))
124 })
125 })
126 .await
127 .map_err(|e| Error::Internal(format!("Failed to fetch protocol configs in db: {e}")))?
128 .into_iter()
129 .collect();
130
131 let feature_flags: BTreeMap<String, bool> = db
132 .execute(move |conn| {
133 conn.results(move || {
134 f::feature_flags
135 .select((f::flag_name, f::flag_value))
136 .filter(f::protocol_version.eq(version as i64))
137 })
138 })
139 .await
140 .map_err(|e| Error::Internal(format!("Failed to fetch feature flags in db: {e}")))?
141 .into_iter()
142 .collect();
143
144 Ok(ProtocolConfigs {
145 version,
146 configs,
147 feature_flags,
148 })
149 }
150}