1use ethers::types::Address;
2use serde::{Deserialize, Serialize};
3use url::Url;
4
5use crate::NftImage;
6
7#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13pub enum OpenSeaDisplayType {
14 Date,
16 Number,
18 BoostPercentage,
20 BoostNumber,
22}
23
24#[derive(Clone, Debug, Serialize, Deserialize)]
29#[serde(untagged)]
30pub enum OpenSeaAttributeValue {
31 String {
33 value: String,
35 },
36 Integer {
38 value: i64,
40 #[serde(default, skip_serializing_if = "Option::is_none")]
42 display_type: Option<OpenSeaDisplayType>,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
44 max_value: Option<i64>,
46 },
47 Float {
49 value: f64,
51 #[serde(default, skip_serializing_if = "Option::is_none")]
52 display_type: Option<OpenSeaDisplayType>,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 max_value: Option<f64>,
57 },
58}
59
60impl<T> From<T> for OpenSeaAttributeValue
61where
62 T: AsRef<str>,
63{
64 fn from(t: T) -> Self {
65 OpenSeaAttributeValue::String {
66 value: t.as_ref().to_string(),
67 }
68 }
69}
70
71#[derive(Clone, Debug, Serialize, Deserialize)]
74pub struct OpenSeaAttribute {
75 #[serde(default, skip_serializing_if = "Option::is_none")]
77 pub trait_type: Option<String>,
78 #[serde(flatten)]
80 pub value: OpenSeaAttributeValue,
81}
82
83impl OpenSeaAttribute {
84 pub fn string<S, T>(trait_type: Option<S>, value: T) -> Self
86 where
87 S: AsRef<str>,
88 T: AsRef<str>,
89 {
90 Self {
91 trait_type: trait_type.map(|s| s.as_ref().to_string()),
92 value: value.into(),
93 }
94 }
95
96 pub fn float<S>(trait_type: Option<S>, value: f64, max_value: Option<f64>) -> Self
98 where
99 S: AsRef<str>,
100 {
101 Self {
102 trait_type: trait_type.map(|s| s.as_ref().to_string()),
103 value: OpenSeaAttributeValue::Float {
104 value,
105 display_type: None,
106 max_value,
107 },
108 }
109 }
110
111 pub fn integer<S>(trait_type: Option<S>, value: i64, max_value: Option<i64>) -> Self
113 where
114 S: AsRef<str>,
115 {
116 Self {
117 trait_type: trait_type.map(|s| s.as_ref().to_string()),
118 value: OpenSeaAttributeValue::Integer {
119 value,
120 display_type: None,
121 max_value,
122 },
123 }
124 }
125}
126
127#[derive(Clone, Debug, Serialize, Deserialize)]
129pub struct ContractMetadata {
130 pub name: String,
132 pub description: String,
134 #[serde(flatten)]
136 pub image: NftImage,
137 pub external_link: Url,
139 pub seller_fee_basis_points: usize,
141 pub fee_recipient: Address,
143}