use crate::event::EventFingerprint;
use crate::types::CanonicalType;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TrustLevel {
#[default]
Unverified,
CommunityVerified,
MaintainerVerified,
ProtocolVerified,
}
impl std::fmt::Display for TrustLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
TrustLevel::Unverified => "unverified",
TrustLevel::CommunityVerified => "community_verified",
TrustLevel::MaintainerVerified => "maintainer_verified",
TrustLevel::ProtocolVerified => "protocol_verified",
};
write!(f, "{s}")
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldDef {
pub ty: CanonicalType,
pub indexed: bool,
pub nullable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SchemaMeta {
#[serde(skip_serializing_if = "Option::is_none")]
pub protocol: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub category: Option<String>,
pub verified: bool,
pub trust_level: TrustLevel,
#[serde(skip_serializing_if = "Option::is_none")]
pub provenance_sig: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Schema {
pub name: String,
pub version: u32,
pub chains: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<Vec<String>>,
pub event: String,
pub fingerprint: EventFingerprint,
#[serde(skip_serializing_if = "Option::is_none")]
pub supersedes: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub superseded_by: Option<String>,
pub deprecated: bool,
pub fields: Vec<(String, FieldDef)>,
pub meta: SchemaMeta,
}
impl Schema {
pub fn fields_map(&self) -> HashMap<&str, &FieldDef> {
self.fields.iter().map(|(k, v)| (k.as_str(), v)).collect()
}
pub fn indexed_fields(&self) -> Vec<(&str, &FieldDef)> {
self.fields
.iter()
.filter(|(_, f)| f.indexed)
.map(|(k, v)| (k.as_str(), v))
.collect()
}
pub fn data_fields(&self) -> Vec<(&str, &FieldDef)> {
self.fields
.iter()
.filter(|(_, f)| !f.indexed)
.map(|(k, v)| (k.as_str(), v))
.collect()
}
}
pub trait SchemaRegistry: Send + Sync {
fn get_by_fingerprint(&self, fp: &EventFingerprint) -> Option<Schema>;
fn get_by_name(&self, name: &str, version: Option<u32>) -> Option<Schema>;
fn list_for_chain(&self, chain_slug: &str) -> Vec<Schema>;
fn history(&self, name: &str) -> Vec<Schema>;
}