use schemars::JsonSchema;
use serde::{Deserialize, Deserializer, Serialize};
use crate::prelude::*;
#[derive(
Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema, cw_schema::Schemaifier,
)]
#[schemaifier(mute_warnings)] pub struct DenomMetadata {
pub description: String,
#[serde(deserialize_with = "deserialize_null_default")]
pub denom_units: Vec<DenomUnit>,
pub base: String,
pub display: String,
pub name: String,
pub symbol: String,
pub uri: String,
pub uri_hash: String,
}
#[derive(
Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema, cw_schema::Schemaifier,
)]
#[schemaifier(mute_warnings)] pub struct DenomUnit {
pub denom: String,
pub exponent: u32,
#[serde(deserialize_with = "deserialize_null_default")]
pub aliases: Vec<String>,
}
fn deserialize_null_default<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
T: Default + Deserialize<'de>,
D: Deserializer<'de>,
{
let opt = Option::deserialize(deserializer)?;
Ok(opt.unwrap_or_default())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{DenomMetadata, DenomUnit};
use serde_json::{json, Error};
#[test]
fn deserialize_denom_metadata_with_null_fields_works() {
let json_with_null_denom_units = json!({
"description": "Test Token",
"denom_units": null,
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_null_denom_units: DenomMetadata =
serde_json::from_value(json_with_null_denom_units).unwrap();
assert_eq!(
metadata_null_denom_units.denom_units,
Vec::<DenomUnit>::new()
);
let json_with_units = json!({
"description": "Test Token",
"denom_units": [
{
"denom": "utest",
"exponent": 6,
"aliases": ["microtest"]
}
],
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_with_units: DenomMetadata = serde_json::from_value(json_with_units).unwrap();
assert_eq!(metadata_with_units.denom_units.len(), 1);
assert_eq!(metadata_with_units.denom_units[0].denom, "utest");
let json_with_null_aliases = json!({
"description": "Test Token",
"denom_units": [
{
"denom": "utest",
"exponent": 6,
"aliases": null
}
],
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_with_null_aliases: DenomMetadata =
serde_json::from_value(json_with_null_aliases).unwrap();
assert_eq!(metadata_with_null_aliases.denom_units.len(), 1);
assert_eq!(
metadata_with_null_aliases.denom_units[0].aliases,
Vec::<String>::new()
);
}
#[test]
fn deserialize_denom_metadata_with_missing_fields_fails() {
let json_missing_denom_units = json!({
"description": "Test Token",
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata: Result<DenomMetadata, Error> =
serde_json::from_value(json_missing_denom_units);
assert!(metadata.is_err());
let json_missing_alias = json!({
"description": "Test Token",
"base": "utest",
"denom_units": [
{
"denom": "utest",
"exponent": 6,
}
],
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_missing_alias: Result<DenomMetadata, Error> =
serde_json::from_value(json_missing_alias);
assert!(metadata_missing_alias.is_err());
}
#[test]
fn query_denom_metadata_with_null_denom_units_works() {
let json_with_null_denom_units = json!({
"description": "Test Token",
"denom_units": null,
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_with_null_denom_units: DenomMetadata =
serde_json::from_value(json_with_null_denom_units).unwrap();
assert_eq!(
metadata_with_null_denom_units.denom_units,
Vec::<DenomUnit>::new()
);
let json_with_units = json!({
"description": "Test Token",
"denom_units": [
{
"denom": "utest",
"exponent": 6,
"aliases": ["microtest"]
}
],
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_with_units: DenomMetadata = serde_json::from_value(json_with_units).unwrap();
assert_eq!(metadata_with_units.denom_units.len(), 1);
assert_eq!(metadata_with_units.denom_units[0].denom, "utest");
assert_eq!(metadata_with_units.denom_units[0].aliases.len(), 1);
assert_eq!(metadata_with_units.denom_units[0].aliases[0], "microtest");
let json_with_null_aliases = json!({
"description": "Test Token",
"denom_units": [
{
"denom": "utest",
"exponent": 6,
"aliases": null
}
],
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let metadata_with_null_aliases: DenomMetadata =
serde_json::from_value(json_with_null_aliases).unwrap();
assert_eq!(metadata_with_null_aliases.denom_units.len(), 1);
assert_eq!(
metadata_with_null_aliases.denom_units[0].aliases,
Vec::<String>::new()
);
}
#[test]
fn query_denom_metadata_with_missing_fields_fails() {
let json_missing_denom_units = json!({
"description": "Test Token",
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let json_missing_denom_units_metadata: Result<DenomMetadata, Error> =
serde_json::from_value(json_missing_denom_units);
assert!(json_missing_denom_units_metadata.is_err());
let json_missing_aliases = json!({
"description": "Test Token",
"denom_units": [
{
"denom": "utest",
"exponent": 6
}
],
"base": "utest",
"display": "TEST",
"name": "Test Token",
"symbol": "TEST",
"uri": "https://test.com",
"uri_hash": "hash"
});
let missing_aliases_metadata: Result<DenomMetadata, Error> =
serde_json::from_value(json_missing_aliases);
assert!(missing_aliases_metadata.is_err());
}
#[test]
fn query_denom_metadata_with_mixed_null_and_value_works() {
let mixed_json = json!({
"description": "Mixed Token",
"denom_units": [
{
"denom": "unit1",
"exponent": 0,
"aliases": null
},
{
"denom": "unit2",
"exponent": 6,
"aliases": ["microunit", "u"]
},
{
"denom": "unit3",
"exponent": 9,
"aliases": []
}
],
"base": "unit1",
"display": "MIXED",
"name": "Mixed Token",
"symbol": "MIX",
"uri": "https://mixed.token",
"uri_hash": "hash123"
});
let metadata: DenomMetadata = serde_json::from_value(mixed_json).unwrap();
assert!(metadata.denom_units[0].aliases.is_empty());
assert_eq!(metadata.denom_units[1].aliases.len(), 2);
assert_eq!(metadata.denom_units[1].aliases[0], "microunit");
assert_eq!(metadata.denom_units[1].aliases[1], "u");
assert!(metadata.denom_units[2].aliases.is_empty());
}
}