1#![cfg_attr(not(feature = "std"), no_std)]23#[cfg(feature = "serde")]4pub use serde::{Serialize, Deserialize};56use sp_runtime::sp_std::prelude::Vec;7use codec::{Decode, Encode};8use max_encoded_len::MaxEncodedLen;9pub use frame_support::{10 BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,11 dispatch::DispatchResult,12 ensure, fail, parameter_types,13 traits::{14 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,15 Randomness, IsSubType, WithdrawReasons,16 },17 weights::{18 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},19 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,20 WeightToFeePolynomial, DispatchClass,21 },22 StorageValue, transactional,23};24use derivative::Derivative;2526pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;27pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;28pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;29pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;30313233parameter_types! {34pub const MaxDataSize: u32 = 2048;3536pub const MaxItemsPerBatch: u32 = 200;37}3839pub type CollectionId = u32;40pub type TokenId = u32;41pub type DecimalPoints = u8;4243#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]44#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]45pub enum CollectionMode {46 Invalid,47 NFT,48 49 Fungible(DecimalPoints),50 ReFungible,51}5253impl Default for CollectionMode {54 fn default() -> Self {55 Self::Invalid56 }57}5859impl CollectionMode {60 pub fn id(&self) -> u8 {61 match self {62 CollectionMode::Invalid => 0,63 CollectionMode::NFT => 1,64 CollectionMode::Fungible(_) => 2,65 CollectionMode::ReFungible => 3,66 }67 }68}6970pub trait SponsoringResolve<AccountId, Call> {71 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;72}7374#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]75#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]76pub enum AccessMode {77 Normal,78 WhiteList,79}80impl Default for AccessMode {81 fn default() -> Self {82 Self::Normal83 }84}8586#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]87#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]88pub enum SchemaVersion {89 ImageURL,90 Unique,91}92impl Default for SchemaVersion {93 fn default() -> Self {94 Self::ImageURL95 }96}9798#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]99#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]100pub struct Ownership<AccountId> {101 pub owner: AccountId,102 pub fraction: u128,103}104105#[derive(Encode, Decode, Debug, Clone, PartialEq)]106#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]107pub enum SponsorshipState<AccountId> {108 109 Disabled,110 Unconfirmed(AccountId),111 112 Confirmed(AccountId),113}114115impl<AccountId> SponsorshipState<AccountId> {116 pub fn sponsor(&self) -> Option<&AccountId> {117 match self {118 Self::Confirmed(sponsor) => Some(sponsor),119 _ => None,120 }121 }122123 pub fn pending_sponsor(&self) -> Option<&AccountId> {124 match self {125 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),126 _ => None,127 }128 }129130 pub fn confirmed(&self) -> bool {131 matches!(self, Self::Confirmed(_))132 }133}134135impl<T> Default for SponsorshipState<T> {136 fn default() -> Self {137 Self::Disabled138 }139}140141#[derive(Encode, Decode, Clone, PartialEq)]142#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]143pub struct Collection<T: frame_system::Config> {144 pub owner: T::AccountId,145 pub mode: CollectionMode,146 pub access: AccessMode,147 pub decimal_points: DecimalPoints,148 pub name: Vec<u16>, 149 pub description: Vec<u16>, 150 pub token_prefix: Vec<u8>, 151 pub mint_mode: bool,152 pub offchain_schema: Vec<u8>,153 pub schema_version: SchemaVersion,154 pub sponsorship: SponsorshipState<T::AccountId>,155 pub limits: CollectionLimits<T::BlockNumber>, 156 pub variable_on_chain_schema: Vec<u8>, 157 pub const_on_chain_schema: Vec<u8>, 158 pub transfers_enabled: bool,159}160161#[derive(Encode, Decode, Debug, Clone, PartialEq)]162#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]163pub struct NftItemType<AccountId> {164 pub owner: AccountId,165 pub const_data: Vec<u8>,166 pub variable_data: Vec<u8>,167}168169#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]170#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]171pub struct FungibleItemType {172 pub value: u128,173}174175#[derive(Encode, Decode, Debug, Clone, PartialEq)]176#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]177pub struct ReFungibleItemType<AccountId> {178 pub owner: Vec<Ownership<AccountId>>,179 pub const_data: Vec<u8>,180 pub variable_data: Vec<u8>,181}182183#[derive(Encode, Decode, Debug, Clone, PartialEq)]184#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]185pub struct CollectionLimits<BlockNumber: Encode + Decode> {186 pub account_token_ownership_limit: u32,187 pub sponsored_data_size: u32,188 189 190 191 pub sponsored_data_rate_limit: Option<BlockNumber>,192 pub token_limit: u32,193194 195 pub sponsor_transfer_timeout: u32,196 pub owner_can_transfer: bool,197 pub owner_can_destroy: bool,198}199200impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {201 fn default() -> Self {202 Self {203 account_token_ownership_limit: 10_000_000,204 token_limit: u32::max_value(),205 sponsored_data_size: u32::MAX,206 sponsored_data_rate_limit: None,207 sponsor_transfer_timeout: 14400,208 owner_can_transfer: true,209 owner_can_destroy: true,210 }211 }212}213214#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct ChainLimits {217 pub collection_numbers_limit: u32,218 pub account_token_ownership_limit: u32,219 pub collections_admins_limit: u64,220 pub custom_data_limit: u32,221222 223 pub nft_sponsor_transfer_timeout: u32,224 pub fungible_sponsor_transfer_timeout: u32,225 pub refungible_sponsor_transfer_timeout: u32,226227 228 pub offchain_schema_limit: u32,229 pub variable_on_chain_schema_limit: u32,230 pub const_on_chain_schema_limit: u32,231}232233234#[cfg(feature = "serde1")]235mod bounded_serde {236 use core::convert::TryFrom;237 use frame_support::{BoundedVec, traits::Get};238 use serde::{239 ser::{self, Serialize},240 de::{self, Deserialize, Error},241 };242 use sp_std::vec::Vec;243244 pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>245 where246 D: ser::Serializer,247 V: Serialize,248 {249 let vec: &Vec<_> = &value;250 vec.serialize(serializer)251 }252253 pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>254 where255 D: de::Deserializer<'de>,256 V: de::Deserialize<'de>,257 S: Get<u32>,258 {259 260 let vec = <Vec<V>>::deserialize(deserializer)?;261 let len = vec.len();262 TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))263 }264}265266#[derive(Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq)]267#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]268#[derivative(Debug)]269pub struct CreateNftData {270 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]271 #[derivative(Debug = "ignore")]272 pub const_data: BoundedVec<u8, MaxDataSize>,273 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]274 #[derivative(Debug = "ignore")]275 pub variable_data: BoundedVec<u8, MaxDataSize>,276}277278#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)]279#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]280pub struct CreateFungibleData {281 pub value: u128,282}283284#[derive(Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq)]285#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]286#[derivative(Debug)]287pub struct CreateReFungibleData {288 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]289 #[derivative(Debug = "ignore")]290 pub const_data: BoundedVec<u8, MaxDataSize>,291 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]292 #[derivative(Debug = "ignore")]293 pub variable_data: BoundedVec<u8, MaxDataSize>,294 pub pieces: u128,295}296297#[derive(Encode, Decode, MaxEncodedLen, Debug, Clone, PartialEq)]298#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]299pub enum CreateItemData {300 NFT(CreateNftData),301 Fungible(CreateFungibleData),302 ReFungible(CreateReFungibleData),303}304305impl CreateItemData {306 pub fn data_size(&self) -> usize {307 match self {308 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),309 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),310 _ => 0,311 }312 }313}314315impl From<CreateNftData> for CreateItemData {316 fn from(item: CreateNftData) -> Self {317 CreateItemData::NFT(item)318 }319}320321impl From<CreateReFungibleData> for CreateItemData {322 fn from(item: CreateReFungibleData) -> Self {323 CreateItemData::ReFungible(item)324 }325}326327impl From<CreateFungibleData> for CreateItemData {328 fn from(item: CreateFungibleData) -> Self {329 CreateItemData::Fungible(item)330 }331}