difftreelog
Merge pull request #411 from UniqueNetwork/feature/total_pieces
in: master
Add rpc method for total_pieces
11 files changed
client/rpc/src/lib.rsdiffbeforeafterboth191 at: Option<BlockHash>,192 at: Option<BlockHash>,192 ) -> Result<Option<CollectionLimits>>;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>>;193}202}194203195mod rmrk_unique_rpc {204mod rmrk_unique_rpc {463 pass_method!(collection_stats() -> CollectionStats, unique_api);472 pass_method!(collection_stats() -> CollectionStats, unique_api);464 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);473 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);465 pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, 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);466}476}467477468#[allow(deprecated)]478#[allow(deprecated)]pallets/common/src/lib.rsdiffbeforeafterboth1384 fn account_balance(&self, account: T::CrossAccountId) -> u32;1384 fn account_balance(&self, account: T::CrossAccountId) -> u32;1385 /// Amount of specific token account have (Applicable to fungible/refungible)1385 /// Amount of specific token account have (Applicable to fungible/refungible)1386 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;1386 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;1387 /// Amount of token pieces1388 fn total_pieces(&self, token: TokenId) -> Option<u128>;1387 fn allowance(1389 fn allowance(1388 &self,1390 &self,1389 sender: T::CrossAccountId,1391 sender: T::CrossAccountId,pallets/fungible/src/common.rsdiffbeforeafterboth25use up_data_structs::{Property, PropertyKey, PropertyValue, PropertyKeyPermission};25use up_data_structs::{Property, PropertyKey, PropertyValue, PropertyKeyPermission};262627use crate::{27use crate::{28 Allowance, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf, weights::WeightInfo,28 Allowance, TotalSupply, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf,29 weights::WeightInfo,29};30};3031406 None407 None407 }408 }409410 fn total_pieces(&self, token: TokenId) -> Option<u128> {411 if token != TokenId::default() {412 return None;413 }414 <TotalSupply<T>>::try_get(self.id).ok()415 }408}416}409417pallets/nonfungible/src/common.rsdiffbeforeafterboth488 None488 None489 }489 }490491 fn total_pieces(&self, token: TokenId) -> Option<u128> {492 if <TokenData<T>>::contains_key((self.id, token)) {493 Some(1)494 } else {495 None496 }497 }490}498}491499pallets/refungible/src/common.rsdiffbeforeafterboth412 Some(self)412 Some(self)413 }413 }414415 fn total_pieces(&self, token: TokenId) -> Option<u128> {416 <Pallet<T>>::total_pieces(self.id, token)417 }414}418}415419416impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {420impl<T: Config> RefungibleExtensions<T> for RefungibleHandle<T> {pallets/refungible/src/lib.rsdiffbeforeafterboth711 Ok(())711 Ok(())712 }712 }713714 fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128> {715 <TotalSupply<T>>::try_get((collection_id, token_id)).ok()716 }713}717}714718primitives/data-structs/src/lib.rsdiffbeforeafterboth181pub struct TokenData<CrossAccountId> {181pub struct TokenData<CrossAccountId> {182 pub properties: Vec<Property>,182 pub properties: Vec<Property>,183 pub owner: Option<CrossAccountId>,183 pub owner: Option<CrossAccountId>,184 pub pieces: u128,184}185}185186186pub struct OverflowError;187pub struct OverflowError;primitives/rpc/src/lib.rsdiffbeforeafterboth80 fn collection_stats() -> Result<CollectionStats>;80 fn collection_stats() -> Result<CollectionStats>;81 fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>>;81 fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>>;82 fn effective_collection_limits(collection_id: CollectionId) -> Result<Option<CollectionLimits>>;82 fn effective_collection_limits(collection_id: CollectionId) -> Result<Option<CollectionLimits>>;83 fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Result<Option<u128>>;83 }84 }84}85}8586runtime/common/src/runtime_apis.rsdiffbeforeafterboth89 ) -> Result<TokenData<CrossAccountId>, DispatchError> {89 ) -> Result<TokenData<CrossAccountId>, DispatchError> {90 let token_data = TokenData {90 let token_data = TokenData {91 properties: Self::token_properties(collection, token_id, keys)?,91 properties: Self::token_properties(collection, token_id, keys)?,92 owner: Self::token_owner(collection, token_id)?92 owner: Self::token_owner(collection, token_id)?,93 pieces: Self::total_pieces(collection, token_id)?.unwrap_or(0),93 };94 };949595 Ok(token_data)96 Ok(token_data)143 Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))144 Ok(<pallet_common::Pallet<Runtime>>::effective_collection_limits(collection))144 }145 }146147 fn total_pieces(collection: CollectionId, token_id: TokenId) -> Result<Option<u128>, DispatchError> {148 dispatch_unique_runtime!(collection.total_pieces(token_id))149 }145 }150 }146151147 impl sp_api::Core<Block> for Runtime {152 impl sp_api::Core<Block> for Runtime {tests/src/createItem.test.tsdiffbeforeafterboth24 createCollectionWithPropsExpectSuccess,24 createCollectionWithPropsExpectSuccess,25 createItemWithPropsExpectSuccess,25 createItemWithPropsExpectSuccess,26 createItemWithPropsExpectFailure,26 createItemWithPropsExpectFailure,27 createCollection,28 transferExpectSuccess,27} from './util/helpers';29} from './util/helpers';283029const expect = chai.expect;31const expect = chai.expect;96 await createItemWithPropsExpectSuccess(alice, newCollectionID, createMode, [{key: 'key1', value: 'val1'}]);98 await createItemWithPropsExpectSuccess(alice, newCollectionID, createMode, [{key: 'key1', value: 'val1'}]);97 });99 });100101 it('Check total pieces of Fungible token', async () => {102 await usingApi(async api => {103 const createMode = 'Fungible';104 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});105 const amountPieces = 10n;106 const tokenId = await createItemExpectSuccess(alice, collectionId, createMode, bob.address);107 {108 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);109 expect(totalPieces.isSome).to.be.true;110 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);111 }112113 await transferExpectSuccess(collectionId, tokenId, bob, alice, 1, createMode);114 {115 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);116 expect(totalPieces.isSome).to.be.true;117 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);118 }119120 const totalPieces = (await api.rpc.unique.tokenData(collectionId, tokenId, [])).pieces;121 expect(totalPieces.isSome).to.be.true;122 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);123 });124 });125126 it('Check total pieces of NFT token', async () => {127 await usingApi(async api => {128 const createMode = 'NFT';129 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});130 const amountPieces = 1n;131 const tokenId = await createItemExpectSuccess(alice, collectionId, createMode, bob.address);132 {133 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);134 expect(totalPieces.isSome).to.be.true;135 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);136 }137138 await transferExpectSuccess(collectionId, tokenId, bob, alice, 1, createMode);139 {140 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);141 expect(totalPieces.isSome).to.be.true;142 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);143 }144145 const totalPieces = (await api.rpc.unique.tokenData(collectionId, tokenId, [])).pieces;146 expect(totalPieces.isSome).to.be.true;147 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);148 });149 });150151 it('Check total pieces of ReFungible token', async () => {152 await usingApi(async api => {153 const createMode = 'ReFungible';154 const createCollectionResult = await createCollection(api, alice, {mode: {type: createMode}});155 const collectionId = createCollectionResult.collectionId;156 const amountPieces = 100n;157 const tokenId = await createItemExpectSuccess(alice, collectionId, createMode, bob.address);158 {159 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);160 expect(totalPieces.isSome).to.be.true;161 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);162 }163164 await transferExpectSuccess(collectionId, tokenId, bob, alice, 60n, createMode);165 {166 const totalPieces = await api.rpc.unique.totalPieces(collectionId, tokenId);167 expect(totalPieces.isSome).to.be.true;168 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);169 }170171 const totalPieces = (await api.rpc.unique.tokenData(collectionId, tokenId, [])).pieces;172 expect(totalPieces.isSome).to.be.true;173 expect(totalPieces.unwrap().toBigInt()).to.be.eq(amountPieces);174 });175 });98});176});99177100describe('Negative integration test: ext. createItem():', () => {178describe('Negative integration test: ext. createItem():', () => {170 });248 });171 });249 });250251 it('Check total pieces for invalid Fungible token', async () => {252 await usingApi(async api => {253 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});254 const collectionId = createCollectionResult.collectionId;255 const invalidTokenId = 1000_000;256 257 expect((await api.rpc.unique.totalPieces(collectionId, invalidTokenId)).isNone).to.be.true;258 expect((await api.rpc.unique.tokenData(collectionId, invalidTokenId, [])).pieces.isNone).to.be.true;259 });260 });261262 it('Check total pieces for invalid NFT token', async () => {263 await usingApi(async api => {264 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'NFT'}});265 const collectionId = createCollectionResult.collectionId;266 const invalidTokenId = 1000_000;267 268 expect((await api.rpc.unique.totalPieces(collectionId, invalidTokenId)).isNone).to.be.true;269 expect((await api.rpc.unique.tokenData(collectionId, invalidTokenId, [])).pieces.isNone).to.be.true;270 });271 });272273 it('Check total pieces for invalid Refungible token', async () => {274 await usingApi(async api => {275 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});276 const collectionId = createCollectionResult.collectionId;277 const invalidTokenId = 1000_000;278 279 expect((await api.rpc.unique.totalPieces(collectionId, invalidTokenId)).isNone).to.be.true;280 expect((await api.rpc.unique.tokenData(collectionId, invalidTokenId, [])).pieces.isNone).to.be.true;281 });282 });172});283});173284tests/src/interfaces/unique/definitions.tsdiffbeforeafterboth79 allowed: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam()], 'bool'),79 allowed: fun('Check if user is allowed to use collection', [collectionParam, crossAccountParam()], 'bool'),80 nextSponsored: fun('Get number of blocks when sponsored transaction is available', [collectionParam, crossAccountParam(), tokenParam], 'Option<u64>'),80 nextSponsored: fun('Get number of blocks when sponsored transaction is available', [collectionParam, crossAccountParam(), tokenParam], 'Option<u64>'),81 effectiveCollectionLimits: fun('Get effective collection limits', [collectionParam], 'Option<UpDataStructsCollectionLimits>'),81 effectiveCollectionLimits: fun('Get effective collection limits', [collectionParam], 'Option<UpDataStructsCollectionLimits>'),82 totalPieces: fun('Get total pieces of token', [collectionParam, tokenParam], 'Option<u128>'),82 },83 },83};84};8485