From a6f3f04785a9b76a6ecc14afdfcba33121b43e30 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Mon, 22 Mar 2021 19:21:06 +0000 Subject: [PATCH] Merge pull request #135 from usetech-llc/feature/NFTPAR-299_storage_option_refactor Optional collections related review --- --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -199,7 +199,7 @@ } } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] +#[derive(Encode, Decode, Debug, Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct NftItemType { pub owner: AccountId, @@ -213,7 +213,7 @@ pub value: u128, } -#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)] +#[derive(Encode, Decode, Debug, Clone, PartialEq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ReFungibleItemType { pub owner: Vec>, @@ -537,15 +537,16 @@ /// Amount of items which spender can transfer out of owners account (via transferFrom) /// Collection id (controlled?2), (token id (controlled ?2) + owner account id (real) + spender account id (controlled?3)) + /// TODO: Off chain worker should remove from this map when token gets removed pub Allowances get(fn approved): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) (TokenId, T::AccountId, T::AccountId) => u128; //#region Item collections /// Collection id (controlled?2), token id (controlled?1) - pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => NftItemType; + pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option>; /// Collection id (controlled?2), owner (controlled?2) pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType; /// Collection id (controlled?2), token id (controlled?1) - pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => ReFungibleItemType; + pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option>; //#endregion //#region Index list @@ -555,6 +556,7 @@ //#region Tokens transfer 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) => T::BlockNumber; /// Collection id (controlled?2), token id (controlled?2) pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber; @@ -570,7 +572,7 @@ //#region Contract Sponsorship and Ownership /// Contract address (real) - pub ContractOwner get(fn contract_owner): map hasher(twox_64_concat) T::AccountId => T::AccountId; + pub ContractOwner get(fn contract_owner): map hasher(twox_64_concat) T::AccountId => Option; /// Contract address (real) pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(twox_64_concat) T::AccountId => bool; /// (Contract address(real), caller (real)) @@ -968,20 +970,17 @@ let sender = ensure_signed(origin)?; let collection = Self::get_collection(collection_id)?; Self::check_owner_or_admin_permissions(&collection, sender)?; - let mut admin_arr: Vec = Vec::new(); + let mut admin_arr = >::get(collection_id); - if >::contains_key(collection_id) - { - admin_arr = >::get(collection_id); - ensure!(!admin_arr.contains(&new_admin_id), Error::::AlreadyAdmin); + match admin_arr.binary_search(&new_admin_id) { + Ok(_) => {}, + Err(idx) => { + let limits = ChainLimit::get(); + ensure!(admin_arr.len() < limits.collections_admins_limit as usize, Error::::CollectionAdminsLimitExceeded); + admin_arr.insert(idx, new_admin_id); + >::insert(collection_id, admin_arr); + } } - - // Number of collection admins - ensure!((admin_arr.len() as u64) < ChainLimit::get().collections_admins_limit, Error::::CollectionAdminsLimitExceeded); - - admin_arr.push(new_admin_id); - >::insert(collection_id, admin_arr); - Ok(()) } @@ -1004,12 +1003,15 @@ let sender = ensure_signed(origin)?; let collection = Self::get_collection(collection_id)?; Self::check_owner_or_admin_permissions(&collection, sender)?; - ensure!(>::contains_key(collection_id), Error::::AdminNotFound); - let mut admin_arr = >::get(collection_id); - admin_arr.retain(|i| *i != account_id); - >::insert(collection_id, admin_arr); + match admin_arr.binary_search(&account_id) { + Ok(idx) => { + admin_arr.remove(idx); + >::insert(collection_id, admin_arr); + }, + Err(_) => {} + } Ok(()) } @@ -1267,7 +1269,7 @@ let sender = ensure_signed(origin)?; let target_collection = Self::get_collection(collection_id)?; - Self::token_exists(&target_collection, item_id, &sender)?; + Self::token_exists(&target_collection, item_id)?; // Transfer permissions check let bypasses_limits = target_collection.limits.owner_can_transfer && @@ -1419,7 +1421,7 @@ let sender = ensure_signed(origin)?; let target_collection = Self::get_collection(collection_id)?; - Self::token_exists(&target_collection, item_id, &sender)?; + Self::token_exists(&target_collection, item_id)?; ensure!(ChainLimit::get().custom_data_limit >= data.len() as u32, Error::::TokenVariableDataLimitExceeded); @@ -1668,7 +1670,11 @@ >::insert(contract_address.clone(), sender.clone()); Self::ensure_contract_owned(sender, &contract_address)?; - >::insert(contract_address, enable); + if enable { + >::insert(contract_address, true); + } else { + >::remove(contract_address); + } Ok(()) } @@ -1901,14 +1907,11 @@ let collection_id = collection.id; // Does new owner already have an account? - let mut balance: u128 = 0; - if >::contains_key(collection_id, owner) { - balance = >::get(collection_id, owner).value; - } + let balance: u128 = >::get(collection_id, owner).value; // Mint let item = FungibleItemType { - value: balance + value + value: balance.checked_add(value).ok_or(Error::::NumOverflow)?, }; >::insert(collection_id, (*owner).clone(), item); @@ -1984,11 +1987,8 @@ ) -> DispatchResult { let collection_id = collection.id; - ensure!( - >::contains_key(collection_id, item_id), - Error::::TokenNotFound - ); - let mut token = >::get(collection_id, item_id); + let mut token = >::get(collection_id, item_id) + .ok_or(Error::::TokenNotFound)?; let rft_balance = token .owner .iter() @@ -2026,11 +2026,8 @@ fn burn_nft_item(collection: &CollectionHandle, item_id: TokenId) -> DispatchResult { let collection_id = collection.id; - ensure!( - >::contains_key(collection_id, item_id), - Error::::TokenNotFound - ); - let item = >::get(collection_id, item_id); + let item = >::get(collection_id, item_id) + .ok_or(Error::::TokenNotFound)?; Self::remove_token_index(collection_id, item_id, &item.owner)?; // update balance @@ -2047,10 +2044,6 @@ fn burn_fungible_item(owner: &T::AccountId, collection: &CollectionHandle, value: u128) -> DispatchResult { let collection_id = collection.id; - ensure!( - >::contains_key(collection_id, owner), - Error::::TokenNotFound - ); let mut balance = >::get(collection_id, owner); ensure!(balance.value >= value, Error::::TokenValueNotEnough); @@ -2094,28 +2087,15 @@ } fn is_owner_or_admin_permissions(collection: &CollectionHandle, subject: T::AccountId) -> bool { - let mut result: bool = subject == collection.owner; - let exists = >::contains_key(collection.id); - - if !result & exists { - if >::get(collection.id).contains(&subject) { - result = true - } - } - - result + subject == collection.owner || >::get(collection.id).contains(&subject) } fn check_owner_or_admin_permissions( collection: &CollectionHandle, subject: T::AccountId, ) -> DispatchResult { - let result = Self::is_owner_or_admin_permissions(collection, subject.clone()); + ensure!(Self::is_owner_or_admin_permissions(collection, subject), Error::::NoPermission); - ensure!( - result, - Error::::NoPermission - ); Ok(()) } @@ -2127,20 +2107,11 @@ let collection_id = target_collection.id; match target_collection.mode { - CollectionMode::NFT => { - if >::get(collection_id, item_id).owner == subject { - return Some(1) - } - None - }, - CollectionMode::Fungible(_) => { - if >::contains_key(collection_id, &subject) { - return Some(>::get(collection_id, &subject) - .value); - } - None - }, - CollectionMode::ReFungible => >::get(collection_id, item_id) + CollectionMode::NFT => (>::get(collection_id, item_id)?.owner == subject) + .then(|| 1), + CollectionMode::Fungible(_) => Some(>::get(collection_id, &subject) + .value), + CollectionMode::ReFungible => >::get(collection_id, item_id)? .owner .iter() .find(|i| i.owner == subject) @@ -2150,22 +2121,9 @@ } fn is_item_owner(subject: T::AccountId, target_collection: &CollectionHandle, item_id: TokenId) -> bool { - let collection_id = target_collection.id; - match target_collection.mode { - CollectionMode::NFT => { - >::get(collection_id, item_id).owner == subject - } - CollectionMode::Fungible(_) => { - >::contains_key(collection_id, &subject) - } - CollectionMode::ReFungible => { - >::get(collection_id, item_id) - .owner - .iter() - .any(|i| i.owner == subject) - } - CollectionMode::Invalid => false, + CollectionMode::Fungible(_) => true, + _ => Self::owned_amount(subject, target_collection, item_id).is_some(), } } @@ -2183,13 +2141,12 @@ fn token_exists( target_collection: &CollectionHandle, item_id: TokenId, - owner: &T::AccountId ) -> DispatchResult { let collection_id = target_collection.id; let exists = match target_collection.mode { CollectionMode::NFT => >::contains_key(collection_id, item_id), - CollectionMode::Fungible(_) => >::contains_key(collection_id, owner), + CollectionMode::Fungible(_) => true, CollectionMode::ReFungible => >::contains_key(collection_id, item_id), _ => false }; @@ -2205,7 +2162,6 @@ recipient: &T::AccountId, ) -> DispatchResult { let collection_id = collection.id; - Self::token_exists(&collection, 0, owner)?; let mut balance = >::get(collection_id, owner); ensure!(balance.value >= value, Error::::TokenValueTooLow); @@ -2236,9 +2192,9 @@ new_owner: T::AccountId, ) -> DispatchResult { let collection_id = collection.id; - Self::token_exists(collection, item_id, &owner)?; + let full_item = >::get(collection_id, item_id) + .ok_or(Error::::TokenNotFound)?; - let full_item = >::get(collection_id, item_id); let item = full_item .owner .iter() @@ -2318,10 +2274,9 @@ new_owner: T::AccountId, ) -> DispatchResult { let collection_id = collection.id; - Self::token_exists(&collection, item_id, &sender)?; + let mut item = >::get(collection_id, item_id) + .ok_or(Error::::TokenNotFound)?; - let mut item = >::get(collection_id, item_id); - ensure!( sender == item.owner, Error::::MustBeTokenOwner @@ -2355,7 +2310,8 @@ data: Vec ) -> DispatchResult { let collection_id = collection.id; - let mut item = >::get(collection_id, item_id); + let mut item = >::get(collection_id, item_id) + .ok_or(Error::::TokenNotFound)?; item.variable_data = data; @@ -2370,7 +2326,8 @@ data: Vec ) -> DispatchResult { let collection_id = collection.id; - let mut item = >::get(collection_id, item_id); + let mut item = >::get(collection_id, item_id) + .ok_or(Error::::TokenNotFound)?; item.variable_data = data; @@ -2533,12 +2490,7 @@ } fn ensure_contract_owned(account: T::AccountId, contract: &T::AccountId) -> DispatchResult { - if >::contains_key(contract.clone()) { - let owner = >::get(contract); - ensure!(account == owner, Error::::NoPermission); - } else { - fail!(Error::::NoPermission); - } + ensure!(>::get(contract) == Some(account), Error::::NoPermission); Ok(()) } @@ -2787,9 +2739,8 @@ let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default()); - let owned_contract = >::contains_key(called_contract.clone()) - && >::get(called_contract.clone()) == *who; - let white_list_enabled = >::contains_key(called_contract.clone()) && >::get(called_contract.clone()); + let owned_contract = >::get(called_contract.clone()).as_ref() == Some(who); + let white_list_enabled = >::contains_key(called_contract.clone()); if !owned_contract && white_list_enabled { if !>::contains_key(called_contract.clone(), who) { --- a/tests/package.json +++ b/tests/package.json @@ -32,6 +32,7 @@ "testRemoveFromWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromWhiteList.test.ts", "testConnection": "mocha --timeout 9999999 -r ts-node/register ./**/connection.test.ts", "testCollection": "mocha --timeout 9999999 -r ts-node/register ./**/createCollection.test.ts", + "testContracts": "mocha --timeout 9999999 -r ts-node/register ./**/contracts.test.ts", "testCreateItem": "mocha --timeout 9999999 -r ts-node/register ./**/createItem.test.ts", "testCreateMultipleItems": "mocha --timeout 9999999 -r ts-node/register ./**/createMultipleItems.test.ts", "testApprove": "mocha --timeout 9999999 -r ts-node/register ./**/approve.test.ts", @@ -44,6 +45,7 @@ "testSetMintPermission": "mocha --timeout 9999999 -r ts-node/register ./**/setMintPermission.test.ts", "testCreditFeesToTreasury": "mocha --timeout 9999999 -r ts-node/register ./**/creditFeesToTreasury.test.ts", "testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts", + "testRemoveFromContractWhiteList": "mocha --timeout 9999999 -r ts-node/register ./**/removeFromContractWhiteList.test.ts", "testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts", "testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts", "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts", --- a/tests/src/approve.test.ts +++ b/tests/src/approve.test.ts @@ -123,9 +123,6 @@ // nft const nftCollectionId = await createCollectionExpectSuccess(); await approveExpectFail(nftCollectionId, 2, Alice, Bob); - // fungible - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await approveExpectFail(fungibleCollectionId, 2, Alice, Bob); // reFungible const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); --- a/tests/src/burnItem.test.ts +++ b/tests/src/burnItem.test.ts @@ -46,8 +46,7 @@ // tslint:disable-next-line:no-unused-expression expect(result.success).to.be.true; // tslint:disable-next-line:no-unused-expression - expect(item).to.be.not.null; - expect(item.Owner).to.be.equal(nullPublicKey); + expect(item).to.be.null; }); }); @@ -88,8 +87,7 @@ // What to expect expect(result.success).to.be.true; - expect(balance).to.be.not.null; - expect(balance.Owner.length).to.be.equal(0); + expect(balance).to.be.null; }); }); --- a/tests/src/contracts.test.ts +++ b/tests/src/contracts.test.ts @@ -63,13 +63,13 @@ const collectionId = await createCollectionExpectSuccess(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); const [contract, deployer] = await deployTransferContract(api); - const tokenBefore: any = await api.query.nft.nftItemList(collectionId, tokenId); + const tokenBefore: any = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap(); // Transfer const transferTx = contract.tx.transfer(value, gasLimit, bob.address, collectionId, tokenId, 1); const events = await submitTransactionAsync(alice, transferTx); const result = getGenericResult(events); - const tokenAfter: any = await api.query.nft.nftItemList(collectionId, tokenId); + const tokenAfter: any = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap(); // tslint:disable-next-line:no-unused-expression expect(result.success).to.be.true; --- a/tests/src/createMultipleItems.test.ts +++ b/tests/src/createMultipleItems.test.ts @@ -38,9 +38,9 @@ await submitTransactionAsync(Alice, createMultipleItemsTx); const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN; expect(itemsListIndexAfter.toNumber()).to.be.equal(3); - const token1Data = await api.query.nft.nftItemList(collectionId, 1) as unknown as ITokenDataType; - const token2Data = await api.query.nft.nftItemList(collectionId, 2) as unknown as ITokenDataType; - const token3Data = await api.query.nft.nftItemList(collectionId, 3) as unknown as ITokenDataType; + const token1Data = (await api.query.nft.nftItemList(collectionId, 1)).toJSON() as unknown as ITokenDataType; + const token2Data = (await api.query.nft.nftItemList(collectionId, 2)).toJSON() as unknown as ITokenDataType; + const token3Data = (await api.query.nft.nftItemList(collectionId, 3)).toJSON() as unknown as ITokenDataType; expect(token1Data.Owner.toString()).to.be.equal(Alice.address); expect(token2Data.Owner.toString()).to.be.equal(Alice.address); @@ -72,9 +72,9 @@ await submitTransactionAsync(Alice, createMultipleItemsTx); const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN; expect(itemsListIndexAfter.toNumber()).to.be.equal(3); - const token1Data = await api.query.nft.reFungibleItemList(collectionId, 1) as unknown as IReFungibleTokenDataType; - const token2Data = await api.query.nft.reFungibleItemList(collectionId, 2) as unknown as IReFungibleTokenDataType; - const token3Data = await api.query.nft.reFungibleItemList(collectionId, 3) as unknown as IReFungibleTokenDataType; + const token1Data = (await api.query.nft.reFungibleItemList(collectionId, 1) as any).unwrap() as unknown as IReFungibleTokenDataType; + const token2Data = (await api.query.nft.reFungibleItemList(collectionId, 2) as any).unwrap() as unknown as IReFungibleTokenDataType; + const token3Data = (await api.query.nft.reFungibleItemList(collectionId, 3) as any).unwrap() as unknown as IReFungibleTokenDataType; expect(token1Data.Owner[0].Owner.toString()).to.be.equal(Alice.address); expect(token1Data.Owner[0].Fraction.toNumber()).to.be.equal(1); --- a/tests/src/removeCollectionAdmin.test.ts +++ b/tests/src/removeCollectionAdmin.test.ts @@ -36,6 +36,19 @@ expect(adminListAfterRemoveAdmin).not.to.be.contains(Bob.address); }); }); + + it('Remove admin from collection that has no admins', async () => { + await usingApi(async (api: ApiPromise) => { + const Alice = privateKey('//Alice'); + const collectionId = await createCollectionExpectSuccess(); + + const adminListBeforeAddAdmin: any = (await api.query.nft.adminList(collectionId)); + expect(adminListBeforeAddAdmin).to.have.lengthOf(0); + + const tx = api.tx.nft.removeCollectionAdmin(collectionId, Alice.address); + await submitTransactionAsync(Alice, tx); + }); + }); }); describe('Negative Integration Test removeCollectionAdmin(collection_id, account_id):', () => { @@ -68,19 +81,6 @@ // Verifying that nothing bad happened (network is live, new collections can be created, etc.) await createCollectionExpectSuccess(); - }); - }); - - it('Remove admin from collection that has no admins', async () => { - await usingApi(async (api: ApiPromise) => { - const Alice = privateKey('//Alice'); - const collectionId = await createCollectionExpectSuccess(); - - const adminListBeforeAddAdmin: any = (await api.query.nft.adminList(collectionId)); - expect(adminListBeforeAddAdmin).to.have.lengthOf(0); - - const tx = api.tx.nft.removeCollectionAdmin(collectionId, Alice.address); - await expect(submitTransactionExpectFailAsync(Alice, tx)).to.be.rejected; }); }); }); --- a/tests/src/removeFromContractWhiteList.test.ts +++ b/tests/src/removeFromContractWhiteList.test.ts @@ -13,8 +13,10 @@ describe('Integration Test removeFromContractWhiteList', () => { let bob: IKeyringPair; - before(() => { - bob = privateKey('//Bob'); + before(async () => { + await usingApi(async () => { + bob = privateKey('//Bob'); + }); }); it('user is no longer whitelisted after removal', async () => { @@ -56,9 +58,11 @@ let alice: IKeyringPair; let bob: IKeyringPair; - before(() => { - alice = privateKey('//Alice'); - bob = privateKey('//Bob'); + before(async () => { + await usingApi(async () => { + alice = privateKey('//Alice'); + bob = privateKey('//Bob'); + }); }); it('fails when called with non-contract address', async () => { --- a/tests/src/setVariableMetaData.test.ts +++ b/tests/src/setVariableMetaData.test.ts @@ -41,7 +41,7 @@ it('verify data was set', async () => { await usingApi(async api => { - const item: any = await api.query.nft.nftItemList(collectionId, tokenId); + const item: any = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap(); expect(Array.from(item.VariableData)).to.deep.equal(Array.from(data)); }); --- a/tests/src/transferFrom.test.ts +++ b/tests/src/transferFrom.test.ts @@ -237,7 +237,7 @@ const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible'); await burnItemExpectSuccess(Alice, fungibleCollectionId, 1, 10); - await approveExpectFail(fungibleCollectionId, newFungibleTokenId, Alice, Bob); + await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob); await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1); }); --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -599,8 +599,7 @@ // tslint:disable-next-line:no-unused-expression expect(result.success).to.be.true; // tslint:disable-next-line:no-unused-expression - expect(item).to.be.not.null; - expect(item.Owner).to.be.equal(nullPublicKey); + expect(item).to.be.null; }); } @@ -641,16 +640,16 @@ // tslint:disable-next-line:no-unused-expression expect(result.success).to.be.true; if (type === 'NFT') { - const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType; + const nftItemData = (await api.query.nft.nftItemList(collectionId, tokenId) as any).unwrap() as ITokenDataType; expect(nftItemData.Owner.toString()).to.be.equal(accountTo.address); } if (type === 'Fungible') { - const balanceAfter = await api.query.nft.balance(collectionId, accountTo.address) as unknown as BN; + const balanceAfter = (await api.query.nft.fungibleItemList(collectionId, accountTo.address) as any).Value as unknown as BN; expect(balanceAfter.sub(balanceBefore).toString()).to.be.equal(value.toString()); } if (type === 'ReFungible') { const nftItemData = - await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType; + (await api.query.nft.reFungibleItemList(collectionId, tokenId) as any).unwrap() as IReFungibleTokenDataType; expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(accountTo.address); expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value); } @@ -697,18 +696,18 @@ expect(result.recipient).to.be.equal(recipient.address); expect(result.value.toString()).to.be.equal(value.toString()); if (type === 'NFT') { - const nftItemData = await api.query.nft.nftItemList(collectionId, tokenId) as unknown as ITokenDataType; + const nftItemData = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON() as unknown as ITokenDataType; expect(nftItemData.Owner.toString()).to.be.equal(recipient.address); } if (type === 'Fungible') { - const balanceAfter = await api.query.nft.balance(collectionId, recipient.address) as unknown as BN; + const balanceAfter = (await api.query.nft.fungibleItemList(collectionId, recipient.address) as any).Value as unknown as BN; expect(balanceAfter.sub(balanceBefore).toString()).to.be.equal(value.toString()); } if (type === 'ReFungible') { const nftItemData = - await api.query.nft.reFungibleItemList(collectionId, tokenId) as unknown as IReFungibleTokenDataType; + (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON() as unknown as IReFungibleTokenDataType; expect(nftItemData.Owner[0].Owner.toString()).to.be.equal(recipient.address); - expect(nftItemData.Owner[0].Fraction.toNumber()).to.be.equal(value); + expect(nftItemData.Owner[0].Fraction.toString()).to.be.equal(value.toString()); } }); } -- gitstuff