difftreelog
doc: architectural changes
in: master
10 files changed
client/rpc/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original License18use std::sync::Arc;1920use codec::{Decode, Encode};21use jsonrpsee::{22 core::{RpcResult as Result},23 proc_macros::rpc,24};25use anyhow::anyhow;26use up_data_structs::{27 RpcCollection, CollectionId, CollectionStats, CollectionLimits, TokenId, Property,28 PropertyKeyPermission, TokenData, TokenChild,29};30use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt};31use sp_blockchain::HeaderBackend;32use up_rpc::UniqueApi as UniqueRuntimeApi;3334// RMRK35use rmrk_rpc::RmrkApi as RmrkRuntimeApi;36use up_data_structs::{37 RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,38};3940pub use rmrk_unique_rpc::RmrkApiServer;4142#[rpc(server)]43#[async_trait]44pub trait UniqueApi<BlockHash, CrossAccountId, AccountId> {45 #[method(name = "unique_accountTokens")]46 fn account_tokens(47 &self,48 collection: CollectionId,49 account: CrossAccountId,50 at: Option<BlockHash>,51 ) -> Result<Vec<TokenId>>;52 #[method(name = "unique_collectionTokens")]53 fn collection_tokens(54 &self,55 collection: CollectionId,56 at: Option<BlockHash>,57 ) -> Result<Vec<TokenId>>;58 #[method(name = "unique_tokenExists")]59 fn token_exists(60 &self,61 collection: CollectionId,62 token: TokenId,63 at: Option<BlockHash>,64 ) -> Result<bool>;6566 #[method(name = "unique_tokenOwner")]67 fn token_owner(68 &self,69 collection: CollectionId,70 token: TokenId,71 at: Option<BlockHash>,72 ) -> Result<Option<CrossAccountId>>;73 #[method(name = "unique_topmostTokenOwner")]74 fn topmost_token_owner(75 &self,76 collection: CollectionId,77 token: TokenId,78 at: Option<BlockHash>,79 ) -> Result<Option<CrossAccountId>>;80 #[method(name = "unique_tokenChildren")]81 fn token_children(82 &self,83 collection: CollectionId,84 token: TokenId,85 at: Option<BlockHash>,86 ) -> Result<Vec<TokenChild>>;8788 #[method(name = "unique_collectionProperties")]89 fn collection_properties(90 &self,91 collection: CollectionId,92 keys: Option<Vec<String>>,93 at: Option<BlockHash>,94 ) -> Result<Vec<Property>>;9596 #[method(name = "unique_tokenProperties")]97 fn token_properties(98 &self,99 collection: CollectionId,100 token_id: TokenId,101 keys: Option<Vec<String>>,102 at: Option<BlockHash>,103 ) -> Result<Vec<Property>>;104105 #[method(name = "unique_propertyPermissions")]106 fn property_permissions(107 &self,108 collection: CollectionId,109 keys: Option<Vec<String>>,110 at: Option<BlockHash>,111 ) -> Result<Vec<PropertyKeyPermission>>;112113 #[method(name = "unique_tokenData")]114 fn token_data(115 &self,116 collection: CollectionId,117 token_id: TokenId,118 keys: Option<Vec<String>>,119 at: Option<BlockHash>,120 ) -> Result<TokenData<CrossAccountId>>;121122 #[method(name = "unique_totalSupply")]123 fn total_supply(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<u32>;124 #[method(name = "unique_accountBalance")]125 fn account_balance(126 &self,127 collection: CollectionId,128 account: CrossAccountId,129 at: Option<BlockHash>,130 ) -> Result<u32>;131 #[method(name = "unique_balance")]132 fn balance(133 &self,134 collection: CollectionId,135 account: CrossAccountId,136 token: TokenId,137 at: Option<BlockHash>,138 ) -> Result<String>;139 #[method(name = "unique_allowance")]140 fn allowance(141 &self,142 collection: CollectionId,143 sender: CrossAccountId,144 spender: CrossAccountId,145 token: TokenId,146 at: Option<BlockHash>,147 ) -> Result<String>;148149 #[method(name = "unique_adminlist")]150 fn adminlist(151 &self,152 collection: CollectionId,153 at: Option<BlockHash>,154 ) -> Result<Vec<CrossAccountId>>;155 #[method(name = "unique_allowlist")]156 fn allowlist(157 &self,158 collection: CollectionId,159 at: Option<BlockHash>,160 ) -> Result<Vec<CrossAccountId>>;161 #[method(name = "unique_allowed")]162 fn allowed(163 &self,164 collection: CollectionId,165 user: CrossAccountId,166 at: Option<BlockHash>,167 ) -> Result<bool>;168 #[method(name = "unique_lastTokenId")]169 fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;170 #[method(name = "unique_collectionById")]171 fn collection_by_id(172 &self,173 collection: CollectionId,174 at: Option<BlockHash>,175 ) -> Result<Option<RpcCollection<AccountId>>>;176 #[method(name = "unique_collectionStats")]177 fn collection_stats(&self, at: Option<BlockHash>) -> Result<CollectionStats>;178179 #[method(name = "unique_nextSponsored")]180 fn next_sponsored(181 &self,182 collection: CollectionId,183 account: CrossAccountId,184 token: TokenId,185 at: Option<BlockHash>,186 ) -> Result<Option<u64>>;187188 #[method(name = "unique_effectiveCollectionLimits")]189 fn effective_collection_limits(190 &self,191 collection_id: CollectionId,192 at: Option<BlockHash>,193 ) -> Result<Option<CollectionLimits>>;194195 #[method(name = "unique_totalPieces")]196 fn total_pieces(197 &self,198 collection_id: CollectionId,199 token_id: TokenId,200 at: Option<BlockHash>,201 ) -> Result<Option<u128>>;202}203204mod rmrk_unique_rpc {205 use super::*;206207 #[rpc(server)]208 #[async_trait]209 pub trait RmrkApi<210 BlockHash,211 AccountId,212 CollectionInfo,213 NftInfo,214 ResourceInfo,215 PropertyInfo,216 BaseInfo,217 PartType,218 Theme,219 >220 {221 #[method(name = "rmrk_lastCollectionIdx")]222 /// Get the latest created collection id223 fn last_collection_idx(&self, at: Option<BlockHash>) -> Result<RmrkCollectionId>;224225 #[method(name = "rmrk_collectionById")]226 /// Get collection by id227 fn collection_by_id(228 &self,229 id: RmrkCollectionId,230 at: Option<BlockHash>,231 ) -> Result<Option<CollectionInfo>>;232233 #[method(name = "rmrk_nftById")]234 /// Get NFT by collection id and NFT id235 fn nft_by_id(236 &self,237 collection_id: RmrkCollectionId,238 nft_id: RmrkNftId,239 at: Option<BlockHash>,240 ) -> Result<Option<NftInfo>>;241242 #[method(name = "rmrk_accountTokens")]243 /// Get tokens owned by an account in a collection244 fn account_tokens(245 &self,246 account_id: AccountId,247 collection_id: RmrkCollectionId,248 at: Option<BlockHash>,249 ) -> Result<Vec<RmrkNftId>>;250251 #[method(name = "rmrk_nftChildren")]252 /// Get NFT children253 fn nft_children(254 &self,255 collection_id: RmrkCollectionId,256 nft_id: RmrkNftId,257 at: Option<BlockHash>,258 ) -> Result<Vec<RmrkNftChild>>;259260 #[method(name = "rmrk_collectionProperties")]261 /// Get collection properties262 fn collection_properties(263 &self,264 collection_id: RmrkCollectionId,265 filter_keys: Option<Vec<String>>,266 at: Option<BlockHash>,267 ) -> Result<Vec<PropertyInfo>>;268269 #[method(name = "rmrk_nftProperties")]270 /// Get NFT properties271 fn nft_properties(272 &self,273 collection_id: RmrkCollectionId,274 nft_id: RmrkNftId,275 filter_keys: Option<Vec<String>>,276 at: Option<BlockHash>,277 ) -> Result<Vec<PropertyInfo>>;278279 #[method(name = "rmrk_nftResources")]280 /// Get NFT resources281 fn nft_resources(282 &self,283 collection_id: RmrkCollectionId,284 nft_id: RmrkNftId,285 at: Option<BlockHash>,286 ) -> Result<Vec<ResourceInfo>>;287288 #[method(name = "rmrk_nftResourcePriority")]289 /// Get NFT resource priority290 fn nft_resource_priority(291 &self,292 collection_id: RmrkCollectionId,293 nft_id: RmrkNftId,294 resource_id: RmrkResourceId,295 at: Option<BlockHash>,296 ) -> Result<Option<u32>>;297298 #[method(name = "rmrk_base")]299 /// Get base info300 fn base(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Option<BaseInfo>>;301302 #[method(name = "rmrk_baseParts")]303 /// Get all Base's parts304 fn base_parts(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Vec<PartType>>;305306 #[method(name = "rmrk_themeNames")]307 fn theme_names(308 &self,309 base_id: RmrkBaseId,310 at: Option<BlockHash>,311 ) -> Result<Vec<RmrkThemeName>>;312313 #[method(name = "rmrk_themes")]314 fn theme(315 &self,316 base_id: RmrkBaseId,317 theme_name: String,318 filter_keys: Option<Vec<String>>,319 at: Option<BlockHash>,320 ) -> Result<Option<Theme>>;321 }322}323324pub struct Unique<C, P> {325 client: Arc<C>,326 _marker: std::marker::PhantomData<P>,327}328329impl<C, P> Unique<C, P> {330 pub fn new(client: Arc<C>) -> Self {331 Self {332 client,333 _marker: Default::default(),334 }335 }336}337338pub struct Rmrk<C, P> {339 client: Arc<C>,340 _marker: std::marker::PhantomData<P>,341}342343impl<C, P> Rmrk<C, P> {344 pub fn new(client: Arc<C>) -> Self {345 Self {346 client,347 _marker: Default::default(),348 }349 }350}351352macro_rules! pass_method {353 (354 $method_name:ident(355 $($(#[map(|$map_arg:ident| $map:expr)])? $name:ident: $ty:ty),* $(,)?356 ) -> $result:ty $(=> $mapper:expr)?,357 //$runtime_name:ident $(<$($lt: tt),+>)*358 $runtime_api_macro:ident359 $(; changed_in $ver:expr, $changed_method_name:ident ($($changed_name:expr), * $(,)?) => $fixer:expr)*360 ) => {361 fn $method_name(362 &self,363 $(364 $name: $ty,365 )*366 at: Option<<Block as BlockT>::Hash>,367 ) -> Result<$result> {368 let api = self.client.runtime_api();369 let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));370 let _api_version = if let Ok(Some(api_version)) =371 api.api_version::<$runtime_api_macro!()>(&at)372 {373 api_version374 } else {375 // unreachable for our runtime376 return Err(anyhow!("api is not available").into())377 };378379 let result = $(if _api_version < $ver {380 api.$changed_method_name(&at, $($changed_name),*).map(|r| r.map($fixer))381 } else)*382 { api.$method_name(&at, $($((|$map_arg: $ty| $map))? ($name)),*) };383384 Ok(result385 .map_err(|e| anyhow!("unable to query: {e}"))?386 .map_err(|e| anyhow!("runtime error: {e:?}"))$(.map($mapper))??)387 }388 };389}390391macro_rules! unique_api {392 () => {393 dyn UniqueRuntimeApi<Block, CrossAccountId, AccountId>394 };395}396397macro_rules! rmrk_api {398 () => {399 dyn RmrkRuntimeApi<Block, AccountId, CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme>400 };401}402403#[allow(deprecated)]404impl<C, Block, CrossAccountId, AccountId>405 UniqueApiServer<<Block as BlockT>::Hash, CrossAccountId, AccountId> for Unique<C, Block>406where407 Block: BlockT,408 AccountId: Decode,409 C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,410 C::Api: UniqueRuntimeApi<Block, CrossAccountId, AccountId>,411 CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,412{413 pass_method!(414 account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>, unique_api415 );416 pass_method!(417 collection_tokens(collection: CollectionId) -> Vec<TokenId>, unique_api418 );419 pass_method!(420 token_exists(collection: CollectionId, token: TokenId) -> bool, unique_api421 );422 pass_method!(423 token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>, unique_api424 );425 pass_method!(426 topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>, unique_api427 );428 pass_method!(token_children(collection: CollectionId, token: TokenId) -> Vec<TokenChild>, unique_api);429 pass_method!(total_supply(collection: CollectionId) -> u32, unique_api);430 pass_method!(account_balance(collection: CollectionId, account: CrossAccountId) -> u32, unique_api);431 pass_method!(balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> String => |v| v.to_string(), unique_api);432 pass_method!(433 allowance(collection: CollectionId, sender: CrossAccountId, spender: CrossAccountId, token: TokenId) -> String => |v| v.to_string(),434 unique_api435 );436437 pass_method!(collection_properties(438 collection: CollectionId,439440 #[map(|keys| string_keys_to_bytes_keys(keys))]441 keys: Option<Vec<String>>442 ) -> Vec<Property>, unique_api);443444 pass_method!(token_properties(445 collection: CollectionId,446 token_id: TokenId,447448 #[map(|keys| string_keys_to_bytes_keys(keys))]449 keys: Option<Vec<String>>450 ) -> Vec<Property>, unique_api);451452 pass_method!(property_permissions(453 collection: CollectionId,454455 #[map(|keys| string_keys_to_bytes_keys(keys))]456 keys: Option<Vec<String>>457 ) -> Vec<PropertyKeyPermission>, unique_api);458459 pass_method!(token_data(460 collection: CollectionId,461 token_id: TokenId,462463 #[map(|keys| string_keys_to_bytes_keys(keys))]464 keys: Option<Vec<String>>,465 ) -> TokenData<CrossAccountId>, unique_api);466467 pass_method!(adminlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);468 pass_method!(allowlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);469 pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool, unique_api);470 pass_method!(last_token_id(collection: CollectionId) -> TokenId, unique_api);471 pass_method!(collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api);472 pass_method!(collection_stats() -> CollectionStats, unique_api);473 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);474 pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);475 pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128>, unique_api);476}477478#[allow(deprecated)]479impl<480 C,481 Block,482 AccountId,483 CollectionInfo,484 NftInfo,485 ResourceInfo,486 PropertyInfo,487 BaseInfo,488 PartType,489 Theme,490 >491 rmrk_unique_rpc::RmrkApiServer<492 <Block as BlockT>::Hash,493 AccountId,494 CollectionInfo,495 NftInfo,496 ResourceInfo,497 PropertyInfo,498 BaseInfo,499 PartType,500 Theme,501 > for Rmrk<C, Block>502where503 C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,504 C::Api: RmrkRuntimeApi<505 Block,506 AccountId,507 CollectionInfo,508 NftInfo,509 ResourceInfo,510 PropertyInfo,511 BaseInfo,512 PartType,513 Theme,514 >,515 AccountId: Decode + Encode,516 CollectionInfo: Decode,517 NftInfo: Decode,518 ResourceInfo: Decode,519 PropertyInfo: Decode,520 BaseInfo: Decode,521 PartType: Decode,522 Theme: Decode,523 Block: BlockT,524{525 pass_method!(last_collection_idx() -> RmrkCollectionId, rmrk_api);526 pass_method!(collection_by_id(id: RmrkCollectionId) -> Option<CollectionInfo>, rmrk_api);527 pass_method!(nft_by_id(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Option<NftInfo>, rmrk_api);528 pass_method!(account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Vec<RmrkNftId>, rmrk_api);529 pass_method!(nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<RmrkNftChild>, rmrk_api);530 pass_method!(531 collection_properties(532 collection_id: RmrkCollectionId,533534 #[map(|keys| string_keys_to_bytes_keys(keys))]535 filter_keys: Option<Vec<String>>536 ) -> Vec<PropertyInfo>,537 rmrk_api538 );539 pass_method!(540 nft_properties(541 collection_id: RmrkCollectionId,542 nft_id: RmrkNftId,543544 #[map(|keys| string_keys_to_bytes_keys(keys))]545 filter_keys: Option<Vec<String>>546 ) -> Vec<PropertyInfo>,547 rmrk_api548 );549 pass_method!(nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<ResourceInfo>, rmrk_api);550 pass_method!(nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Option<u32>, rmrk_api);551 pass_method!(base(base_id: RmrkBaseId) -> Option<BaseInfo>, rmrk_api);552 pass_method!(base_parts(base_id: RmrkBaseId) -> Vec<PartType>, rmrk_api);553 pass_method!(theme_names(base_id: RmrkBaseId) -> Vec<RmrkThemeName>, rmrk_api);554 pass_method!(555 theme(556 base_id: RmrkBaseId,557558 #[map(|n| n.into_bytes())]559 theme_name: String,560561 #[map(|keys| string_keys_to_bytes_keys(keys))]562 filter_keys: Option<Vec<String>>563 ) -> Option<Theme>, rmrk_api);564}565566fn string_keys_to_bytes_keys(keys: Option<Vec<String>>) -> Option<Vec<Vec<u8>>> {567 keys.map(|keys| keys.into_iter().map(|key| key.into_bytes()).collect())568}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original License18use std::sync::Arc;1920use codec::{Decode, Encode};21use jsonrpsee::{22 core::{RpcResult as Result},23 proc_macros::rpc,24};25use anyhow::anyhow;26use up_data_structs::{27 RpcCollection, CollectionId, CollectionStats, CollectionLimits, TokenId, Property,28 PropertyKeyPermission, TokenData, TokenChild,29};30use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt};31use sp_blockchain::HeaderBackend;32use up_rpc::UniqueApi as UniqueRuntimeApi;3334// RMRK35use rmrk_rpc::RmrkApi as RmrkRuntimeApi;36use up_data_structs::{37 RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,38};3940pub use rmrk_unique_rpc::RmrkApiServer;4142#[rpc(server)]43#[async_trait]44pub trait UniqueApi<BlockHash, CrossAccountId, AccountId> {45 /// Get tokens owned by account46 #[method(name = "unique_accountTokens")]47 fn account_tokens(48 &self,49 collection: CollectionId,50 account: CrossAccountId,51 at: Option<BlockHash>,52 ) -> Result<Vec<TokenId>>;53 /// Get tokens contained in collection54 #[method(name = "unique_collectionTokens")]55 fn collection_tokens(56 &self,57 collection: CollectionId,58 at: Option<BlockHash>,59 ) -> Result<Vec<TokenId>>;60 /// Check if token exists61 #[method(name = "unique_tokenExists")]62 fn token_exists(63 &self,64 collection: CollectionId,65 token: TokenId,66 at: Option<BlockHash>,67 ) -> Result<bool>;68 /// Get token owner69 #[method(name = "unique_tokenOwner")]70 fn token_owner(71 &self,72 collection: CollectionId,73 token: TokenId,74 at: Option<BlockHash>,75 ) -> Result<Option<CrossAccountId>>;76 /// Get token owner, in case of nested token - find the parent recursively77 #[method(name = "unique_topmostTokenOwner")]78 fn topmost_token_owner(79 &self,80 collection: CollectionId,81 token: TokenId,82 at: Option<BlockHash>,83 ) -> Result<Option<CrossAccountId>>;84 /// Get tokens nested directly into the token85 #[method(name = "unique_tokenChildren")]86 fn token_children(87 &self,88 collection: CollectionId,89 token: TokenId,90 at: Option<BlockHash>,91 ) -> Result<Vec<TokenChild>>;92 /// Get collection properties93 #[method(name = "unique_collectionProperties")]94 fn collection_properties(95 &self,96 collection: CollectionId,97 keys: Option<Vec<String>>,98 at: Option<BlockHash>,99 ) -> Result<Vec<Property>>;100 /// Get token properties101 #[method(name = "unique_tokenProperties")]102 fn token_properties(103 &self,104 collection: CollectionId,105 token_id: TokenId,106 keys: Option<Vec<String>>,107 at: Option<BlockHash>,108 ) -> Result<Vec<Property>>;109 /// Get property permissions110 #[method(name = "unique_propertyPermissions")]111 fn property_permissions(112 &self,113 collection: CollectionId,114 keys: Option<Vec<String>>,115 at: Option<BlockHash>,116 ) -> Result<Vec<PropertyKeyPermission>>;117 /// Get token data118 #[method(name = "unique_tokenData")]119 fn token_data(120 &self,121 collection: CollectionId,122 token_id: TokenId,123 keys: Option<Vec<String>>,124 at: Option<BlockHash>,125 ) -> Result<TokenData<CrossAccountId>>;126 /// Get amount of unique collection tokens127 #[method(name = "unique_totalSupply")]128 fn total_supply(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<u32>;129 /// Get owned amount of any user tokens130 #[method(name = "unique_accountBalance")]131 fn account_balance(132 &self,133 collection: CollectionId,134 account: CrossAccountId,135 at: Option<BlockHash>,136 ) -> Result<u32>;137 /// Get owned amount of specific account token138 #[method(name = "unique_balance")]139 fn balance(140 &self,141 collection: CollectionId,142 account: CrossAccountId,143 token: TokenId,144 at: Option<BlockHash>,145 ) -> Result<String>;146 /// Get allowed amount147 #[method(name = "unique_allowance")]148 fn allowance(149 &self,150 collection: CollectionId,151 sender: CrossAccountId,152 spender: CrossAccountId,153 token: TokenId,154 at: Option<BlockHash>,155 ) -> Result<String>;156 /// Get admin list157 #[method(name = "unique_adminlist")]158 fn adminlist(159 &self,160 collection: CollectionId,161 at: Option<BlockHash>,162 ) -> Result<Vec<CrossAccountId>>;163 /// Get allowlist164 #[method(name = "unique_allowlist")]165 fn allowlist(166 &self,167 collection: CollectionId,168 at: Option<BlockHash>,169 ) -> Result<Vec<CrossAccountId>>;170 /// Check if user is allowed to use collection171 #[method(name = "unique_allowed")]172 fn allowed(173 &self,174 collection: CollectionId,175 user: CrossAccountId,176 at: Option<BlockHash>,177 ) -> Result<bool>;178 /// Get last token ID created in a collection179 #[method(name = "unique_lastTokenId")]180 fn last_token_id(&self, collection: CollectionId, at: Option<BlockHash>) -> Result<TokenId>;181 /// Get collection by specified ID182 #[method(name = "unique_collectionById")]183 fn collection_by_id(184 &self,185 collection: CollectionId,186 at: Option<BlockHash>,187 ) -> Result<Option<RpcCollection<AccountId>>>;188 /// Get collection stats189 #[method(name = "unique_collectionStats")]190 fn collection_stats(&self, at: Option<BlockHash>) -> Result<CollectionStats>;191 /// Get number of blocks when sponsored transaction is available192 #[method(name = "unique_nextSponsored")]193 fn next_sponsored(194 &self,195 collection: CollectionId,196 account: CrossAccountId,197 token: TokenId,198 at: Option<BlockHash>,199 ) -> Result<Option<u64>>;200 /// Get effective collection limits201 #[method(name = "unique_effectiveCollectionLimits")]202 fn effective_collection_limits(203 &self,204 collection_id: CollectionId,205 at: Option<BlockHash>,206 ) -> Result<Option<CollectionLimits>>;207 /// Get total pieces of token208 #[method(name = "unique_totalPieces")]209 fn total_pieces(210 &self,211 collection_id: CollectionId,212 token_id: TokenId,213 at: Option<BlockHash>,214 ) -> Result<Option<u128>>;215}216217mod rmrk_unique_rpc {218 use super::*;219220 #[rpc(server)]221 #[async_trait]222 pub trait RmrkApi<223 BlockHash,224 AccountId,225 CollectionInfo,226 NftInfo,227 ResourceInfo,228 PropertyInfo,229 BaseInfo,230 PartType,231 Theme,232 >233 {234 #[method(name = "rmrk_lastCollectionIdx")]235 /// Get the latest created collection id236 fn last_collection_idx(&self, at: Option<BlockHash>) -> Result<RmrkCollectionId>;237238 #[method(name = "rmrk_collectionById")]239 /// Get collection by id240 fn collection_by_id(241 &self,242 id: RmrkCollectionId,243 at: Option<BlockHash>,244 ) -> Result<Option<CollectionInfo>>;245246 #[method(name = "rmrk_nftById")]247 /// Get NFT by collection id and NFT id248 fn nft_by_id(249 &self,250 collection_id: RmrkCollectionId,251 nft_id: RmrkNftId,252 at: Option<BlockHash>,253 ) -> Result<Option<NftInfo>>;254255 #[method(name = "rmrk_accountTokens")]256 /// Get tokens owned by an account in a collection257 fn account_tokens(258 &self,259 account_id: AccountId,260 collection_id: RmrkCollectionId,261 at: Option<BlockHash>,262 ) -> Result<Vec<RmrkNftId>>;263264 #[method(name = "rmrk_nftChildren")]265 /// Get NFT children266 fn nft_children(267 &self,268 collection_id: RmrkCollectionId,269 nft_id: RmrkNftId,270 at: Option<BlockHash>,271 ) -> Result<Vec<RmrkNftChild>>;272273 #[method(name = "rmrk_collectionProperties")]274 /// Get collection properties275 fn collection_properties(276 &self,277 collection_id: RmrkCollectionId,278 filter_keys: Option<Vec<String>>,279 at: Option<BlockHash>,280 ) -> Result<Vec<PropertyInfo>>;281282 #[method(name = "rmrk_nftProperties")]283 /// Get NFT properties284 fn nft_properties(285 &self,286 collection_id: RmrkCollectionId,287 nft_id: RmrkNftId,288 filter_keys: Option<Vec<String>>,289 at: Option<BlockHash>,290 ) -> Result<Vec<PropertyInfo>>;291292 #[method(name = "rmrk_nftResources")]293 /// Get NFT resources294 fn nft_resources(295 &self,296 collection_id: RmrkCollectionId,297 nft_id: RmrkNftId,298 at: Option<BlockHash>,299 ) -> Result<Vec<ResourceInfo>>;300301 #[method(name = "rmrk_nftResourcePriority")]302 /// Get NFT resource priority303 fn nft_resource_priority(304 &self,305 collection_id: RmrkCollectionId,306 nft_id: RmrkNftId,307 resource_id: RmrkResourceId,308 at: Option<BlockHash>,309 ) -> Result<Option<u32>>;310311 #[method(name = "rmrk_base")]312 /// Get base info313 fn base(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Option<BaseInfo>>;314315 #[method(name = "rmrk_baseParts")]316 /// Get all Base's parts317 fn base_parts(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Vec<PartType>>;318319 #[method(name = "rmrk_themeNames")]320 /// Get Base's theme names321 fn theme_names(322 &self,323 base_id: RmrkBaseId,324 at: Option<BlockHash>,325 ) -> Result<Vec<RmrkThemeName>>;326327 #[method(name = "rmrk_themes")]328 /// Get Theme info -- name, properties, and inherit flag329 fn theme(330 &self,331 base_id: RmrkBaseId,332 theme_name: String,333 filter_keys: Option<Vec<String>>,334 at: Option<BlockHash>,335 ) -> Result<Option<Theme>>;336 }337}338339pub struct Unique<C, P> {340 client: Arc<C>,341 _marker: std::marker::PhantomData<P>,342}343344impl<C, P> Unique<C, P> {345 pub fn new(client: Arc<C>) -> Self {346 Self {347 client,348 _marker: Default::default(),349 }350 }351}352353pub struct Rmrk<C, P> {354 client: Arc<C>,355 _marker: std::marker::PhantomData<P>,356}357358impl<C, P> Rmrk<C, P> {359 pub fn new(client: Arc<C>) -> Self {360 Self {361 client,362 _marker: Default::default(),363 }364 }365}366367macro_rules! pass_method {368 (369 $method_name:ident(370 $($(#[map(|$map_arg:ident| $map:expr)])? $name:ident: $ty:ty),* $(,)?371 ) -> $result:ty $(=> $mapper:expr)?,372 //$runtime_name:ident $(<$($lt: tt),+>)*373 $runtime_api_macro:ident374 $(; changed_in $ver:expr, $changed_method_name:ident ($($changed_name:expr), * $(,)?) => $fixer:expr)*375 ) => {376 fn $method_name(377 &self,378 $(379 $name: $ty,380 )*381 at: Option<<Block as BlockT>::Hash>,382 ) -> Result<$result> {383 let api = self.client.runtime_api();384 let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));385 let _api_version = if let Ok(Some(api_version)) =386 api.api_version::<$runtime_api_macro!()>(&at)387 {388 api_version389 } else {390 // unreachable for our runtime391 return Err(anyhow!("api is not available").into())392 };393394 let result = $(if _api_version < $ver {395 api.$changed_method_name(&at, $($changed_name),*).map(|r| r.map($fixer))396 } else)*397 { api.$method_name(&at, $($((|$map_arg: $ty| $map))? ($name)),*) };398399 Ok(result400 .map_err(|e| anyhow!("unable to query: {e}"))?401 .map_err(|e| anyhow!("runtime error: {e:?}"))$(.map($mapper))??)402 }403 };404}405406macro_rules! unique_api {407 () => {408 dyn UniqueRuntimeApi<Block, CrossAccountId, AccountId>409 };410}411412macro_rules! rmrk_api {413 () => {414 dyn RmrkRuntimeApi<Block, AccountId, CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme>415 };416}417418#[allow(deprecated)]419impl<C, Block, CrossAccountId, AccountId>420 UniqueApiServer<<Block as BlockT>::Hash, CrossAccountId, AccountId> for Unique<C, Block>421where422 Block: BlockT,423 AccountId: Decode,424 C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,425 C::Api: UniqueRuntimeApi<Block, CrossAccountId, AccountId>,426 CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,427{428 pass_method!(429 account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>, unique_api430 );431 pass_method!(432 collection_tokens(collection: CollectionId) -> Vec<TokenId>, unique_api433 );434 pass_method!(435 token_exists(collection: CollectionId, token: TokenId) -> bool, unique_api436 );437 pass_method!(438 token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>, unique_api439 );440 pass_method!(441 topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>, unique_api442 );443 pass_method!(token_children(collection: CollectionId, token: TokenId) -> Vec<TokenChild>, unique_api);444 pass_method!(total_supply(collection: CollectionId) -> u32, unique_api);445 pass_method!(account_balance(collection: CollectionId, account: CrossAccountId) -> u32, unique_api);446 pass_method!(balance(collection: CollectionId, account: CrossAccountId, token: TokenId) -> String => |v| v.to_string(), unique_api);447 pass_method!(448 allowance(collection: CollectionId, sender: CrossAccountId, spender: CrossAccountId, token: TokenId) -> String => |v| v.to_string(),449 unique_api450 );451452 pass_method!(collection_properties(453 collection: CollectionId,454455 #[map(|keys| string_keys_to_bytes_keys(keys))]456 keys: Option<Vec<String>>457 ) -> Vec<Property>, unique_api);458459 pass_method!(token_properties(460 collection: CollectionId,461 token_id: TokenId,462463 #[map(|keys| string_keys_to_bytes_keys(keys))]464 keys: Option<Vec<String>>465 ) -> Vec<Property>, unique_api);466467 pass_method!(property_permissions(468 collection: CollectionId,469470 #[map(|keys| string_keys_to_bytes_keys(keys))]471 keys: Option<Vec<String>>472 ) -> Vec<PropertyKeyPermission>, unique_api);473474 pass_method!(token_data(475 collection: CollectionId,476 token_id: TokenId,477478 #[map(|keys| string_keys_to_bytes_keys(keys))]479 keys: Option<Vec<String>>,480 ) -> TokenData<CrossAccountId>, unique_api);481482 pass_method!(adminlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);483 pass_method!(allowlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);484 pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool, unique_api);485 pass_method!(last_token_id(collection: CollectionId) -> TokenId, unique_api);486 pass_method!(collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api);487 pass_method!(collection_stats() -> CollectionStats, unique_api);488 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);489 pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);490 pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128>, unique_api);491}492493#[allow(deprecated)]494impl<495 C,496 Block,497 AccountId,498 CollectionInfo,499 NftInfo,500 ResourceInfo,501 PropertyInfo,502 BaseInfo,503 PartType,504 Theme,505 >506 rmrk_unique_rpc::RmrkApiServer<507 <Block as BlockT>::Hash,508 AccountId,509 CollectionInfo,510 NftInfo,511 ResourceInfo,512 PropertyInfo,513 BaseInfo,514 PartType,515 Theme,516 > for Rmrk<C, Block>517where518 C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,519 C::Api: RmrkRuntimeApi<520 Block,521 AccountId,522 CollectionInfo,523 NftInfo,524 ResourceInfo,525 PropertyInfo,526 BaseInfo,527 PartType,528 Theme,529 >,530 AccountId: Decode + Encode,531 CollectionInfo: Decode,532 NftInfo: Decode,533 ResourceInfo: Decode,534 PropertyInfo: Decode,535 BaseInfo: Decode,536 PartType: Decode,537 Theme: Decode,538 Block: BlockT,539{540 pass_method!(last_collection_idx() -> RmrkCollectionId, rmrk_api);541 pass_method!(collection_by_id(id: RmrkCollectionId) -> Option<CollectionInfo>, rmrk_api);542 pass_method!(nft_by_id(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Option<NftInfo>, rmrk_api);543 pass_method!(account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Vec<RmrkNftId>, rmrk_api);544 pass_method!(nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<RmrkNftChild>, rmrk_api);545 pass_method!(546 collection_properties(547 collection_id: RmrkCollectionId,548549 #[map(|keys| string_keys_to_bytes_keys(keys))]550 filter_keys: Option<Vec<String>>551 ) -> Vec<PropertyInfo>,552 rmrk_api553 );554 pass_method!(555 nft_properties(556 collection_id: RmrkCollectionId,557 nft_id: RmrkNftId,558559 #[map(|keys| string_keys_to_bytes_keys(keys))]560 filter_keys: Option<Vec<String>>561 ) -> Vec<PropertyInfo>,562 rmrk_api563 );564 pass_method!(nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<ResourceInfo>, rmrk_api);565 pass_method!(nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Option<u32>, rmrk_api);566 pass_method!(base(base_id: RmrkBaseId) -> Option<BaseInfo>, rmrk_api);567 pass_method!(base_parts(base_id: RmrkBaseId) -> Vec<PartType>, rmrk_api);568 pass_method!(theme_names(base_id: RmrkBaseId) -> Vec<RmrkThemeName>, rmrk_api);569 pass_method!(570 theme(571 base_id: RmrkBaseId,572573 #[map(|n| n.into_bytes())]574 theme_name: String,575576 #[map(|keys| string_keys_to_bytes_keys(keys))]577 filter_keys: Option<Vec<String>>578 ) -> Option<Theme>, rmrk_api);579}580581fn string_keys_to_bytes_keys(keys: Option<Vec<String>>) -> Option<Vec<Vec<u8>>> {582 keys.map(|keys| keys.into_iter().map(|key| key.into_bytes()).collect())583}pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -299,46 +299,48 @@
///
/// # Arguments
///
- /// * collection_id: Globally unique identifier of collection.
+ /// * collection_id: Globally unique identifier of collection that has been destroyed.
CollectionDestroyed(CollectionId),
/// New item was created.
///
/// # Arguments
///
- /// * collection_id: Id of the collection where item was created.
+ /// * collection_id: ID of the collection where the item was created.
///
- /// * item_id: Id of an item. Unique within the collection.
+ /// * item_id: ID of the item. Unique within the collection.
///
- /// * recipient: Owner of newly created item
+ /// * recipient: Owner of the newly created item.
///
- /// * amount: Always 1 for NFT
+ /// * amount: The amount of tokens that were created (always 1 for NFT).
ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),
/// Collection item was burned.
///
/// # Arguments
///
- /// * collection_id.
+ /// * collection_id: Identifier of the collection to which the burned NFT belonged.
///
/// * item_id: Identifier of burned NFT.
///
- /// * owner: which user has destroyed its tokens
+ /// * owner: Which user has destroyed their tokens.
///
- /// * amount: Always 1 for NFT
+ /// * amount: The amount of tokens that were destroyed (always 1 for NFT).
ItemDestroyed(CollectionId, TokenId, T::CrossAccountId, u128),
- /// Item was transferred
+ /// Item was transferred.
+ ///
+ /// # Arguments
///
- /// * collection_id: Id of collection to which item is belong
+ /// * collection_id: ID of the collection to which the item belongs.
///
- /// * item_id: Id of an item
+ /// * item_id: ID of the item trasnferred.
///
- /// * sender: Original owner of item
+ /// * sender: Original owner of the item.
///
- /// * recipient: New owner of item
+ /// * recipient: New owner of the item.
///
- /// * amount: Always 1 for NFT
+ /// * amount: The amount of tokens that were transferred (always 1 for NFT).
Transfer(
CollectionId,
TokenId,
@@ -347,6 +349,10 @@
u128,
),
+ /// Sponsoring allowance was approved.
+ ///
+ /// # Arguments
+ ///
/// * collection_id
///
/// * item_id
@@ -364,14 +370,53 @@
u128,
),
+ /// Collection property was added or edited.
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection, whose property was just set.
+ ///
+ /// * property_key: Key of the property that was just set.
CollectionPropertySet(CollectionId, PropertyKey),
+ /// Collection property was deleted.
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection, whose property was just deleted.
+ ///
+ /// * property_key: Key of the property that was just deleted.
CollectionPropertyDeleted(CollectionId, PropertyKey),
+ /// Item property was added or edited.
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection, whose token's property was just set.
+ ///
+ /// * item_id: ID of the item, whose property was just set.
+ ///
+ /// * property_key: Key of the property that was just set.
TokenPropertySet(CollectionId, TokenId, PropertyKey),
+ /// Item property was deleted.
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection, whose token's property was just deleted.
+ ///
+ /// * item_id: ID of the item, whose property was just deleted.
+ ///
+ /// * property_key: Key of the property that was just deleted.
TokenPropertyDeleted(CollectionId, TokenId, PropertyKey),
+ /// Token property permission was added or updated for a collection.
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection, whose permissions were just set/updated.
+ ///
+ /// * property_key: Key of the property of the set/updated permission.
PropertyPermissionSet(CollectionId, PropertyKey),
}
@@ -413,26 +458,26 @@
/// Metadata flag frozen
MetadataFlagFrozen,
- /// Item not exists.
+ /// Item does not exist
TokenNotFound,
- /// Item balance not enough.
+ /// Item is balance not enough
TokenValueTooLow,
- /// Requested value more than approved.
+ /// Requested value is more than the approved
ApprovedValueTooLow,
/// Tried to approve more than owned
CantApproveMoreThanOwned,
/// Can't transfer tokens to ethereum zero address
AddressIsZero,
- /// Target collection doesn't supports this operation
+ /// Target collection doesn't support this operation
UnsupportedOperation,
- /// Not sufficient funds to perform action
+ /// Insufficient funds to perform an action
NotSufficientFounds,
- /// User not passed nesting rule
+ /// User does not satisfy the nesting rule
UserIsNotAllowedToNest,
- /// Only tokens from specific collections may nest tokens under this
+ /// Only tokens from specific collections may nest tokens under this one
SourceCollectionIsNotAllowedToNest,
/// Tried to store more data than allowed in collection field
@@ -447,7 +492,7 @@
/// Property key is too long
PropertyKeyIsTooLong,
- /// Only ASCII letters, digits, and '_', '-' are allowed
+ /// Only ASCII letters, digits, and symbols '_', '-', and '.' are allowed
InvalidCharacterInPropertyKey,
/// Empty property keys are forbidden
@@ -460,8 +505,11 @@
CollectionIsInternal,
}
+ /// The number of created collections. Essentially contains the last collection ID.
#[pallet::storage]
pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;
+
+ /// The number of destroyed collections
#[pallet::storage]
pub type DestroyedCollectionCount<T> =
StorageValue<Value = CollectionId, QueryKind = ValueQuery>;
@@ -486,6 +534,7 @@
OnEmpty = up_data_structs::CollectionProperties,
>;
+ /// Token permissions of a collection
#[pallet::storage]
#[pallet::getter(fn property_permissions)]
pub type CollectionPropertyPermissions<T> = StorageMap<
@@ -495,6 +544,7 @@
QueryKind = ValueQuery,
>;
+ /// Amount of collection admins
#[pallet::storage]
pub type AdminAmount<T> = StorageMap<
Hasher = Blake2_128Concat,
pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -44,6 +44,7 @@
pub mod erc;
pub mod weights;
+/// todo:doc?
pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);
pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
@@ -78,10 +79,12 @@
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
+ /// Total amount of fungible tokens inside a collection.
#[pallet::storage]
pub type TotalSupply<T: Config> =
StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u128, QueryKind = ValueQuery>;
+ /// Amount of tokens owned by an account inside a collection.
#[pallet::storage]
pub type Balance<T: Config> = StorageNMap<
Key = (
@@ -92,6 +95,7 @@
QueryKind = ValueQuery,
>;
+ /// todo:doc
#[pallet::storage]
pub type Allowance<T: Config> = StorageNMap<
Key = (
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -56,6 +56,8 @@
pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;
pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
+/// Token data, stored independently from other data used to describe it.
+/// Notably contains the owner account address.
#[struct_versioning::versioned(version = 2, upper)]
#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
pub struct ItemData<CrossAccountId> {
@@ -102,13 +104,17 @@
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
+ /// Total amount of minted tokens in a collection.
#[pallet::storage]
pub type TokensMinted<T: Config> =
StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
+
+ /// Amount of burnt tokens in a collection.
#[pallet::storage]
pub type TokensBurnt<T: Config> =
StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
+ /// Token data, used to partially describe a token.
#[pallet::storage]
pub type TokenData<T: Config> = StorageNMap<
Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
@@ -116,6 +122,7 @@
QueryKind = OptionQuery,
>;
+ /// Key-value pairs, describing the metadata of a token.
#[pallet::storage]
#[pallet::getter(fn token_properties)]
pub type TokenProperties<T: Config> = StorageNMap<
@@ -125,6 +132,7 @@
OnEmpty = up_data_structs::TokenProperties,
>;
+ /// Scoped, auxiliary properties of a token, primarily used for on-chain operations.
#[pallet::storage]
#[pallet::getter(fn token_aux_property)]
pub type TokenAuxProperties<T: Config> = StorageNMap<
@@ -138,7 +146,7 @@
QueryKind = OptionQuery,
>;
- /// Used to enumerate tokens owned by account
+ /// Used to enumerate tokens owned by account.
#[pallet::storage]
pub type Owned<T: Config> = StorageNMap<
Key = (
@@ -150,7 +158,7 @@
QueryKind = ValueQuery,
>;
- /// Used to enumerate token's children
+ /// Used to enumerate token's children.
#[pallet::storage]
#[pallet::getter(fn token_children)]
pub type TokenChildren<T: Config> = StorageNMap<
@@ -163,6 +171,7 @@
QueryKind = ValueQuery,
>;
+ /// Amount of tokens owned in a collection.s
#[pallet::storage]
pub type AccountBalance<T: Config> = StorageNMap<
Key = (
@@ -173,6 +182,7 @@
QueryKind = ValueQuery,
>;
+ /// todo doc
#[pallet::storage]
pub type Allowance<T: Config> = StorageNMap<
Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
@@ -180,6 +190,7 @@
QueryKind = OptionQuery,
>;
+ /// Upgrade from the old schema to properties.
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_runtime_upgrade() -> Weight {
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -38,6 +38,8 @@
pub mod weights;
pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
+/// Token data, stored independently from other data used to describe it.
+/// Notably contains the token metadata.
#[struct_versioning::versioned(version = 2, upper)]
#[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]
pub struct ItemData {
@@ -86,13 +88,17 @@
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
+ /// Total amount of minted tokens in a collection.
#[pallet::storage]
pub type TokensMinted<T: Config> =
StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
+
+ /// Amount of tokens burnt in a collection.
#[pallet::storage]
pub type TokensBurnt<T: Config> =
StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
+ /// Token data, used to partially describe a token.
#[pallet::storage]
pub type TokenData<T: Config> = StorageNMap<
Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
@@ -100,6 +106,7 @@
QueryKind = ValueQuery,
>;
+ /// Amount of pieces a refungible token is split into.
#[pallet::storage]
pub type TotalSupply<T: Config> = StorageNMap<
Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
@@ -107,7 +114,7 @@
QueryKind = ValueQuery,
>;
- /// Used to enumerate tokens owned by account
+ /// Used to enumerate tokens owned by account.
#[pallet::storage]
pub type Owned<T: Config> = StorageNMap<
Key = (
@@ -119,6 +126,7 @@
QueryKind = ValueQuery,
>;
+ /// Amount of tokens (not pieces) partially owned by an account within a collection.
#[pallet::storage]
pub type AccountBalance<T: Config> = StorageNMap<
Key = (
@@ -130,6 +138,7 @@
QueryKind = ValueQuery,
>;
+ /// Amount of pieces of a token owned by an account.
#[pallet::storage]
pub type Balance<T: Config> = StorageNMap<
Key = (
@@ -142,6 +151,7 @@
QueryKind = ValueQuery,
>;
+ /// todo:doc
#[pallet::storage]
pub type Allowance<T: Config> = StorageNMap<
Key = (
@@ -248,7 +258,7 @@
// TODO: ERC721 transfer event
Ok(())
}
-
+
pub fn burn(
collection: &RefungibleHandle<T>,
owner: &T::CrossAccountId,
@@ -595,6 +605,7 @@
Ok(())
}
+ /// todo:doc oh look, a precedent. not pub, too. but it has an unclear use-case.
/// Returns allowance, which should be set after transaction
fn check_allowed(
collection: &RefungibleHandle<T>,
pallets/scheduler/src/lib.rsdiffbeforeafterboth--- a/pallets/scheduler/src/lib.rs
+++ b/pallets/scheduler/src/lib.rs
@@ -258,6 +258,7 @@
/// A Scheduler-Runtime interface for finer payment handling.
pub trait DispatchCall<T: frame_system::Config + Config, SelfContainedSignedInfo> {
+ /// Reserve the maximum spendings on a call.
fn reserve_balance(
id: ScheduledId,
sponsor: <T as frame_system::Config>::AccountId,
@@ -265,6 +266,7 @@
count: u32,
) -> Result<(), DispatchError>;
+ /// Pay for call dispatch (un-reserve) from the reserved funds, returning the change.
fn pay_for_call(
id: ScheduledId,
sponsor: <T as frame_system::Config>::AccountId,
@@ -280,6 +282,7 @@
TransactionValidityError,
>;
+ /// Release reserved funds.
fn cancel_reserve(
id: ScheduledId,
sponsor: <T as frame_system::Config>::AccountId,
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -25,19 +25,19 @@
#[pallet::error]
pub enum Error<T> {
- /// While searched for owner, got already checked account
+ /// While searching for the owner, encountered an already checked account, detecting a loop.
OuroborosDetected,
- /// While searched for owner, encountered depth limit
+ /// While searching for the owner, reached the depth limit.
DepthLimit,
- /// While iterating over children, encountered breadth limit
+ /// While iterating over children, reached the breadth limit.
BreadthLimit,
- /// While searched for owner, found token owner by not-yet-existing token
+ /// Couldn't find the token owner that is a token. Perhaps, it does not yet exist. todo:doc? rephrase?
TokenNotFound,
}
#[pallet::event]
pub enum Event<T> {
- /// Executed call on behalf of token
+ /// Executed call on behalf of the token.
Executed(DispatchResult),
}
@@ -73,11 +73,11 @@
#[derive(PartialEq)]
pub enum Parent<CrossAccountId> {
- /// Token owned by normal account
+ /// Token owned by a normal account.
User(CrossAccountId),
- /// Passed token not found
+ /// Could not find the token provided as the owner.
TokenNotFound,
- /// Token owner is another token (target token still may not exist)
+ /// Token owner is another token (still, the target token may not exist).
Token(CollectionId, TokenId),
}
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -101,7 +101,7 @@
/// * admin: Admin address.
CollectionAdminAdded(CollectionId, CrossAccountId),
- /// Collection owned was change
+ /// Collection owned was changed
///
/// # Arguments
///
@@ -137,7 +137,7 @@
/// * admin: Admin address.
CollectionAdminRemoved(CollectionId, CrossAccountId),
- /// Address was remove from allow list
+ /// Address was removed from the allow list
///
/// # Arguments
///
@@ -146,7 +146,7 @@
/// * user: Address.
AllowListAddressRemoved(CollectionId, CrossAccountId),
- /// Address was add to allow list
+ /// Address was added to the allow list
///
/// # Arguments
///
@@ -155,13 +155,18 @@
/// * user: Address.
AllowListAddressAdded(CollectionId, CrossAccountId),
- /// Collection limits was set
+ /// Collection limits were set
///
/// # Arguments
///
/// * collection_id: Globally unique collection identifier.
CollectionLimitSet(CollectionId),
+ /// Collection permissions were set
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: Globally unique collection identifier.
CollectionPermissionSet(CollectionId),
}
}
@@ -198,7 +203,7 @@
ChainVersion: u64;
//#endregion
- //#region Tokens transfer rate limit baskets
+ //#region Tokens transfer sponosoring rate limit baskets
/// (Collection id (controlled?2), who created (real))
/// TODO: Off chain worker should remove from this map when collection gets removed
pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;
@@ -214,11 +219,14 @@
/// Collection id (controlled?2), token id (controlled?2)
#[deprecated]
pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+ /// Last sponsoring of token property setting // todo:doc rephrase this and the following
pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
- /// Approval sponsoring
+ /// Last sponsoring of NFT approval in a collection
pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
+ /// Last sponsoring of fungible tokens approval in a collection
pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
+ /// Last sponsoring of RFT approval in a collection
pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
}
}
@@ -278,9 +286,16 @@
Self::create_collection_ex(origin, data)
}
- /// This method creates a collection
+ /// Create a collection with explicit parameters.
+ /// Prefer it to the deprecated [`created_collection`] method.
+ ///
+ /// # Permissions
+ ///
+ /// * Anyone.
///
- /// Prefer it to deprecated [`created_collection`] method
+ /// # Arguments
+ ///
+ /// * data: explicit create-collection data.
#[weight = <SelfWeightOf<T>>::create_collection()]
#[transactional]
pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {
@@ -293,11 +308,11 @@
Ok(())
}
- /// Destroys collection if no tokens within this collection
+ /// Destroy the collection if no tokens exist within.
///
/// # Permissions
///
- /// * Collection Owner.
+ /// * Collection Owner
///
/// # Arguments
///
@@ -398,7 +413,7 @@
///
/// # Permissions
///
- /// * Collection Owner.
+ /// * Collection Owner
///
/// # Arguments
///
@@ -424,40 +439,40 @@
target_collection.save()
}
- /// Adds an admin of the Collection.
+ /// Adds an admin of the collection.
/// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.
///
/// # Permissions
///
- /// * Collection Owner.
- /// * Collection Admin.
+ /// * Collection Owner
+ /// * Collection Admin
///
/// # Arguments
///
/// * collection_id: ID of the Collection to add admin for.
///
- /// * new_admin_id: Address of new admin to add.
+ /// * new_admin: Address of new admin to add.
#[weight = <SelfWeightOf<T>>::add_collection_admin()]
#[transactional]
- pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {
+ pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin: T::CrossAccountId) -> DispatchResult {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let collection = <CollectionHandle<T>>::try_get(collection_id)?;
collection.check_is_internal()?;
<Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(
collection_id,
- new_admin_id.clone()
+ new_admin.clone()
));
- <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)
+ <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin, true)
}
/// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.
///
/// # Permissions
///
- /// * Collection Owner.
- /// * Collection Admin.
+ /// * Collection Owner
+ /// * Collection Admin
///
/// # Arguments
///
@@ -479,9 +494,12 @@
<PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)
}
+ /// Set (invite) a new collection sponsor. If successful, confirmation from the sponsor-to-be will be pending.
+ ///
/// # Permissions
///
/// * Collection Owner
+ /// * Collection Admin
///
/// # Arguments
///
@@ -507,9 +525,11 @@
target_collection.save()
}
+ /// Confirm own sponsorship of a collection.
+ ///
/// # Permissions
///
- /// * Sponsor.
+ /// * The sponsor to-be
///
/// # Arguments
///
@@ -538,7 +558,7 @@
///
/// # Permissions
///
- /// * Collection owner.
+ /// * Collection Owner
///
/// # Arguments
///
@@ -560,12 +580,12 @@
target_collection.save()
}
- /// This method creates a concrete instance of NFT Collection created with CreateCollection method.
+ /// Create a concrete instance of NFT Collection created with CreateCollection method.
///
/// # Permissions
///
- /// * Collection Owner.
- /// * Collection Admin.
+ /// * Collection Owner
+ /// * Collection Admin
/// * Anyone if
/// * Allow List is enabled, and
/// * Address is added to allow list, and
@@ -587,12 +607,12 @@
dispatch_tx::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))
}
- /// This method creates multiple items in a collection created with CreateCollection method.
+ /// Create multiple items in a collection created with CreateCollection method.
///
/// # Permissions
///
- /// * Collection Owner.
- /// * Collection Admin.
+ /// * Collection Owner
+ /// * Collection Admin
/// * Anyone if
/// * Allow List is enabled, and
/// * Address is added to allow list, and
@@ -615,6 +635,18 @@
dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
}
+ /// Add or change collection properties.
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * properties: a vector of key-value pairs stored as the collection's metadata. Keys support Latin letters, '-', '_', and '.' as symbols.
#[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]
#[transactional]
pub fn set_collection_properties(
@@ -629,6 +661,18 @@
dispatch_tx::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))
}
+ /// Delete specified collection properties.
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * property_keys: a vector of keys of the properties to be deleted.
#[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]
#[transactional]
pub fn delete_collection_properties(
@@ -643,6 +687,22 @@
dispatch_tx::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))
}
+ /// Add or change token properties according to collection's permissions.
+ ///
+ /// # Permissions
+ ///
+ /// * Depends on collection's token property permissions and specified property mutability:
+ /// * Collection Owner
+ /// * Collection Admin
+ /// * Token Owner
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * token_id.
+ ///
+ /// * properties: a vector of key-value pairs stored as the token's metadata. Keys support Latin letters, '-', '_', and '.' as symbols.
#[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]
#[transactional]
pub fn set_token_properties(
@@ -659,6 +719,22 @@
dispatch_tx::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties, &budget))
}
+ /// Delete specified token properties.
+ ///
+ /// # Permissions
+ ///
+ /// * Depends on collection's token property permissions and specified property mutability:
+ /// * Collection Owner
+ /// * Collection Admin
+ /// * Token Owner
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * token_id.
+ ///
+ /// * property_keys: a vector of keys of the properties to be deleted.
#[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]
#[transactional]
pub fn delete_token_properties(
@@ -675,6 +751,18 @@
dispatch_tx::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys, &budget))
}
+ /// Add or change token property permissions of a collection.
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * property_permissions: a vector of permissions for property keys. Keys support Latin letters, '-', '_', and '.' as symbols.
#[weight = T::CommonWeightInfo::set_token_property_permissions(property_permissions.len() as u32)]
#[transactional]
pub fn set_token_property_permissions(
@@ -689,6 +777,22 @@
dispatch_tx::<T, _>(collection_id, |d| d.set_token_property_permissions(&sender, property_permissions))
}
+ /// Create multiple items inside a collection with explicitly specified initial parameters.
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ /// * Anyone if
+ /// * Allow List is enabled, and
+ /// * Address is added to allow list, and
+ /// * MintPermission is enabled (see SetMintPermission method)
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id: ID of the collection.
+ ///
+ /// * data: explicit item creation data.
#[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]
#[transactional]
pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {
@@ -698,11 +802,11 @@
dispatch_tx::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))
}
- /// Set transfers_enabled value for particular collection
+ /// Set transfers_enabled value for particular collection.
///
/// # Permissions
///
- /// * Collection Owner.
+ /// * Collection Owner
///
/// # Arguments
///
@@ -723,13 +827,13 @@
target_collection.save()
}
- /// Destroys a concrete instance of NFT.
+ /// Destroy a concrete instance of NFT.
///
/// # Permissions
///
- /// * Collection Owner.
- /// * Collection Admin.
- /// * Current NFT Owner.
+ /// * Collection Owner
+ /// * Collection Admin
+ /// * Current NFT Owner
///
/// # Arguments
///
@@ -752,7 +856,7 @@
Ok(post_info)
}
- /// Destroys a concrete instance of NFT on behalf of the owner
+ /// Destroy a concrete instance of NFT on behalf of the owner.
/// See also: [`approve`]
///
/// # Permissions
@@ -835,6 +939,7 @@
/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
///
/// # Permissions
+ ///
/// * Collection Owner
/// * Collection Admin
/// * Current NFT owner
@@ -860,6 +965,18 @@
dispatch_tx::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
}
+ /// Set specific limits of a collection. Empty, or None fields mean chain default.
+ ///.
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * new_limit: The new limits of the collection. They will overwrite the current ones.
#[weight = <SelfWeightOf<T>>::set_collection_limits()]
#[transactional]
pub fn set_collection_limits(
@@ -882,12 +999,24 @@
target_collection.save()
}
+ /// Set specific permissions of a collection. Empty, or None fields mean chain default.
+ ///
+ /// # Permissions
+ ///
+ /// * Collection Owner
+ /// * Collection Admin
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * new_permission: The new permissions of the collection. They will overwrite the current ones.
#[weight = <SelfWeightOf<T>>::set_collection_limits()]
#[transactional]
pub fn set_collection_permissions(
origin,
collection_id: CollectionId,
- new_limit: CollectionPermissions,
+ new_permission: CollectionPermissions,
) -> DispatchResult {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
@@ -895,7 +1024,7 @@
target_collection.check_is_owner_or_admin(&sender)?;
let old_limit = &target_collection.permissions;
- target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;
+ target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_permission)?;
<Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(
collection_id
@@ -904,6 +1033,19 @@
target_collection.save()
}
+ /// Re-partition a refungible token, while owning all of its parts.
+ ///
+ /// # Permissions
+ ///
+ /// * Token Owner (must own every part)
+ ///
+ /// # Arguments
+ ///
+ /// * collection_id.
+ ///
+ /// * token: the ID of the RFT.
+ ///
+ /// * amount: The new number of parts into which the token shall be partitioned.
#[weight = T::RefungibleExtensionsWeightInfo::repartition()]
#[transactional]
pub fn repartition(
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -197,7 +197,6 @@
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub enum CollectionMode {
NFT,
- // decimal points
Fungible(DecimalPoints),
ReFungible,
}
@@ -252,12 +251,14 @@
pub enum SponsorshipState<AccountId> {
/// The fees are applied to the transaction sender
Disabled,
+ /// Pending confirmation from a sponsor-to-be
Unconfirmed(AccountId),
/// Transactions are sponsored by specified account
Confirmed(AccountId),
}
impl<AccountId> SponsorshipState<AccountId> {
+ /// Get the acting sponsor account, if present
pub fn sponsor(&self) -> Option<&AccountId> {
match self {
Self::Confirmed(sponsor) => Some(sponsor),
@@ -265,6 +266,7 @@
}
}
+ /// Get the sponsor account currently pending confirmation, if present
pub fn pending_sponsor(&self) -> Option<&AccountId> {
match self {
Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),
@@ -272,6 +274,7 @@
}
}
+ /// Is sponsorship set and acting
pub fn confirmed(&self) -> bool {
matches!(self, Self::Confirmed(_))
}
@@ -283,7 +286,7 @@
}
}
-/// Used in storage
+/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version)
#[struct_versioning::versioned(version = 2, upper)]
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]
pub struct Collection<AccountId> {
@@ -324,7 +327,7 @@
pub meta_update_permission: MetaUpdatePermission,
}
-/// Used in RPC calls
+/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version)
#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct RpcCollection<AccountId> {
@@ -362,12 +365,15 @@
pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
-/// All fields are wrapped in `Option`s, where None means chain default
+/// Limits and restrictions of a collection.
+/// All fields are wrapped in `Option`s, where None means chain default.
// When adding/removing fields from this struct - don't forget to also update clamp_limits
#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct CollectionLimits {
+ /// Maximum number of owned tokens per account
pub account_token_ownership_limit: Option<u32>,
+ /// Maximum size of data of a sponsored transaction
pub sponsored_data_size: Option<u32>,
/// FIXME should we delete this or repurpose it?
@@ -375,13 +381,18 @@
/// Some(v) - setVariableMetadata is sponsored
/// if there is v block between txs
pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,
+ /// Maximum amount of tokens inside the collection
pub token_limit: Option<u32>,
- // Timeouts for item types in passed blocks
+ /// Timeout for sponsoring a token transfer in passed blocks
pub sponsor_transfer_timeout: Option<u32>,
+ /// Timeout for sponsoring an approval in passed blocks
pub sponsor_approve_timeout: Option<u32>,
+ /// Can a token be transferred by the owner
pub owner_can_transfer: Option<bool>,
+ /// Can a token be burned by the owner
pub owner_can_destroy: Option<bool>,
+ /// Can a token be transferred at all
pub transfers_enabled: Option<bool>,
}
@@ -509,6 +520,7 @@
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub enum SponsoringRateLimit {
SponsoringDisabled,
+ /// Once per how many blocks can sponsorship of a transaction type occur
Blocks(u32),
}
@@ -516,6 +528,7 @@
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
#[derivative(Debug)]
pub struct CreateNftData {
+ /// Key-value pairs used to describe the token as metadata
#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
#[derivative(Debug(format_with = "bounded::vec_debug"))]
pub properties: CollectionPropertiesVec,
@@ -524,6 +537,7 @@
#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
pub struct CreateFungibleData {
+ /// Number of fungible tokens minted
pub value: u128,
}
@@ -534,6 +548,7 @@
#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
#[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
+ /// Number of pieces the RFT is split into
pub pieces: u128,
}
@@ -553,6 +568,7 @@
ReFungible(CreateReFungibleData),
}
+/// Explicit NFT creation data with meta parameters
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
#[derivative(Debug)]
pub struct CreateNftExData<CrossAccountId> {
@@ -561,6 +577,7 @@
pub owner: CrossAccountId,
}
+/// Explicit RFT creation data with meta parameters
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
pub struct CreateRefungibleExData<CrossAccountId> {
@@ -570,6 +587,7 @@
pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
}
+/// Explicit item creation data with meta parameters, namely the owner
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
pub enum CreateItemExData<CrossAccountId> {
@@ -617,6 +635,7 @@
}
}
+/// Token's address, dictated by its collection and token IDs
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
// todo possibly rename to be used generally as an address pair
tests/src/interfaces/unique/definitions.tsdiffbeforeafterboth--- a/tests/src/interfaces/unique/definitions.ts
+++ b/tests/src/interfaces/unique/definitions.ts
@@ -43,13 +43,13 @@
accountTokens: fun('Get tokens owned by account', [collectionParam, crossAccountParam()], 'Vec<u32>'),
collectionTokens: fun('Get tokens contained in collection', [collectionParam], 'Vec<u32>'),
- lastTokenId: fun('Get last token id', [collectionParam], 'u32'),
+ lastTokenId: fun('Get last token ID created in a collection', [collectionParam], 'u32'),
totalSupply: fun('Get amount of unique collection tokens', [collectionParam], 'u32'),
- accountBalance: fun('Get amount of different user tokens', [collectionParam, crossAccountParam()], 'u32'),
- balance: fun('Get amount of specific account token', [collectionParam, crossAccountParam(), tokenParam], 'u128'),
+ accountBalance: fun('Get owned amount of any user tokens', [collectionParam, crossAccountParam()], 'u32'),
+ balance: fun('Get owned amount of specific account token', [collectionParam, crossAccountParam(), tokenParam], 'u128'),
allowance: fun('Get allowed amount', [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam], 'u128'),
tokenOwner: fun('Get token owner', [collectionParam, tokenParam], `Option<${CROSS_ACCOUNT_ID_TYPE}>`),
- topmostTokenOwner: fun('Get token owner, in case of nested token - find parent recursive', [collectionParam, tokenParam], `Option<${CROSS_ACCOUNT_ID_TYPE}>`),
+ topmostTokenOwner: fun('Get token owner, in case of nested token - find the parent recursively', [collectionParam, tokenParam], `Option<${CROSS_ACCOUNT_ID_TYPE}>`),
tokenChildren: fun('Get tokens nested directly into the token', [collectionParam, tokenParam], 'Vec<UpDataStructsTokenChild>'),
constMetadata: fun('Get token constant metadata', [collectionParam, tokenParam], 'Vec<u8>'),
variableMetadata: fun('Get token variable metadata', [collectionParam, tokenParam], 'Vec<u8>'),
@@ -74,7 +74,7 @@
'UpDataStructsTokenData',
),
tokenExists: fun('Check if token exists', [collectionParam, tokenParam], 'bool'),
- collectionById: fun('Get collection by specified id', [collectionParam], 'Option<UpDataStructsRpcCollection>'),
+ collectionById: fun('Get collection by specified ID', [collectionParam], 'Option<UpDataStructsRpcCollection>'),
collectionStats: fun('Get collection stats', [], 'UpDataStructsCollectionStats'),
allowed: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam()], 'bool'),
nextSponsored: fun('Get number of blocks when sponsored transaction is available', [collectionParam, crossAccountParam(), tokenParam], 'Option<u64>'),