use serde_json::Value;
use cow_sdk_core::{AppCode, ValidationReason};
use crate::{
AppDataDoc, AppDataError, AppDataParams, DEFAULT_APP_CODE, LATEST_APP_DATA_VERSION, PartnerFee,
QuoteMetadata, SchemaVersion, metadata::FlashloanHints,
};
#[must_use]
pub fn generate_app_data_doc(params: AppDataParams) -> AppDataDoc {
let metadata = params
.metadata_wire_value()
.expect("typed flashloan metadata must remain serializable");
let mut doc = serde_json::Map::new();
doc.insert(
"appCode".to_string(),
Value::String(
params
.app_code
.map_or_else(|| DEFAULT_APP_CODE.to_string(), AppCode::into_inner),
),
);
if let Some(environment) = params.environment {
doc.insert("environment".to_string(), Value::String(environment));
}
doc.insert("metadata".to_string(), metadata);
doc.insert(
"version".to_string(),
Value::String(LATEST_APP_DATA_VERSION.to_string()),
);
Value::Object(doc)
}
pub fn validate_app_data_doc(app_data_doc: &AppDataDoc) -> Result<(), AppDataError> {
let version = extract_schema_version(app_data_doc)?;
SchemaVersion::new(version)?;
let Some(metadata) = app_data_doc.get("metadata").and_then(Value::as_object) else {
return Ok(());
};
if let Some(value) = metadata.get("flashloan") {
serde_json::from_value::<FlashloanHints>(value.clone())
.map_err(|_| AppDataError::InvalidAppDataProvided {
field: "metadata.flashloan",
reason: ValidationReason::BadShape {
details: "value does not match the typed flash-loan hint shape",
},
})?
.validate()?;
}
if let Some(value) = metadata.get("partnerFee") {
PartnerFee::from_value(value.clone())
.map_err(|_| AppDataError::InvalidAppDataProvided {
field: "metadata.partnerFee",
reason: ValidationReason::BadShape {
details: "value does not match a supported partner-fee policy shape",
},
})?
.validate()?;
}
if let Some(value) = metadata.get("quote")
&& let Ok(quote) = QuoteMetadata::from_value(value.clone())
{
quote.validate()?;
}
Ok(())
}
pub fn extract_schema_version(app_data_doc: &AppDataDoc) -> Result<&str, AppDataError> {
app_data_doc
.get("version")
.and_then(Value::as_str)
.ok_or(AppDataError::MissingSchemaVersion)
}