From 8bbc7539fcb323d48ed7e702bf60144d2e94f29c Mon Sep 17 00:00:00 2001 From: str-mv Date: Fri, 08 Apr 2022 05:56:38 +0000 Subject: [PATCH] CORE-178 --- --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -119,6 +119,15 @@ ) -> Result>>; #[rpc(name = "unique_collectionStats")] fn collection_stats(&self, at: Option) -> Result; + + #[rpc(name = "unique_nextSponsored")] + fn next_sponsored( + &self, + collection: CollectionId, + account: CrossAccountId, + token: TokenId, + at: Option, + ) -> Result>; } pub struct Unique { @@ -222,4 +231,5 @@ pass_method!(last_token_id(collection: CollectionId) -> TokenId); pass_method!(collection_by_id(collection: CollectionId) -> Option>); pass_method!(collection_stats() -> CollectionStats); + pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option); } --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -69,7 +69,7 @@ mod eth; mod sponsorship; -pub use sponsorship::UniqueSponsorshipHandler; +pub use sponsorship::{UniqueSponsorshipHandler, UniqueSponsorshipPredict}; pub use eth::sponsoring::UniqueEthSponsorshipHandler; pub use eth::UniqueErcSupport; @@ -84,6 +84,12 @@ pub mod weights; use weights::WeightInfo; +pub trait SponsorshipPredict { + fn predict(collection: CollectionId, account: T::CrossAccountId, token: TokenId) -> Option + where + u64: From<::BlockNumber>; +} + decl_error! { /// Error for non-fungible-token module. pub enum Error for Module { --- a/pallets/unique/src/sponsorship.rs +++ b/pallets/unique/src/sponsorship.rs @@ -301,3 +301,80 @@ } } } + +use crate::SponsorshipPredict; +use up_data_structs::SponsorshipState; +pub struct UniqueSponsorshipPredict(PhantomData); + +impl SponsorshipPredict for UniqueSponsorshipPredict +where + T: Config, +{ + fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option + where + u64: From<::BlockNumber>, + { + let collection = >::try_get(collection_id).ok()?; + + // preliminary sponsoring correctness check + match collection.sponsorship { + SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => return None, + _ => (), + } + + // sponsor timeout + let block_number = >::block_number() as T::BlockNumber; + let limit = collection + .limits + .sponsor_transfer_timeout(match collection.mode { + CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT, + CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, + CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, + }); + + let last_tx_block = match collection.mode { + CollectionMode::NFT => >::get(collection.id, token), + CollectionMode::Fungible(_) => { + >::get(collection.id, who.as_sub()) + } + CollectionMode::ReFungible => { + >::get((collection.id, token, who.as_sub())) + } + }; + + if let Some(last_tx_block) = last_tx_block { + let timeout = last_tx_block + limit.into(); + if block_number < timeout { + return Some((timeout - block_number).into()); + } + return Some(0); + } + + let token_exists = match collection.mode { + CollectionMode::NFT => { + >::contains_key((collection.id, token)) + } + CollectionMode::Fungible(_) => true, + CollectionMode::ReFungible => { + >::contains_key((collection.id, token)) + } + }; + + if token_exists { + Some(0) + } else { + None + } + + // // existance check + // match collection.mode { + // CollectionMode::NFT => >::get(collection.id, token), + // CollectionMode::Fungible(_) => { + // >::get(collection.id, who.as_sub()) + // } + // CollectionMode::ReFungible => { + // >::get((collection.id, token, who.as_sub())) + // } + // }; + } +} --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -59,5 +59,6 @@ fn last_token_id(collection: CollectionId) -> Result; fn collection_by_id(collection: CollectionId) -> Result>>; fn collection_stats() -> Result; + fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result>; } } --- a/runtime/common/src/runtime_apis.rs +++ b/runtime/common/src/runtime_apis.rs @@ -69,6 +69,13 @@ fn collection_stats() -> Result { Ok(>::collection_stats()) } + fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result, DispatchError> { + Ok( as + pallet_unique::SponsorshipPredict>::predict( + collection, + account, + token)) + } } impl sp_api::Core for Runtime { --- a/tests/src/interfaces/augment-api-rpc.ts +++ b/tests/src/interfaces/augment-api-rpc.ts @@ -619,6 +619,10 @@ * Get token variable metadata **/ variableMetadata: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; + /** + * nextSponsored transaction + **/ + nextSponsored: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, account: PalletCommonAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable>>; }; web3: { /** --- a/tests/src/interfaces/unique/definitions.ts +++ b/tests/src/interfaces/unique/definitions.ts @@ -55,5 +55,6 @@ collectionById: fun('Get collection by specified id', [collectionParam], 'Option'), collectionStats: fun('Get collection stats', [], 'UpDataStructsCollectionStats'), allowed: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam()], 'bool'), + nextSponsored: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam(), tokenParam], 'Option'), }, }; -- gitstuff