--- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -54,6 +54,7 @@ mod default_weights; pub const MAX_DECIMAL_POINTS: DecimalPoints = 30; +pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000; pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000; pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000; @@ -71,8 +72,7 @@ NFT, // decimal points Fungible(DecimalPoints), - // decimal points - ReFungible(DecimalPoints), + ReFungible, } impl Default for CollectionMode { @@ -87,7 +87,7 @@ CollectionMode::Invalid => 0, CollectionMode::NFT => 1, CollectionMode::Fungible(_) => 2, - CollectionMode::ReFungible(_) => 3, + CollectionMode::ReFungible => 3, } } } @@ -266,6 +266,7 @@ pub struct CreateReFungibleData { pub const_data: Vec, pub variable_data: Vec, + pub pieces: u128, } #[derive(Encode, Decode, Debug, Clone, PartialEq)] @@ -377,7 +378,9 @@ /// Collection limit bounds per collection exceeded CollectionLimitBoundsExceeded, /// Schema data size limit bound exceeded - SchemaDataLimitExceeded + SchemaDataLimitExceeded, + /// Maximum refungibility exceeded + WrongRefungiblePieces } } @@ -548,7 +551,6 @@ let decimal_points = match mode { CollectionMode::Fungible(points) => points, - CollectionMode::ReFungible(points) => points, _ => 0 }; @@ -933,7 +935,7 @@ Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?; Self::validate_create_item_args(&target_collection, &data)?; - Self::create_item_no_validation(collection_id, &target_collection, owner, data)?; + Self::create_item_no_validation(collection_id, owner, data)?; Ok(()) } @@ -973,7 +975,7 @@ Self::validate_create_item_args(&target_collection, data)?; } for data in &items_data { - Self::create_item_no_validation(collection_id, &target_collection, owner.clone(), data.clone())?; + Self::create_item_no_validation(collection_id, owner.clone(), data.clone())?; } Ok(()) @@ -1012,7 +1014,7 @@ { CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?, CollectionMode::Fungible(_) => Self::burn_fungible_item(&sender, collection_id, value)?, - CollectionMode::ReFungible(_) => Self::burn_refungible_item(collection_id, item_id, &sender)?, + CollectionMode::ReFungible => Self::burn_refungible_item(collection_id, item_id, &sender)?, _ => () }; @@ -1154,7 +1156,7 @@ { CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, from, recipient)?, CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, value, &from, &recipient)?, - CollectionMode::ReFungible(_) => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?, + CollectionMode::ReFungible => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?, _ => () }; @@ -1211,7 +1213,7 @@ match target_collection.mode { CollectionMode::NFT => Self::set_nft_variable_data(collection_id, item_id, data)?, - CollectionMode::ReFungible(_) => Self::set_re_fungible_variable_data(collection_id, item_id, data)?, + CollectionMode::ReFungible => Self::set_re_fungible_variable_data(collection_id, item_id, data)?, CollectionMode::Fungible(_) => fail!(Error::::CantStoreMetadataInFungibleTokens), _ => fail!(Error::::UnexpectedCollectionType) }; @@ -1551,7 +1553,7 @@ { CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?, CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, value, &sender, &recipient)?, - CollectionMode::ReFungible(_) => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?, + CollectionMode::ReFungible => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?, _ => () }; @@ -1603,12 +1605,16 @@ fail!(Error::::NotFungibleDataUsedToMintFungibleCollectionToken); } }, - CollectionMode::ReFungible(_) => { + CollectionMode::ReFungible => { if let CreateItemData::ReFungible(data) = data { // check sizes ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, Error::::TokenConstDataLimitExceeded); ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, Error::::TokenVariableDataLimitExceeded); + + // Check refungibility limits + ensure!(data.pieces <= MAX_REFUNGIBLE_PIECES, Error::::WrongRefungiblePieces); + ensure!(data.pieces > 0, Error::::WrongRefungiblePieces); } else { fail!(Error::::NotReFungibleDataUsedToMintReFungibleCollectionToken); } @@ -1619,7 +1625,7 @@ Ok(()) } - fn create_item_no_validation(collection_id: CollectionId, collection: &CollectionType, owner: T::AccountId, data: CreateItemData) -> DispatchResult { + fn create_item_no_validation(collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult { match data { CreateItemData::NFT(data) => { @@ -1636,8 +1642,7 @@ }, CreateItemData::ReFungible(data) => { let mut owner_list = Vec::new(); - let value = (10 as u128).pow(collection.decimal_points as u32); - owner_list.push(Ownership {owner: owner.clone(), fraction: value}); + owner_list.push(Ownership {owner: owner.clone(), fraction: data.pieces}); let item = ReFungibleItemType { owner: owner_list, @@ -1866,7 +1871,7 @@ CollectionMode::Fungible(_) => { >::contains_key(collection_id, &subject) } - CollectionMode::ReFungible(_) => { + CollectionMode::ReFungible => { >::get(collection_id, item_id) .owner .iter() @@ -1895,7 +1900,7 @@ { CollectionMode::NFT => >::contains_key(collection_id, item_id), CollectionMode::Fungible(_) => >::contains_key(collection_id, owner), - CollectionMode::ReFungible(_) => >::contains_key(collection_id, item_id), + CollectionMode::ReFungible => >::contains_key(collection_id, item_id), _ => false }; @@ -2421,7 +2426,7 @@ sponsored } - CollectionMode::ReFungible(_) => { + CollectionMode::ReFungible => { // get correct limit let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 { --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -35,7 +35,7 @@ } fn default_re_fungible_data () -> CreateReFungibleData { - CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] } + CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1], pieces: 1023 } } fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId { @@ -114,26 +114,6 @@ } #[test] -fn create_re_fungible_collection_fails_with_large_decimal_numbers() { - new_test_ext().execute_with(|| { - default_limits(); - - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); - let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); - let token_prefix1: Vec = b"token_prefix1\0".to_vec(); - - let origin1 = Origin::signed(1); - assert_noop!(TemplateModule::create_collection( - origin1, - col_name1, - col_desc1, - token_prefix1, - CollectionMode::ReFungible(MAX_DECIMAL_POINTS + 1) - ), Error::::CollectionDecimalPointLimitExceeded); - }); -} - -#[test] fn create_nft_item() { new_test_ext().execute_with(|| { default_limits(); @@ -176,7 +156,7 @@ fn create_refungible_item() { new_test_ext().execute_with(|| { default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1); + let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let data = default_re_fungible_data(); create_test_item(collection_id, &data.clone().into()); @@ -192,7 +172,7 @@ TemplateModule::refungible_item_id(collection_id, 1).owner[0], Ownership { owner: 1, - fraction: 1000 + fraction: 1023 } ); }); @@ -203,7 +183,7 @@ new_test_ext().execute_with(|| { default_limits(); - create_test_collection(&CollectionMode::ReFungible(3), 1); + create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -224,7 +204,7 @@ item.owner[0], Ownership { owner: 1, - fraction: 1000 + fraction: 1023 } ); } @@ -312,7 +292,7 @@ new_test_ext().execute_with(|| { default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1); + let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let data = default_re_fungible_data(); create_test_item(collection_id, &data.clone().into()); @@ -331,23 +311,23 @@ TemplateModule::refungible_item_id(collection_id, 1).owner[0], Ownership { owner: 1, - fraction: 1000 + fraction: 1023 } ); - assert_eq!(TemplateModule::balance_count(1, 1), 1000); + assert_eq!(TemplateModule::balance_count(1, 1), 1023); assert_eq!(TemplateModule::address_tokens(1, 1), [1]); // change owner scenario - assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000)); + assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1023)); assert_eq!( TemplateModule::refungible_item_id(1, 1).owner[0], Ownership { owner: 2, - fraction: 1000 + fraction: 1023 } ); assert_eq!(TemplateModule::balance_count(1, 1), 0); - assert_eq!(TemplateModule::balance_count(1, 2), 1000); + assert_eq!(TemplateModule::balance_count(1, 2), 1023); // assert_eq!(TemplateModule::address_tokens(1, 1), []); assert_eq!(TemplateModule::address_tokens(1, 2), [1]); @@ -357,7 +337,7 @@ TemplateModule::refungible_item_id(1, 1).owner[0], Ownership { owner: 2, - fraction: 500 + fraction: 523 } ); assert_eq!( @@ -367,7 +347,7 @@ fraction: 500 } ); - assert_eq!(TemplateModule::balance_count(1, 2), 500); + assert_eq!(TemplateModule::balance_count(1, 2), 523); assert_eq!(TemplateModule::balance_count(1, 3), 500); assert_eq!(TemplateModule::address_tokens(1, 2), [1]); assert_eq!(TemplateModule::address_tokens(1, 3), [1]); @@ -378,7 +358,7 @@ TemplateModule::refungible_item_id(1, 1).owner[0], Ownership { owner: 2, - fraction: 300 + fraction: 323 } ); assert_eq!( @@ -388,7 +368,7 @@ fraction: 700 } ); - assert_eq!(TemplateModule::balance_count(1, 2), 300); + assert_eq!(TemplateModule::balance_count(1, 2), 323); assert_eq!(TemplateModule::balance_count(1, 3), 700); assert_eq!(TemplateModule::address_tokens(1, 2), [1]); assert_eq!(TemplateModule::address_tokens(1, 3), [1]); @@ -517,7 +497,7 @@ new_test_ext().execute_with(|| { default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1); + let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); @@ -525,7 +505,7 @@ let data = default_re_fungible_data(); create_test_item(collection_id, &data.into()); - assert_eq!(TemplateModule::balance_count(1, 1), 1000); + assert_eq!(TemplateModule::balance_count(1, 1), 1023); assert_eq!(TemplateModule::address_tokens(1, 1), [1]); assert_ok!(TemplateModule::set_mint_permission( @@ -543,8 +523,8 @@ assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3)); // do approve - assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1000)); - assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1000); + assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1023)); + assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023); assert_ok!(TemplateModule::transfer_from( origin2.clone(), @@ -554,14 +534,14 @@ 1, 100 )); - assert_eq!(TemplateModule::balance_count(1, 1), 900); + assert_eq!(TemplateModule::balance_count(1, 1), 923); assert_eq!(TemplateModule::balance_count(1, 3), 100); assert_eq!(TemplateModule::address_tokens(1, 1), [1]); assert_eq!(TemplateModule::address_tokens(1, 3), [1]); assert_eq!( TemplateModule::approved(1, (1, 1, 2)), - 900 + 923 ); }); } @@ -717,7 +697,7 @@ new_test_ext().execute_with(|| { default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1); + let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); assert_ok!(TemplateModule::set_mint_permission( @@ -738,12 +718,12 @@ create_test_item(collection_id, &data.into()); // check balance (collection with id = 1, user id = 2) - assert_eq!(TemplateModule::balance_count(1, 1), 1000); + assert_eq!(TemplateModule::balance_count(1, 1), 1023); // burn item - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1000)); + assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023)); assert_noop!( - TemplateModule::burn_item(origin1.clone(), 1, 1, 1000), + TemplateModule::burn_item(origin1.clone(), 1, 1, 1023), Error::::TokenNotFound ); @@ -807,7 +787,7 @@ let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1); let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2); - let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible(3), 3); + let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3); // check balance before assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0); @@ -826,7 +806,7 @@ // check balance (collection with id = 1, user id = 1) assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1); assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5); - assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1000); + assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1023); assert_eq!(TemplateModule::nft_item_id(nft_collection_id, 1).owner, 1); assert_eq!(TemplateModule::fungible_item_id(fungible_collection_id, 1).value, 5); assert_eq!(TemplateModule::refungible_item_id(re_fungible_collection_id, 1).owner[0].owner, 1); @@ -1905,7 +1885,7 @@ new_test_ext().execute_with(|| { default_limits(); - let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1); + let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); @@ -1982,7 +1962,7 @@ })); - let collection_id = create_test_collection(&CollectionMode::ReFungible(3), 1); + let collection_id = create_test_collection(&CollectionMode::ReFungible, 1); let origin1 = Origin::signed(1); --- a/runtime_types.json +++ b/runtime_types.json @@ -1,27 +1,4 @@ { - "Schedule": { - "version": "u32", - "put_code_per_byte_cost": "Gas", - "grow_mem_cost": "Gas", - "regular_op_cost": "Gas", - "return_data_per_byte_cost": "Gas", - "event_data_per_byte_cost": "Gas", - "event_per_topic_cost": "Gas", - "event_base_cost": "Gas", - "call_base_cost": "Gas", - "instantiate_base_cost": "Gas", - "dispatch_base_cost": "Gas", - "sandbox_data_read_cost": "Gas", - "sandbox_data_write_cost": "Gas", - "transfer_cost": "Gas", - "instantiate_cost": "Gas", - "max_event_topics": "u32", - "max_stack_height": "u32", - "max_memory_pages": "u32", - "max_table_size": "u32", - "enable_println": "bool", - "max_subject_len": "u32" - }, "AccessMode": { "_enum": [ "Normal", @@ -34,7 +11,7 @@ "Invalid": null, "NFT": null, "Fungible": "DecimalPoints", - "ReFungible": "DecimalPoints" + "ReFungible": null } }, "Ownership": { @@ -84,7 +61,8 @@ }, "CreateReFungibleData": { "const_data": "Vec", - "variable_data": "Vec" + "variable_data": "Vec", + "pieces": "u128" }, "CreateItemData": { "_enum": { @@ -118,14 +96,5 @@ "SponsoredMintSize": "u32", "TokenLimit": "u32", "SponsorTimeout": "u32" - }, - "AccountInfo": "AccountInfoWithProviders", - "AccountInfoWithProviders": { - "nonce": "Index", - "consumers": "RefCount", - "providers": "RefCount", - "data": "AccountData" } - - } - \ No newline at end of file +} \ No newline at end of file --- a/tests/src/addCollectionAdmin.test.ts +++ b/tests/src/addCollectionAdmin.test.ts @@ -1,4 +1,9 @@ -import { ApiPromise } from '@polkadot/api'; +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + +import { ApiPromise } from '@polkadot/api'; import BN from 'bn.js'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; @@ -98,7 +103,7 @@ }); }); - it('Add an admin to a collection that has reached the maximum number of admins limit', async () => { + it.only('Add an admin to a collection that has reached the maximum number of admins limit', async () => { await usingApi(async (api: ApiPromise) => { const Alice = privateKey('//Alice'); const accounts = [ @@ -112,8 +117,8 @@ ]; const collectionId = await createCollectionExpectSuccess(); - const chainLimits: any = await api.query.nft.chainLimit(); - const chainAdminLimit = chainLimits.CollectionAdminsLimit.toNumber(); + const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN }; + const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber(); expect(chainAdminLimit).to.be.equal(5); for (let i = 0; i < chainAdminLimit; i++) { --- a/tests/src/addToContractWhiteList.test.ts +++ b/tests/src/addToContractWhiteList.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import chai from "chai"; import chaiAsPromised from 'chai-as-promised'; import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api"; --- a/tests/src/addToWhiteList.test.ts +++ b/tests/src/addToWhiteList.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { IKeyringPair } from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; --- a/tests/src/approve.test.ts +++ b/tests/src/approve.test.ts @@ -34,7 +34,7 @@ await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob); // reFungible const reFungibleCollectionId = - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob); }); @@ -56,7 +56,7 @@ await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 0); // reFungible const reFungibleCollectionId = - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 1); await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 0); @@ -95,7 +95,7 @@ await approveExpectFail(fungibleCollectionId, 1, Alice, Bob); // reFungible const reFungibleCollectionId = - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); await destroyCollectionExpectSuccess(reFungibleCollectionId); await approveExpectFail(reFungibleCollectionId, 1, Alice, Bob); }); @@ -113,7 +113,7 @@ await approveExpectFail(fungibleCollectionId, 2, Alice, Bob); // reFungible const reFungibleCollectionId = - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); await approveExpectFail(reFungibleCollectionId, 2, Alice, Bob); }); }); @@ -132,7 +132,7 @@ await approveExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice); // reFungible const reFungibleCollectionId = - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Bob, Alice); }); --- a/tests/src/burnItem.test.ts +++ b/tests/src/burnItem.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api'; import { Keyring } from "@polkadot/api"; import { IKeyringPair } from "@polkadot/types/types"; @@ -70,7 +75,7 @@ }); it('Burn item in ReFungible collection', async () => { const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }}); + const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }}); const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); await usingApi(async (api) => { @@ -91,7 +96,7 @@ it('Burn owned portion of item in ReFungible collection', async () => { const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }}); + const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}}); const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); await usingApi(async (api) => { @@ -107,7 +112,7 @@ const tx = api.tx.nft.burnItem(collectionId, tokenId, 0); const events2 = await submitTransactionAsync(bob, tx); const result2 = getGenericResult(events2); - + // Get balances const balance: any = (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON(); // console.log(balance); --- a/tests/src/change-collection-owner.test.ts +++ b/tests/src/change-collection-owner.test.ts @@ -1,4 +1,9 @@ -import chai from 'chai'; +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + +import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import privateKey from './substrate/privateKey'; import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api"; --- a/tests/src/confirmSponsorship.test.ts +++ b/tests/src/confirmSponsorship.test.ts @@ -115,7 +115,7 @@ }); it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }}); + const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); await setCollectionSponsorExpectSuccess(collectionId, bob.address); await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); @@ -247,7 +247,7 @@ }); it('ReFungible: Sponsoring is rate limited', async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }}); + const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); await setCollectionSponsorExpectSuccess(collectionId, bob.address); await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); --- a/tests/src/contracts.test.ts +++ b/tests/src/contracts.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import chai from "chai"; import chaiAsPromised from 'chai-as-promised'; import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api"; --- a/tests/src/createCollection.test.ts +++ b/tests/src/createCollection.test.ts @@ -28,7 +28,7 @@ await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); }); it('Create new ReFungible collection', async () => { - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); }); }); --- a/tests/src/createItem.test.ts +++ b/tests/src/createItem.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { default as usingApi } from './substrate/substrate-api'; import { Keyring } from "@polkadot/api"; import { IKeyringPair } from "@polkadot/types/types"; @@ -28,7 +33,7 @@ }); it('Create new item in ReFungible collection', async () => { const createMode = 'ReFungible'; - const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}}); + const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}}); await createItemExpectSuccess(alice, newCollectionID, createMode); }); }); --- a/tests/src/createMultipleItems.test.ts +++ b/tests/src/createMultipleItems.test.ts @@ -56,14 +56,14 @@ it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => { await usingApi(async (api: ApiPromise) => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN; expect(itemsListIndexBefore.toNumber()).to.be.equal(0); const Alice = privateKey('//Alice'); const args = [ - { Refungible: ['0x31', '0x31'] }, - { Refungible: ['0x32', '0x32'] }, - { Refungible: ['0x33', '0x33'] }, + {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}}, + {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}}, + {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}}, ]; const createMultipleItemsTx = await api.tx.nft .createMultipleItems(collectionId, Alice.address, args); @@ -137,7 +137,7 @@ // ReFungible const collectionIdReFungible = - await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const argsReFungible = [ { ReFungible: ['1'.repeat(2049), '1'.repeat(2049)] }, { ReFungible: ['2'.repeat(2049), '2'.repeat(2049)] }, --- a/tests/src/destroyCollection.test.ts +++ b/tests/src/destroyCollection.test.ts @@ -1,12 +1,14 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api"; -import { createCollectionExpectSuccess, createCollectionExpectFailure, destroyCollectionExpectSuccess, destroyCollectionExpectFailure } from "./util/helpers"; -import type { AccountId, EventRecord } from '@polkadot/types/interfaces'; -import privateKey from './substrate/privateKey'; +import { default as usingApi } from "./substrate/substrate-api"; +import { createCollectionExpectSuccess, destroyCollectionExpectSuccess, destroyCollectionExpectFailure } from "./util/helpers"; chai.use(chaiAsPromised); -const expect = chai.expect; describe('integration test: ext. destroyCollection():', () => { it('NFT collection can be destroyed', async () => { @@ -18,7 +20,7 @@ await destroyCollectionExpectSuccess(collectionId); }); it('ReFungible collection can be destroyed', async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); await destroyCollectionExpectSuccess(collectionId); }); }); --- a/tests/src/enableContractSponsoring.test.ts +++ b/tests/src/enableContractSponsoring.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { IKeyringPair } from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; --- a/tests/src/removeCollectionAdmin.test.ts +++ b/tests/src/removeCollectionAdmin.test.ts @@ -1,5 +1,9 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { ApiPromise } from '@polkadot/api'; -import BN from 'bn.js'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import privateKey from './substrate/privateKey'; --- a/tests/src/removeFromWhiteList.test.ts +++ b/tests/src/removeFromWhiteList.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { default as usingApi } from './substrate/substrate-api'; --- a/tests/src/setCollectionLimits.test.ts +++ b/tests/src/setCollectionLimits.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + // https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits import { ApiPromise, Keyring } from '@polkadot/api'; import { IKeyringPair } from '@polkadot/types/types'; --- a/tests/src/setCollectionSponsor.test.ts +++ b/tests/src/setCollectionSponsor.test.ts @@ -9,7 +9,6 @@ import { createCollectionExpectSuccess, setCollectionSponsorExpectSuccess, destroyCollectionExpectSuccess, setCollectionSponsorExpectFailure } from "./util/helpers"; import { Keyring } from "@polkadot/api"; import { IKeyringPair } from "@polkadot/types/types"; -import type { AccountId } from '@polkadot/types/interfaces'; chai.use(chaiAsPromised); const expect = chai.expect; @@ -34,7 +33,7 @@ await setCollectionSponsorExpectSuccess(collectionId, bob.address); }); it('Set ReFungible collection sponsor', async () => { - const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible', decimalPoints: 0} }); + const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible'} }); await setCollectionSponsorExpectSuccess(collectionId, bob.address); }); --- a/tests/src/setConstOnChainSchema.test.ts +++ b/tests/src/setConstOnChainSchema.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { Keyring } from '@polkadot/api'; import { IKeyringPair } from '@polkadot/types/types'; import chai from 'chai'; --- a/tests/src/setContractSponsoringRateLimit.test.ts +++ b/tests/src/setContractSponsoringRateLimit.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { IKeyringPair } from '@polkadot/types/types'; import privateKey from './substrate/privateKey'; import usingApi from './substrate/substrate-api'; --- a/tests/src/setMintPermission.test.ts +++ b/tests/src/setMintPermission.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { IKeyringPair } from '@polkadot/types/types'; import privateKey from './substrate/privateKey'; import usingApi from './substrate/substrate-api'; --- a/tests/src/setPublicAccessMode.test.ts +++ b/tests/src/setPublicAccessMode.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + // https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion import { ApiPromise, Keyring } from '@polkadot/api'; import { IKeyringPair } from '@polkadot/types/types'; --- a/tests/src/setSchemaVersion.test.ts +++ b/tests/src/setSchemaVersion.test.ts @@ -1,7 +1,11 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + // https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion import { ApiPromise, Keyring } from '@polkadot/api'; import { IKeyringPair } from '@polkadot/types/types'; -import BN from 'bn.js'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api'; --- a/tests/src/setVariableMetaData.test.ts +++ b/tests/src/setVariableMetaData.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { IKeyringPair } from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; --- a/tests/src/setVariableOnChainSchema.test.ts +++ b/tests/src/setVariableOnChainSchema.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import { Keyring } from '@polkadot/api'; import { IKeyringPair } from '@polkadot/types/types'; import chai from 'chai'; --- a/tests/src/toggleContractWhiteList.test.ts +++ b/tests/src/toggleContractWhiteList.test.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import chai from "chai"; import chaiAsPromised from 'chai-as-promised'; import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api"; --- a/tests/src/transfer.test.ts +++ b/tests/src/transfer.test.ts @@ -63,7 +63,7 @@ }); }); - it('Create collection, balance transfers and check balance', async () => { + it('User can transfer owned token', async () => { await usingApi(async (api) => { const Alice = privateKey('//Alice'); const Bob = privateKey('//Bob'); @@ -77,10 +77,10 @@ await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible'); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await transferExpectSuccess(reFungibleCollectionId, - newReFungibleTokenId, Alice, Bob, 1, 'ReFungible'); + newReFungibleTokenId, Alice, Bob, 100, 'ReFungible'); }); }); }); @@ -119,7 +119,7 @@ await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible'); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await destroyCollectionExpectSuccess(reFungibleCollectionId); await transferExpectFail(reFungibleCollectionId, @@ -134,7 +134,7 @@ await transferExpectFail(fungibleCollectionId, 2, Alice, Bob, 1, 'Fungible'); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); await transferExpectFail(reFungibleCollectionId, 2, Alice, Bob, 1, 'ReFungible'); }); @@ -151,7 +151,7 @@ await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1, 'Fungible'); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1); await transferExpectFail(reFungibleCollectionId, @@ -168,7 +168,7 @@ await transferExpectFail(fungibleCollectionId, newFungibleTokenId, Charlie, Bob, 1, 'Fungible'); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await transferExpectFail(reFungibleCollectionId, newReFungibleTokenId, Charlie, Bob, 1, 'ReFungible'); --- a/tests/src/transferFrom.test.ts +++ b/tests/src/transferFrom.test.ts @@ -25,7 +25,7 @@ await usingApi(async (api: ApiPromise) => { const Alice = privateKey('//Alice'); const Bob = privateKey('//Bob'); - const Charlie = privateKey('//CHARLIE'); + const Charlie = privateKey('//Charlie'); // nft const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); @@ -40,11 +40,11 @@ await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1, 'Fungible'); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); - await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob); + await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob, 100); await transferFromExpectSuccess(reFungibleCollectionId, - newReFungibleTokenId, Bob, Alice, Charlie, 1, 'ReFungible'); + newReFungibleTokenId, Bob, Alice, Charlie, 100, 'ReFungible'); }); }); }); @@ -54,7 +54,7 @@ await usingApi(async (api: ApiPromise) => { const Alice = privateKey('//Alice'); const Bob = privateKey('//Bob'); - const Charlie = privateKey('//CHARLIE'); + const Charlie = privateKey('//Charlie'); // nft const nftCollectionCount = await api.query.nft.createdCollectionCount() as unknown as number; await approveExpectFail(nftCollectionCount + 1, 1, Alice, Bob); @@ -96,7 +96,7 @@ await usingApi(async (api: ApiPromise) => { const Alice = privateKey('//Alice'); const Bob = privateKey('//Bob'); - const Charlie = privateKey('//CHARLIE'); + const Charlie = privateKey('//Charlie'); // nft const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); @@ -109,7 +109,7 @@ await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, Bob, Alice, Charlie, 1); @@ -120,7 +120,7 @@ await usingApi(async (api: ApiPromise) => { const Alice = privateKey('//Alice'); const Bob = privateKey('//Bob'); - const Charlie = privateKey('//CHARLIE'); + const Charlie = privateKey('//Charlie'); // nft const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); @@ -135,7 +135,7 @@ await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 2); // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob); await transferFromExpectFail(reFungibleCollectionId, @@ -147,8 +147,8 @@ await usingApi(async (api: ApiPromise) => { const Alice = privateKey('//Alice'); const Bob = privateKey('//Bob'); - const Charlie = privateKey('//CHARLIE'); - const Dave = privateKey('//DAVE'); + const Charlie = privateKey('//Charlie'); + const Dave = privateKey('//Dave'); // nft const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); @@ -174,7 +174,7 @@ } // reFungible const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}}); + createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); try { await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Dave, Bob); --- a/tests/src/types.ts +++ b/tests/src/types.ts @@ -1,3 +1,8 @@ +// +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. +// + import BN from 'bn.js'; export interface ICollectionInterface { --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -124,21 +124,6 @@ interface ReFungible { type: 'ReFungible'; - decimalPoints: number; -} - -interface Nft { - type: 'NFT' -} - -interface Fungible { - type: 'Fungible', - decimalPoints: number -} - -interface ReFungible { - type: 'ReFungible', - decimalPoints: number } type CollectionMode = Nft | Fungible | ReFungible | Invalid; @@ -174,7 +159,7 @@ } else if (mode.type === 'Fungible') { modeprm = {fungible: mode.decimalPoints}; } else if (mode.type === 'ReFungible') { - modeprm = {refungible: mode.decimalPoints}; + modeprm = {refungible: null}; } else if (mode.type === 'Invalid') { modeprm = {invalid: null}; } @@ -216,7 +201,7 @@ } else if (mode.type === 'Fungible') { modeprm = {fungible: mode.decimalPoints}; } else if (mode.type === 'ReFungible') { - modeprm = {refungible: mode.decimalPoints}; + modeprm = {refungible: null}; } else if (mode.type === 'Invalid') { modeprm = {invalid: null}; } @@ -620,6 +605,9 @@ if (createMode === 'Fungible') { const createData = {fungible: {value: 10}}; tx = api.tx.nft.createItem(collectionId, owner, createData); + } else if (createMode === 'ReFungible') { + const createData = {refungible: {const_data: [], variable_data: [], pieces: 100}}; + tx = api.tx.nft.createItem(collectionId, owner, createData); } else { tx = api.tx.nft.createItem(collectionId, owner, createMode); }