1#![cfg_attr(not(feature = "std"), no_std)]23pub use serde::{Serialize, Deserialize};45use sp_runtime::sp_std::prelude::Vec;6use codec::{Decode, Encode};7use max_encoded_len::MaxEncodedLen;8pub use frame_support::{9 BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,10 dispatch::DispatchResult,11 ensure, fail, parameter_types,12 traits::{13 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,14 Randomness, IsSubType, WithdrawReasons,15 },16 weights::{17 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},18 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,19 WeightToFeePolynomial, DispatchClass,20 },21 StorageValue, transactional,22};23use derivative::Derivative;2425pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;26pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;27pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;28pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;29303132parameter_types! {33pub const MaxDataSize: u32 = 2048;3435pub const MaxItemsPerBatch: u32 = 200;36}3738pub type CollectionId = u32;39pub type TokenId = u32;40pub type DecimalPoints = u8;4142#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, Serialize, Deserialize)]43pub enum CollectionMode {44 Invalid,45 NFT,46 47 Fungible(DecimalPoints),48 ReFungible,49}5051impl Default for CollectionMode {52 fn default() -> Self {53 Self::Invalid54 }55}5657impl CollectionMode {58 pub fn id(&self) -> u8 {59 match self {60 CollectionMode::Invalid => 0,61 CollectionMode::NFT => 1,62 CollectionMode::Fungible(_) => 2,63 CollectionMode::ReFungible => 3,64 }65 }66}6768pub trait SponsoringResolve<AccountId, Call> {69 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;70}7172#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, Serialize, Deserialize)]73pub enum AccessMode {74 Normal,75 WhiteList,76}77impl Default for AccessMode {78 fn default() -> Self {79 Self::Normal80 }81}8283#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, Serialize, Deserialize)]84pub enum SchemaVersion {85 ImageURL,86 Unique,87}88impl Default for SchemaVersion {89 fn default() -> Self {90 Self::ImageURL91 }92}9394#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, Serialize, Deserialize)]95pub struct Ownership<AccountId> {96 pub owner: AccountId,97 pub fraction: u128,98}99100#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)]101pub enum SponsorshipState<AccountId> {102 103 Disabled,104 Unconfirmed(AccountId),105 106 Confirmed(AccountId),107}108109impl<AccountId> SponsorshipState<AccountId> {110 pub fn sponsor(&self) -> Option<&AccountId> {111 match self {112 Self::Confirmed(sponsor) => Some(sponsor),113 _ => None,114 }115 }116117 pub fn pending_sponsor(&self) -> Option<&AccountId> {118 match self {119 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),120 _ => None,121 }122 }123124 pub fn confirmed(&self) -> bool {125 matches!(self, Self::Confirmed(_))126 }127}128129impl<T> Default for SponsorshipState<T> {130 fn default() -> Self {131 Self::Disabled132 }133}134135#[derive(Encode, Decode, Clone, PartialEq)]136#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]137pub struct Collection<T: frame_system::Config> {138 pub owner: T::AccountId,139 pub mode: CollectionMode,140 pub access: AccessMode,141 pub decimal_points: DecimalPoints,142 pub name: Vec<u16>, 143 pub description: Vec<u16>, 144 pub token_prefix: Vec<u8>, 145 pub mint_mode: bool,146 pub offchain_schema: Vec<u8>,147 pub schema_version: SchemaVersion,148 pub sponsorship: SponsorshipState<T::AccountId>,149 pub limits: CollectionLimits<T::BlockNumber>, 150 pub variable_on_chain_schema: Vec<u8>, 151 pub const_on_chain_schema: Vec<u8>, 152 pub transfers_enabled: bool,153}154155#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)]156pub struct NftItemType<AccountId> {157 pub owner: AccountId,158 pub const_data: Vec<u8>,159 pub variable_data: Vec<u8>,160}161162#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, Serialize, Deserialize)]163pub struct FungibleItemType {164 pub value: u128,165}166167#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)]168pub struct ReFungibleItemType<AccountId> {169 pub owner: Vec<Ownership<AccountId>>,170 pub const_data: Vec<u8>,171 pub variable_data: Vec<u8>,172}173174#[derive(Encode, Decode, Debug, Clone, PartialEq, Serialize, Deserialize)]175pub struct CollectionLimits<BlockNumber: Encode + Decode> {176 pub account_token_ownership_limit: u32,177 pub sponsored_data_size: u32,178 179 180 181 pub sponsored_data_rate_limit: Option<BlockNumber>,182 pub token_limit: u32,183184 185 pub sponsor_transfer_timeout: u32,186 pub owner_can_transfer: bool,187 pub owner_can_destroy: bool,188}189190impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {191 fn default() -> Self {192 Self {193 account_token_ownership_limit: 10_000_000,194 token_limit: u32::max_value(),195 sponsored_data_size: u32::MAX,196 sponsored_data_rate_limit: None,197 sponsor_transfer_timeout: 14400,198 owner_can_transfer: true,199 owner_can_destroy: true,200 }201 }202}203204#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, Serialize, Deserialize)]205pub struct ChainLimits {206 pub collection_numbers_limit: u32,207 pub account_token_ownership_limit: u32,208 pub collections_admins_limit: u64,209 pub custom_data_limit: u32,210211 212 pub nft_sponsor_transfer_timeout: u32,213 pub fungible_sponsor_transfer_timeout: u32,214 pub refungible_sponsor_transfer_timeout: u32,215216 217 pub offchain_schema_limit: u32,218 pub variable_on_chain_schema_limit: u32,219 pub const_on_chain_schema_limit: u32,220}221222223mod bounded_serde {224 use core::convert::TryFrom;225 use frame_support::{BoundedVec, traits::Get};226 use serde::{227 ser::{self, Serialize},228 de::{self, Deserialize, Error},229 };230 use sp_std::vec::Vec;231232 pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>233 where234 D: ser::Serializer,235 V: Serialize,236 {237 let vec: &Vec<_> = &value;238 vec.serialize(serializer)239 }240241 pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>242 where243 D: de::Deserializer<'de>,244 V: de::Deserialize<'de>,245 S: Get<u32>,246 {247 248 let vec = <Vec<V>>::deserialize(deserializer)?;249 let len = vec.len();250 TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))251 }252}253254#[derive(255 Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq, Serialize, Deserialize,256)]257#[derivative(Debug)]258pub struct CreateNftData {259 #[serde(with = "bounded_serde")]260 #[derivative(Debug = "ignore")]261 pub const_data: BoundedVec<u8, MaxDataSize>,262 #[serde(with = "bounded_serde")]263 #[derivative(Debug = "ignore")]264 pub variable_data: BoundedVec<u8, MaxDataSize>,265}266267#[derive(268 Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, Serialize, Deserialize,269)]270pub struct CreateFungibleData {271 pub value: u128,272}273274#[derive(275 Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq, Serialize, Deserialize,276)]277#[derivative(Debug)]278pub struct CreateReFungibleData {279 #[serde(with = "bounded_serde")]280 #[derivative(Debug = "ignore")]281 pub const_data: BoundedVec<u8, MaxDataSize>,282 #[serde(with = "bounded_serde")]283 #[derivative(Debug = "ignore")]284 pub variable_data: BoundedVec<u8, MaxDataSize>,285 pub pieces: u128,286}287288#[derive(Encode, Decode, MaxEncodedLen, Debug, Clone, PartialEq, Serialize, Deserialize)]289pub enum CreateItemData {290 NFT(CreateNftData),291 Fungible(CreateFungibleData),292 ReFungible(CreateReFungibleData),293}294295impl CreateItemData {296 pub fn data_size(&self) -> usize {297 match self {298 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),299 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),300 _ => 0,301 }302 }303}304305impl From<CreateNftData> for CreateItemData {306 fn from(item: CreateNftData) -> Self {307 CreateItemData::NFT(item)308 }309}310311impl From<CreateReFungibleData> for CreateItemData {312 fn from(item: CreateReFungibleData) -> Self {313 CreateItemData::ReFungible(item)314 }315}316317impl From<CreateFungibleData> for CreateItemData {318 fn from(item: CreateFungibleData) -> Self {319 CreateItemData::Fungible(item)320 }321}