difftreelog
CORE-178
in: master
7 files changed
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -119,6 +119,15 @@
) -> Result<Option<Collection<AccountId>>>;
#[rpc(name = "unique_collectionStats")]
fn collection_stats(&self, at: Option<BlockHash>) -> Result<CollectionStats>;
+
+ #[rpc(name = "unique_nextSponsored")]
+ fn next_sponsored(
+ &self,
+ collection: CollectionId,
+ account: CrossAccountId,
+ token: TokenId,
+ at: Option<BlockHash>,
+ ) -> Result<Option<u64>>;
}
pub struct Unique<C, P> {
@@ -222,4 +231,5 @@
pass_method!(last_token_id(collection: CollectionId) -> TokenId);
pass_method!(collection_by_id(collection: CollectionId) -> Option<Collection<AccountId>>);
pass_method!(collection_stats() -> CollectionStats);
+ pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>);
}
pallets/unique/src/lib.rsdiffbeforeafterboth--- 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<T: Config> {
+ fn predict(collection: CollectionId, account: T::CrossAccountId, token: TokenId) -> Option<u64>
+ where
+ u64: From<<T as frame_system::Config>::BlockNumber>;
+}
+
decl_error! {
/// Error for non-fungible-token module.
pub enum Error for Module<T: Config> {
pallets/unique/src/sponsorship.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/>.1617use crate::{18 Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,19 FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode, NftApproveBasket,20 FungibleApproveBasket, RefungibleApproveBasket,21};22use core::marker::PhantomData;23use up_sponsorship::SponsorshipHandler;24use frame_support::{25 traits::{IsSubType},26 storage::{StorageMap, StorageDoubleMap, StorageNMap},27};28use up_data_structs::{29 CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,30 NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId,31};32use pallet_common::{CollectionHandle};33use pallet_common::account::CrossAccountId;3435pub fn withdraw_transfer<T: Config>(36 collection: &CollectionHandle<T>,37 who: &T::CrossAccountId,38 item_id: &TokenId,39) -> Option<()> {40 // preliminary sponsoring correctness check41 match collection.mode {42 CollectionMode::NFT => {43 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;44 if !owner.conv_eq(who) {45 return None;46 }47 }48 CollectionMode::Fungible(_) => {49 if item_id != &TokenId::default() {50 return None;51 }52 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {53 return None;54 }55 }56 CollectionMode::ReFungible => {57 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {58 return None;59 }60 }61 }6263 // sponsor timeout64 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;65 let limit = collection66 .limits67 .sponsor_transfer_timeout(match collection.mode {68 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,69 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,70 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,71 });7273 let last_tx_block = match collection.mode {74 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),75 CollectionMode::Fungible(_) => {76 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())77 }78 CollectionMode::ReFungible => {79 <ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))80 }81 };8283 if let Some(last_tx_block) = last_tx_block {84 let timeout = last_tx_block + limit.into();85 if block_number < timeout {86 return None;87 }88 }8990 match collection.mode {91 CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),92 CollectionMode::Fungible(_) => {93 <FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)94 }95 CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(96 (collection.id, item_id, who.as_sub()),97 block_number,98 ),99 };100101 Some(())102}103104pub fn withdraw_create_item<T: Config>(105 collection: &CollectionHandle<T>,106 who: &T::CrossAccountId,107 _properties: &CreateItemData,108) -> Option<()> {109 if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {110 return None;111 }112113 // sponsor timeout114 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;115 let limit = collection116 .limits117 .sponsor_transfer_timeout(match _properties {118 CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,119 CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,120 CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,121 });122123 if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {124 let timeout = last_tx_block + limit.into();125 if block_number < timeout {126 return None;127 }128 }129130 CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);131132 Some(())133}134135pub fn withdraw_set_variable_meta_data<T: Config>(136 who: &T::CrossAccountId,137 collection: &CollectionHandle<T>,138 item_id: &TokenId,139 data: &[u8],140) -> Option<()> {141 // TODO: make it work for admins142 if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {143 return None;144 }145 // preliminary sponsoring correctness check146 match collection.mode {147 CollectionMode::NFT => {148 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;149 if !owner.conv_eq(who) {150 return None;151 }152 }153 CollectionMode::Fungible(_) => {154 if item_id != &TokenId::default() {155 return None;156 }157 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {158 return None;159 }160 }161 CollectionMode::ReFungible => {162 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {163 return None;164 }165 }166 }167168 // Can't sponsor fungible collection, this tx will be rejected169 // as invalid170 if matches!(collection.mode, CollectionMode::Fungible(_)) {171 return None;172 }173 if data.len() > collection.limits.sponsored_data_size() as usize {174 return None;175 }176177 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;178 let limit = collection.limits.sponsored_data_rate_limit()?;179180 if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {181 let timeout = last_tx_block + limit.into();182 if block_number < timeout {183 return None;184 }185 }186187 <VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);188189 Some(())190}191192pub fn withdraw_approve<T: Config>(193 collection: &CollectionHandle<T>,194 who: &T::AccountId,195 item_id: &TokenId,196) -> Option<()> {197 // sponsor timeout198 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;199 let limit = collection.limits.sponsor_approve_timeout();200201 let last_tx_block = match collection.mode {202 CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),203 CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),204 CollectionMode::ReFungible => {205 <RefungibleApproveBasket<T>>::get((collection.id, item_id, who))206 }207 };208209 if let Some(last_tx_block) = last_tx_block {210 let timeout = last_tx_block + limit.into();211 if block_number < timeout {212 return None;213 }214 }215216 match collection.mode {217 CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),218 CollectionMode::Fungible(_) => {219 <FungibleApproveBasket<T>>::insert(collection.id, who, block_number)220 }221 CollectionMode::ReFungible => {222 <RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)223 }224 };225226 Some(())227}228229fn load<T: Config>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {230 let collection = CollectionHandle::new(id)?;231 let sponsor = collection.sponsorship.sponsor().cloned()?;232 Some((sponsor, collection))233}234235pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);236impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>237where238 T: Config,239 C: IsSubType<Call<T>>,240{241 fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {242 match IsSubType::<Call<T>>::is_sub_type(call)? {243 Call::create_item {244 collection_id,245 data,246 ..247 } => {248 let (sponsor, collection) = load(*collection_id)?;249 withdraw_create_item::<T>(250 &collection,251 &T::CrossAccountId::from_sub(who.clone()),252 data,253 )254 .map(|()| sponsor)255 }256 Call::transfer {257 collection_id,258 item_id,259 ..260 } => {261 let (sponsor, collection) = load(*collection_id)?;262 withdraw_transfer::<T>(263 &collection,264 &T::CrossAccountId::from_sub(who.clone()),265 item_id,266 )267 .map(|()| sponsor)268 }269 Call::transfer_from {270 collection_id,271 item_id,272 from,273 ..274 } => {275 let (sponsor, collection) = load(*collection_id)?;276 withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)277 }278 Call::approve {279 collection_id,280 item_id,281 ..282 } => {283 let (sponsor, collection) = load(*collection_id)?;284 withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)285 }286 Call::set_variable_meta_data {287 collection_id,288 item_id,289 data,290 } => {291 let (sponsor, collection) = load(*collection_id)?;292 withdraw_set_variable_meta_data::<T>(293 &T::CrossAccountId::from_sub(who.clone()),294 &collection,295 item_id,296 data,297 )298 .map(|()| sponsor)299 }300 _ => None,301 }302 }303}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/>.1617use crate::{18 Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,19 FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode, NftApproveBasket,20 FungibleApproveBasket, RefungibleApproveBasket,21};22use core::marker::PhantomData;23use up_sponsorship::SponsorshipHandler;24use frame_support::{25 traits::{IsSubType},26 storage::{StorageMap, StorageDoubleMap, StorageNMap},27};28use up_data_structs::{29 CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,30 NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId,31};32use pallet_common::{CollectionHandle};33use pallet_common::account::CrossAccountId;3435pub fn withdraw_transfer<T: Config>(36 collection: &CollectionHandle<T>,37 who: &T::CrossAccountId,38 item_id: &TokenId,39) -> Option<()> {40 // preliminary sponsoring correctness check41 match collection.mode {42 CollectionMode::NFT => {43 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;44 if !owner.conv_eq(who) {45 return None;46 }47 }48 CollectionMode::Fungible(_) => {49 if item_id != &TokenId::default() {50 return None;51 }52 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {53 return None;54 }55 }56 CollectionMode::ReFungible => {57 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {58 return None;59 }60 }61 }6263 // sponsor timeout64 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;65 let limit = collection66 .limits67 .sponsor_transfer_timeout(match collection.mode {68 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,69 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,70 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,71 });7273 let last_tx_block = match collection.mode {74 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, item_id),75 CollectionMode::Fungible(_) => {76 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())77 }78 CollectionMode::ReFungible => {79 <ReFungibleTransferBasket<T>>::get((collection.id, item_id, who.as_sub()))80 }81 };8283 if let Some(last_tx_block) = last_tx_block {84 let timeout = last_tx_block + limit.into();85 if block_number < timeout {86 return None;87 }88 }8990 match collection.mode {91 CollectionMode::NFT => <NftTransferBasket<T>>::insert(collection.id, item_id, block_number),92 CollectionMode::Fungible(_) => {93 <FungibleTransferBasket<T>>::insert(collection.id, who.as_sub(), block_number)94 }95 CollectionMode::ReFungible => <ReFungibleTransferBasket<T>>::insert(96 (collection.id, item_id, who.as_sub()),97 block_number,98 ),99 };100101 Some(())102}103104pub fn withdraw_create_item<T: Config>(105 collection: &CollectionHandle<T>,106 who: &T::CrossAccountId,107 _properties: &CreateItemData,108) -> Option<()> {109 if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {110 return None;111 }112113 // sponsor timeout114 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;115 let limit = collection116 .limits117 .sponsor_transfer_timeout(match _properties {118 CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,119 CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,120 CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,121 });122123 if let Some(last_tx_block) = <CreateItemBasket<T>>::get((collection.id, who.as_sub())) {124 let timeout = last_tx_block + limit.into();125 if block_number < timeout {126 return None;127 }128 }129130 CreateItemBasket::<T>::insert((collection.id, who.as_sub()), block_number);131132 Some(())133}134135pub fn withdraw_set_variable_meta_data<T: Config>(136 who: &T::CrossAccountId,137 collection: &CollectionHandle<T>,138 item_id: &TokenId,139 data: &[u8],140) -> Option<()> {141 // TODO: make it work for admins142 if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {143 return None;144 }145 // preliminary sponsoring correctness check146 match collection.mode {147 CollectionMode::NFT => {148 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;149 if !owner.conv_eq(who) {150 return None;151 }152 }153 CollectionMode::Fungible(_) => {154 if item_id != &TokenId::default() {155 return None;156 }157 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {158 return None;159 }160 }161 CollectionMode::ReFungible => {162 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {163 return None;164 }165 }166 }167168 // Can't sponsor fungible collection, this tx will be rejected169 // as invalid170 if matches!(collection.mode, CollectionMode::Fungible(_)) {171 return None;172 }173 if data.len() > collection.limits.sponsored_data_size() as usize {174 return None;175 }176177 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;178 let limit = collection.limits.sponsored_data_rate_limit()?;179180 if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {181 let timeout = last_tx_block + limit.into();182 if block_number < timeout {183 return None;184 }185 }186187 <VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);188189 Some(())190}191192pub fn withdraw_approve<T: Config>(193 collection: &CollectionHandle<T>,194 who: &T::AccountId,195 item_id: &TokenId,196) -> Option<()> {197 // sponsor timeout198 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;199 let limit = collection.limits.sponsor_approve_timeout();200201 let last_tx_block = match collection.mode {202 CollectionMode::NFT => <NftApproveBasket<T>>::get(collection.id, item_id),203 CollectionMode::Fungible(_) => <FungibleApproveBasket<T>>::get(collection.id, who),204 CollectionMode::ReFungible => {205 <RefungibleApproveBasket<T>>::get((collection.id, item_id, who))206 }207 };208209 if let Some(last_tx_block) = last_tx_block {210 let timeout = last_tx_block + limit.into();211 if block_number < timeout {212 return None;213 }214 }215216 match collection.mode {217 CollectionMode::NFT => <NftApproveBasket<T>>::insert(collection.id, item_id, block_number),218 CollectionMode::Fungible(_) => {219 <FungibleApproveBasket<T>>::insert(collection.id, who, block_number)220 }221 CollectionMode::ReFungible => {222 <RefungibleApproveBasket<T>>::insert((collection.id, item_id, who), block_number)223 }224 };225226 Some(())227}228229fn load<T: Config>(id: CollectionId) -> Option<(T::AccountId, CollectionHandle<T>)> {230 let collection = CollectionHandle::new(id)?;231 let sponsor = collection.sponsorship.sponsor().cloned()?;232 Some((sponsor, collection))233}234235pub struct UniqueSponsorshipHandler<T>(PhantomData<T>);236impl<T, C> SponsorshipHandler<T::AccountId, C> for UniqueSponsorshipHandler<T>237where238 T: Config,239 C: IsSubType<Call<T>>,240{241 fn get_sponsor(who: &T::AccountId, call: &C) -> Option<T::AccountId> {242 match IsSubType::<Call<T>>::is_sub_type(call)? {243 Call::create_item {244 collection_id,245 data,246 ..247 } => {248 let (sponsor, collection) = load(*collection_id)?;249 withdraw_create_item::<T>(250 &collection,251 &T::CrossAccountId::from_sub(who.clone()),252 data,253 )254 .map(|()| sponsor)255 }256 Call::transfer {257 collection_id,258 item_id,259 ..260 } => {261 let (sponsor, collection) = load(*collection_id)?;262 withdraw_transfer::<T>(263 &collection,264 &T::CrossAccountId::from_sub(who.clone()),265 item_id,266 )267 .map(|()| sponsor)268 }269 Call::transfer_from {270 collection_id,271 item_id,272 from,273 ..274 } => {275 let (sponsor, collection) = load(*collection_id)?;276 withdraw_transfer::<T>(&collection, from, item_id).map(|()| sponsor)277 }278 Call::approve {279 collection_id,280 item_id,281 ..282 } => {283 let (sponsor, collection) = load(*collection_id)?;284 withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)285 }286 Call::set_variable_meta_data {287 collection_id,288 item_id,289 data,290 } => {291 let (sponsor, collection) = load(*collection_id)?;292 withdraw_set_variable_meta_data::<T>(293 &T::CrossAccountId::from_sub(who.clone()),294 &collection,295 item_id,296 data,297 )298 .map(|()| sponsor)299 }300 _ => None,301 }302 }303}304305use crate::SponsorshipPredict;306use up_data_structs::SponsorshipState;307pub struct UniqueSponsorshipPredict<T>(PhantomData<T>);308309impl<T> SponsorshipPredict<T> for UniqueSponsorshipPredict<T>310where311 T: Config,312{313 fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option<u64>314 where315 u64: From<<T as frame_system::Config>::BlockNumber>,316 {317 let collection = <CollectionHandle<T>>::try_get(collection_id).ok()?;318319 // preliminary sponsoring correctness check320 match collection.sponsorship {321 SponsorshipState::Disabled | SponsorshipState::Unconfirmed(_) => return None,322 _ => (),323 }324325 // sponsor timeout326 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;327 let limit = collection328 .limits329 .sponsor_transfer_timeout(match collection.mode {330 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,331 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,332 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,333 });334335 let last_tx_block = match collection.mode {336 CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),337 CollectionMode::Fungible(_) => {338 <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())339 }340 CollectionMode::ReFungible => {341 <ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))342 }343 };344345 if let Some(last_tx_block) = last_tx_block {346 let timeout = last_tx_block + limit.into();347 if block_number < timeout {348 return Some((timeout - block_number).into());349 }350 return Some(0);351 }352353 let token_exists = match collection.mode {354 CollectionMode::NFT => {355 <pallet_nonfungible::TokenData<T>>::contains_key((collection.id, token))356 }357 CollectionMode::Fungible(_) => true,358 CollectionMode::ReFungible => {359 <pallet_refungible::TotalSupply<T>>::contains_key((collection.id, token))360 }361 };362363 if token_exists {364 Some(0)365 } else {366 None367 }368369 // // existance check370 // match collection.mode {371 // CollectionMode::NFT => <NftTransferBasket<T>>::get(collection.id, token),372 // CollectionMode::Fungible(_) => {373 // <FungibleTransferBasket<T>>::get(collection.id, who.as_sub())374 // }375 // CollectionMode::ReFungible => {376 // <ReFungibleTransferBasket<T>>::get((collection.id, token, who.as_sub()))377 // }378 // };379 }380}primitives/rpc/src/lib.rsdiffbeforeafterboth--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -59,5 +59,6 @@
fn last_token_id(collection: CollectionId) -> Result<TokenId>;
fn collection_by_id(collection: CollectionId) -> Result<Option<Collection<AccountId>>>;
fn collection_stats() -> Result<CollectionStats>;
+ fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>>;
}
}
runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -69,6 +69,13 @@
fn collection_stats() -> Result<CollectionStats, DispatchError> {
Ok(<pallet_common::Pallet<Runtime>>::collection_stats())
}
+ fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>, DispatchError> {
+ Ok(<pallet_unique::UniqueSponsorshipPredict<Runtime> as
+ pallet_unique::SponsorshipPredict<Runtime>>::predict(
+ collection,
+ account,
+ token))
+ }
}
impl sp_api::Core<Block> for Runtime {
tests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth--- 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<Bytes>>;
+ /**
+ * 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<Option<u64>>>;
};
web3: {
/**
tests/src/interfaces/unique/definitions.tsdiffbeforeafterboth--- 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<UpDataStructsCollection>'),
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<u64>'),
},
};