nyxd_scraper_shared/cosmos_module/
message_registry.rs1use crate::cosmos_module::CosmosModule;
5use crate::cosmos_module::modules::auth::Auth;
6use crate::cosmos_module::modules::authz::Authz;
7use crate::cosmos_module::modules::bank::Bank;
8use crate::cosmos_module::modules::capability::Capability;
9use crate::cosmos_module::modules::consensus::Consensus;
10use crate::cosmos_module::modules::crisis::Crisis;
11use crate::cosmos_module::modules::distribution::Distribution;
12use crate::cosmos_module::modules::evidence::Evidence;
13use crate::cosmos_module::modules::feegrant::Feegrant;
14use crate::cosmos_module::modules::gov_v1::GovV1;
15use crate::cosmos_module::modules::gov_v1beta1::GovV1Beta1;
16use crate::cosmos_module::modules::group::Group;
17use crate::cosmos_module::modules::ibc_core::IbcCore;
18use crate::cosmos_module::modules::ibc_fee::IbcFee;
19use crate::cosmos_module::modules::ibc_interchain_accounts_controller::IbcInterchainAccountsController;
20use crate::cosmos_module::modules::ibc_transfer_v1::IbcTransferV1;
21use crate::cosmos_module::modules::ibc_transfer_v2::IbcTransferV2;
22use crate::cosmos_module::modules::mint::Mint;
23use crate::cosmos_module::modules::nft::Nft;
24use crate::cosmos_module::modules::params::Params;
25use crate::cosmos_module::modules::slashing::Slashing;
26use crate::cosmos_module::modules::staking::Staking;
27use crate::cosmos_module::modules::upgrade::Upgrade;
28use crate::cosmos_module::modules::vesting::Vesting;
29use crate::cosmos_module::modules::wasm::Wasm;
30use crate::error::ScraperError;
31use cosmrs::Any;
32use cosmrs::proto::prost::Name;
33use cosmrs::proto::traits::Message;
34use serde::Serialize;
35use std::collections::HashMap;
36
37pub(crate) fn default_proto_to_json<T: Message + Default + Serialize>(
38 msg: &Any,
39) -> Result<serde_json::Value, ScraperError> {
40 let proto = <T as Message>::decode(msg.value.as_slice()).map_err(|error| {
41 ScraperError::InvalidProtoRepresentation {
42 type_url: msg.type_url.clone(),
43 error,
44 }
45 })?;
46 let mut base_serde =
47 serde_json::to_value(&proto).map_err(|error| ScraperError::JsonSerialisationFailure {
48 type_url: msg.type_url.clone(),
49 error,
50 })?;
51
52 let obj = base_serde.as_object_mut().ok_or_else(|| {
54 ScraperError::JsonSerialisationFailureNotObject {
55 type_url: msg.type_url.clone(),
56 }
57 })?;
58 obj.insert(
59 "@type".to_string(),
60 serde_json::Value::String(msg.type_url.clone()),
61 );
62
63 Ok(base_serde)
64}
65
66type ConvertFn = fn(&Any) -> Result<serde_json::Value, ScraperError>;
67
68#[derive(Default, Clone)]
69pub struct MessageRegistry {
70 registered_types: HashMap<String, ConvertFn>,
72}
73
74impl MessageRegistry {
75 pub fn new() -> Self {
76 MessageRegistry {
77 registered_types: Default::default(),
78 }
79 }
80
81 pub fn register<T>(&mut self)
82 where
83 T: Message + Default + Name + Serialize + 'static,
84 {
85 self.register_with_custom_fn::<T>(default_proto_to_json::<T>)
86 }
87
88 #[allow(clippy::panic)]
89 pub fn register_with_custom_fn<T>(&mut self, convert_fn: ConvertFn)
90 where
91 T: Message + Default + Name + Serialize + 'static,
92 {
93 if self
94 .registered_types
95 .insert(<T as Name>::type_url(), convert_fn)
96 .is_some()
97 {
98 panic!("duplicate registration of type {}", <T as Name>::type_url());
100 }
101 }
102
103 pub fn try_decode(&self, raw: &Any) -> Result<serde_json::Value, ScraperError> {
104 self.registered_types.get(&raw.type_url).ok_or(
105 ScraperError::MissingTypeUrlRegistration {
106 type_url: raw.type_url.clone(),
107 },
108 )?(raw)
109 }
110}
111
112pub fn default_message_registry() -> MessageRegistry {
113 let mut registry = MessageRegistry::new();
114 let modules: Vec<Box<dyn CosmosModule>> = vec![
115 Box::new(Auth),
116 Box::new(Authz),
117 Box::new(Bank),
118 Box::new(Capability),
119 Box::new(Consensus),
120 Box::new(Wasm),
121 Box::new(Crisis),
122 Box::new(Distribution),
123 Box::new(Evidence),
124 Box::new(Feegrant),
125 Box::new(GovV1),
126 Box::new(GovV1Beta1),
127 Box::new(Group),
128 Box::new(IbcCore),
129 Box::new(IbcFee),
130 Box::new(IbcTransferV1),
131 Box::new(IbcTransferV2),
132 Box::new(IbcInterchainAccountsController),
133 Box::new(Mint),
134 Box::new(Nft),
135 Box::new(Params),
136 Box::new(Slashing),
137 Box::new(Staking),
138 Box::new(Upgrade),
139 Box::new(Vesting),
140 ];
141
142 for module in modules {
143 module.register_messages(&mut registry)
144 }
145 registry
146}