difftreelog
OwnerCanTransfer flag
in: master
10 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1164,6 +1164,7 @@
old_limit: &CollectionLimits,
mut new_limit: CollectionLimits,
) -> Result<CollectionLimits, DispatchError> {
+ let limits = old_limit;
limit_default!(old_limit, new_limit,
account_token_ownership_limit => ensure!(
new_limit <= MAX_TOKEN_OWNERSHIP,
@@ -1190,6 +1191,7 @@
),
sponsor_approve_timeout => {},
owner_can_transfer => ensure!(
+ !limits.owner_can_transfer_instaled() ||
old_limit || !new_limit,
<Error<T>>::OwnerPermissionsCantBeReverted,
),
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -409,7 +409,10 @@
.min(MAX_SPONSOR_TIMEOUT)
}
pub fn owner_can_transfer(&self) -> bool {
- self.owner_can_transfer.unwrap_or(true)
+ self.owner_can_transfer.unwrap_or(false)
+ }
+ pub fn owner_can_transfer_instaled(&self) -> bool {
+ self.owner_can_transfer.is_some()
}
pub fn owner_can_destroy(&self) -> bool {
self.owner_can_destroy.unwrap_or(true)
tests/src/approve.test.tsdiffbeforeafterboth--- a/tests/src/approve.test.ts
+++ b/tests/src/approve.test.ts
@@ -28,7 +28,7 @@
setCollectionLimitsExpectSuccess,
transferExpectSuccess,
addCollectionAdminExpectSuccess,
- adminApproveFromExpectSuccess,
+ adminApproveFromExpectFail,
getCreatedCollectionCount,
transferFromExpectSuccess,
transferFromExpectFail,
@@ -84,11 +84,11 @@
await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 0);
});
- it('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async () => {
+ it('can`t be called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {
const collectionId = await createCollectionExpectSuccess();
const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);
- await adminApproveFromExpectSuccess(collectionId, itemId, alice, bob.address, charlie.address);
+ await adminApproveFromExpectFail(collectionId, itemId, alice, bob.address, charlie.address);
});
});
@@ -292,7 +292,7 @@
});
});
-describe('Administrator and collection owner do not need approval in order to execute TransferFrom:', () => {
+describe('Administrator and collection owner do not need approval in order to execute TransferFrom (with owner_can_transfer_flag = true):', () => {
let alice: IKeyringPair;
let bob: IKeyringPair;
let charlie: IKeyringPair;
@@ -309,6 +309,7 @@
it('NFT', async () => {
const collectionId = await createCollectionExpectSuccess();
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', charlie.address);
await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'NFT');
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -317,6 +318,7 @@
it('Fungible up to an approved amount', async () => {
const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', charlie.address);
await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'Fungible');
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -325,6 +327,7 @@
it('ReFungible up to an approved amount', async () => {
const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', charlie.address);
await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'ReFungible');
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -402,7 +405,7 @@
const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await adminApproveFromExpectSuccess(collectionId, itemId, bob, alice.address, charlie.address);
+ await adminApproveFromExpectFail(collectionId, itemId, bob, alice.address, charlie.address);
});
});
tests/src/burnItem.test.tsdiffbeforeafterboth--- a/tests/src/burnItem.test.ts
+++ b/tests/src/burnItem.test.ts
@@ -23,6 +23,7 @@
normalizeAccountId,
addCollectionAdminExpectSuccess,
getBalance,
+ setCollectionLimitsExpectSuccess,
isTokenExists,
} from './util/helpers';
@@ -149,6 +150,7 @@
it('Burn item in NFT collection', async () => {
const createMode = 'NFT';
const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -167,6 +169,7 @@
it('Burn item in Fungible collection', async () => {
const createMode = 'Fungible';
const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); // Helper creates 10 fungible tokens
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
@@ -189,6 +192,7 @@
it('Burn item in ReFungible collection', async () => {
const createMode = 'ReFungible';
const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
tests/src/eth/crossTransfer.test.tsdiffbeforeafterboth--- a/tests/src/eth/crossTransfer.test.ts
+++ b/tests/src/eth/crossTransfer.test.ts
@@ -18,6 +18,7 @@
createFungibleItemExpectSuccess,
transferExpectSuccess,
transferFromExpectSuccess,
+ setCollectionLimitsExpectSuccess,
createItemExpectSuccess} from '../util/helpers';
import {collectionIdToAddress,
createEthAccountWithBalance,
@@ -35,6 +36,7 @@
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
const charlie = privateKeyWrapper('//Charlie');
+ await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});
await createFungibleItemExpectSuccess(alice, collection, {Value: 200n}, {Substrate: alice.address});
await transferExpectSuccess(collection, 0, alice, {Ethereum: subToEth(charlie.address)} , 200, 'Fungible');
await transferFromExpectSuccess(collection, 0, alice, {Ethereum: subToEth(charlie.address)}, charlie, 50, 'Fungible');
@@ -48,6 +50,7 @@
});
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
+ await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});
const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
@@ -71,6 +74,7 @@
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
const charlie = privateKeyWrapper('//Charlie');
+ await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
await transferExpectSuccess(collection, tokenId, alice, {Ethereum: subToEth(charlie.address)}, 1, 'NFT');
await transferFromExpectSuccess(collection, tokenId, alice, {Ethereum: subToEth(charlie.address)}, charlie, 1, 'NFT');
@@ -85,6 +89,7 @@
const alice = privateKeyWrapper('//Alice');
const bob = privateKeyWrapper('//Bob');
const charlie = privateKeyWrapper('//Charlie');
+ await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});
const bobProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const aliceProxy = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
const tokenId = await createItemExpectSuccess(alice, collection, 'NFT', {Substrate: alice.address});
tests/src/limits.test.tsdiffbeforeafterboth1// 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/>.1617import {IKeyringPair} from '@polkadot/types/types';18import usingApi from './substrate/substrate-api';19import {20 createCollectionExpectSuccess,21 destroyCollectionExpectSuccess,22 setCollectionLimitsExpectSuccess,23 setCollectionSponsorExpectSuccess,24 confirmSponsorshipExpectSuccess,25 createItemExpectSuccess,26 createItemExpectFailure,27 transferExpectSuccess,28 getFreeBalance,29 waitNewBlocks, burnItemExpectSuccess,30} from './util/helpers';31import {expect} from 'chai';3233describe('Number of tokens per address (NFT)', () => {34 let alice: IKeyringPair;3536 before(async () => {37 await usingApi(async (api, privateKeyWrapper) => {38 alice = privateKeyWrapper('//Alice');39 });40 });4142 it.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {4344 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});45 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 20});46 for(let i = 0; i < 10; i++){47 await createItemExpectSuccess(alice, collectionId, 'NFT');48 }49 await createItemExpectFailure(alice, collectionId, 'NFT');50 for(let i = 1; i < 11; i++) {51 await burnItemExpectSuccess(alice, collectionId, i);52 }53 await destroyCollectionExpectSuccess(collectionId);54 });5556 it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {5758 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});59 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 1});60 await createItemExpectSuccess(alice, collectionId, 'NFT');61 await createItemExpectFailure(alice, collectionId, 'NFT');62 await burnItemExpectSuccess(alice, collectionId, 1);63 await destroyCollectionExpectSuccess(collectionId);64 });65});6667describe('Number of tokens per address (ReFungible)', () => {68 let alice: IKeyringPair;6970 before(async () => {71 await usingApi(async (api, privateKeyWrapper) => {72 alice = privateKeyWrapper('//Alice');73 });74 });7576 it.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {77 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});78 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 20});79 for(let i = 0; i < 10; i++){80 await createItemExpectSuccess(alice, collectionId, 'ReFungible');81 }82 await createItemExpectFailure(alice, collectionId, 'ReFungible');83 for(let i = 1; i < 11; i++) {84 await burnItemExpectSuccess(alice, collectionId, i, 100);85 }86 await destroyCollectionExpectSuccess(collectionId);87 });8889 it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {90 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});91 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 1});92 await createItemExpectSuccess(alice, collectionId, 'ReFungible');93 await createItemExpectFailure(alice, collectionId, 'ReFungible');94 await burnItemExpectSuccess(alice, collectionId, 1, 100);95 await destroyCollectionExpectSuccess(collectionId);96 });97});9899describe.skip('Sponsor timeout (NFT) (only for special chain limits test)', () => {100 let alice: IKeyringPair;101 let bob: IKeyringPair;102 let charlie: IKeyringPair;103104 before(async () => {105 await usingApi(async (api, privateKeyWrapper) => {106 alice = privateKeyWrapper('//Alice');107 bob = privateKeyWrapper('//Bob');108 charlie = privateKeyWrapper('//Charlie');109 });110 });111112 it.skip('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {113 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});114 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});115 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');116 await setCollectionSponsorExpectSuccess(collectionId, alice.address);117 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');118 await transferExpectSuccess(collectionId, tokenId, alice, bob);119 const aliceBalanceBefore = await getFreeBalance(alice);120121 // check setting SponsorTimeout = 5, fail122 await waitNewBlocks(5);123 await transferExpectSuccess(collectionId, tokenId, bob, charlie);124 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);125 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);126127 // check setting SponsorTimeout = 7, success128 await waitNewBlocks(2); // 5 + 2129 await transferExpectSuccess(collectionId, tokenId, charlie, bob);130 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);131 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;132 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);133 await destroyCollectionExpectSuccess(collectionId);134 });135136 it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {137138 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});139 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});140 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');141 await setCollectionSponsorExpectSuccess(collectionId, alice.address);142 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');143 await transferExpectSuccess(collectionId, tokenId, alice, bob);144 const aliceBalanceBefore = await getFreeBalance(alice);145146 // check setting SponsorTimeout = 1, fail147 await waitNewBlocks(1);148 await transferExpectSuccess(collectionId, tokenId, bob, charlie);149 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);150 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);151152 // check setting SponsorTimeout = 5, success153 await waitNewBlocks(4);154 await transferExpectSuccess(collectionId, tokenId, charlie, bob);155 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);156 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;157 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);158 await destroyCollectionExpectSuccess(collectionId);159 });160});161162describe.skip('Sponsor timeout (Fungible) (only for special chain limits test)', () => {163 let alice: IKeyringPair;164 let bob: IKeyringPair;165 let charlie: IKeyringPair;166167 before(async () => {168 await usingApi(async (api, privateKeyWrapper) => {169 alice = privateKeyWrapper('//Alice');170 bob = privateKeyWrapper('//Bob');171 charlie = privateKeyWrapper('//Charlie');172 });173 });174175 it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {176 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});177 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});178 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');179 await setCollectionSponsorExpectSuccess(collectionId, alice.address);180 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');181 await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');182 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');183 const aliceBalanceBefore = await getFreeBalance(alice);184185 // check setting SponsorTimeout = 5, fail186 await waitNewBlocks(5);187 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');188 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);189 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);190191 // check setting SponsorTimeout = 7, success192 await waitNewBlocks(2); // 5 + 2193 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');194 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);195 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;196 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);197198 await destroyCollectionExpectSuccess(collectionId);199 });200201 it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {202203 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});204 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});205 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');206 await setCollectionSponsorExpectSuccess(collectionId, alice.address);207 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');208 await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');209 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');210 const aliceBalanceBefore = await getFreeBalance(alice);211212 // check setting SponsorTimeout = 1, fail213 await waitNewBlocks(1);214 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');215 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);216 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);217218 // check setting SponsorTimeout = 5, success219 await waitNewBlocks(4);220 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');221 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);222 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;223 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);224225 await destroyCollectionExpectSuccess(collectionId);226 });227});228229describe.skip('Sponsor timeout (ReFungible) (only for special chain limits test)', () => {230 let alice: IKeyringPair;231 let bob: IKeyringPair;232 let charlie: IKeyringPair;233234 before(async () => {235 await usingApi(async (api, privateKeyWrapper) => {236 alice = privateKeyWrapper('//Alice');237 bob = privateKeyWrapper('//Bob');238 charlie = privateKeyWrapper('//Charlie');239 });240 });241242 it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {243 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});244 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});245 const tokenId = await createItemExpectSuccess(alice, collectionId, 'ReFungible');246 await setCollectionSponsorExpectSuccess(collectionId, alice.address);247 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');248 await transferExpectSuccess(collectionId, tokenId, alice, bob, 100, 'ReFungible');249 const aliceBalanceBefore = await getFreeBalance(alice);250251 // check setting SponsorTimeout = 5, fail252 await waitNewBlocks(5);253 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');254 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);255 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);256257 // check setting SponsorTimeout = 7, success258 await waitNewBlocks(2); // 5 + 2259 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');260 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);261 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;262 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);263 await destroyCollectionExpectSuccess(collectionId);264 });265266 it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {267268 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});269 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});270 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');271 await setCollectionSponsorExpectSuccess(collectionId, alice.address);272 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');273 await transferExpectSuccess(collectionId, tokenId, alice, bob);274 const aliceBalanceBefore = await getFreeBalance(alice);275276 // check setting SponsorTimeout = 1, fail277 await waitNewBlocks(1);278 await transferExpectSuccess(collectionId, tokenId, bob, charlie);279 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);280 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);281282 // check setting SponsorTimeout = 5, success283 await waitNewBlocks(4);284 await transferExpectSuccess(collectionId, tokenId, charlie, bob);285 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);286 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;287 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);288 await destroyCollectionExpectSuccess(collectionId);289 });290});291292describe('Collection zero limits (NFT)', () => {293 let alice: IKeyringPair;294 let bob: IKeyringPair;295 let charlie: IKeyringPair;296297 before(async () => {298 await usingApi(async (api, privateKeyWrapper) => {299 alice = privateKeyWrapper('//Alice');300 bob = privateKeyWrapper('//Bob');301 charlie = privateKeyWrapper('//Charlie');302 });303 });304305 it.skip('Limits have 0 in tokens per address field, the chain limits are applied', async () => {306 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});307 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 0});308 for(let i = 0; i < 10; i++){309 await createItemExpectSuccess(alice, collectionId, 'NFT');310 }311 await createItemExpectFailure(alice, collectionId, 'NFT');312 });313314 it('Limits have 0 in sponsor timeout, no limits are applied', async () => {315316 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});317 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});318 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');319 await setCollectionSponsorExpectSuccess(collectionId, alice.address);320 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');321 await transferExpectSuccess(collectionId, tokenId, alice, bob);322 const aliceBalanceBefore = await getFreeBalance(alice);323324 // check setting SponsorTimeout = 0, success with next block325 await waitNewBlocks(1);326 await transferExpectSuccess(collectionId, tokenId, bob, charlie);327 const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);328 expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;329 //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);330 });331});332333describe('Collection zero limits (Fungible)', () => {334 let alice: IKeyringPair;335 let bob: IKeyringPair;336 let charlie: IKeyringPair;337338 before(async () => {339 await usingApi(async (api, privateKeyWrapper) => {340 alice = privateKeyWrapper('//Alice');341 bob = privateKeyWrapper('//Bob');342 charlie = privateKeyWrapper('//Charlie');343 });344 });345346 it('Limits have 0 in sponsor timeout, no limits are applied', async () => {347 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});348 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});349 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');350 await setCollectionSponsorExpectSuccess(collectionId, alice.address);351 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');352 await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');353 const aliceBalanceBefore = await getFreeBalance(alice);354 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');355356 // check setting SponsorTimeout = 0, success with next block357 await waitNewBlocks(1);358 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');359 const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);360 expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;361 //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);362 });363});364365describe('Collection zero limits (ReFungible)', () => {366 let alice: IKeyringPair;367 let bob: IKeyringPair;368 let charlie: IKeyringPair;369370 before(async () => {371 await usingApi(async (api, privateKeyWrapper) => {372 alice = privateKeyWrapper('//Alice');373 bob = privateKeyWrapper('//Bob');374 charlie = privateKeyWrapper('//Charlie');375 });376 });377378 it.skip('Limits have 0 in tokens per address field, the chain limits are applied', async () => {379 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});380 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 0});381 for(let i = 0; i < 10; i++){382 await createItemExpectSuccess(alice, collectionId, 'ReFungible');383 }384 await createItemExpectFailure(alice, collectionId, 'ReFungible');385 });386387 it('Limits have 0 in sponsor timeout, no limits are applied', async () => {388389 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});390 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});391 const tokenId = await createItemExpectSuccess(alice, collectionId, 'ReFungible');392 await setCollectionSponsorExpectSuccess(collectionId, alice.address);393 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');394 await transferExpectSuccess(collectionId, tokenId, alice, bob, 100, 'ReFungible');395 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');396 const aliceBalanceBefore = await getFreeBalance(alice);397398 // check setting SponsorTimeout = 0, success with next block399 await waitNewBlocks(1);400 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');401 const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);402 expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;403 //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);404 });405 406 it('Effective collection limits', async () => {407 await usingApi(async (api) => {408 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});409 410 { // Check that limits is undefined411 const collection = await api.rpc.unique.collectionById(collectionId);412 expect(collection.isSome).to.be.true;413 const limits = collection.unwrap().limits;414 expect(limits).to.be.any;415 416 expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.null;417 expect(limits.sponsoredDataSize.toHuman()).to.be.null;418 expect(limits.sponsoredDataRateLimit.toHuman()).to.be.null;419 expect(limits.tokenLimit.toHuman()).to.be.null;420 expect(limits.sponsorTransferTimeout.toHuman()).to.be.null;421 expect(limits.sponsorApproveTimeout.toHuman()).to.be.null;422 expect(limits.ownerCanTransfer.toHuman()).to.be.null;423 expect(limits.ownerCanDestroy.toHuman()).to.be.null;424 expect(limits.transfersEnabled.toHuman()).to.be.null;425 }426 427 { // Check that limits is undefined for non-existent collection428 const limits = await api.rpc.unique.effectiveCollectionLimits(11111);429 expect(limits.toHuman()).to.be.null;430 }431 432 { // Check that default values defined for collection limits433 const limitsOpt = await api.rpc.unique.effectiveCollectionLimits(collectionId);434 expect(limitsOpt.isNone).to.be.false;435 const limits = limitsOpt.unwrap();436 437 expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.eq('100,000');438 expect(limits.sponsoredDataSize.toHuman()).to.be.eq('2,048');439 expect(limits.sponsoredDataRateLimit.toHuman()).to.be.eq('SponsoringDisabled');440 expect(limits.tokenLimit.toHuman()).to.be.eq('4,294,967,295');441 expect(limits.sponsorTransferTimeout.toHuman()).to.be.eq('5');442 expect(limits.sponsorApproveTimeout.toHuman()).to.be.eq('5');443 expect(limits.ownerCanTransfer.toHuman()).to.be.true;444 expect(limits.ownerCanDestroy.toHuman()).to.be.true;445 expect(limits.transfersEnabled.toHuman()).to.be.true;446 }447448 { //Check the values for collection limits449 await setCollectionLimitsExpectSuccess(alice, collectionId, {450 accountTokenOwnershipLimit: 99_999,451 sponsoredDataSize: 1024,452 tokenLimit: 123,453 transfersEnabled: false,454 });455456 const limitsOpt = await api.rpc.unique.effectiveCollectionLimits(collectionId);457 expect(limitsOpt.isNone).to.be.false;458 const limits = limitsOpt.unwrap();459 460 expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.eq('99,999');461 expect(limits.sponsoredDataSize.toHuman()).to.be.eq('1,024');462 expect(limits.sponsoredDataRateLimit.toHuman()).to.be.eq('SponsoringDisabled');463 expect(limits.tokenLimit.toHuman()).to.be.eq('123');464 expect(limits.sponsorTransferTimeout.toHuman()).to.be.eq('5');465 expect(limits.sponsorApproveTimeout.toHuman()).to.be.eq('5');466 expect(limits.ownerCanTransfer.toHuman()).to.be.true;467 expect(limits.ownerCanDestroy.toHuman()).to.be.true;468 expect(limits.transfersEnabled.toHuman()).to.be.false;469 }470 });471 });472});4734741// 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/>.1617import {IKeyringPair} from '@polkadot/types/types';18import usingApi from './substrate/substrate-api';19import {20 createCollectionExpectSuccess,21 destroyCollectionExpectSuccess,22 setCollectionLimitsExpectSuccess,23 setCollectionSponsorExpectSuccess,24 confirmSponsorshipExpectSuccess,25 createItemExpectSuccess,26 createItemExpectFailure,27 transferExpectSuccess,28 getFreeBalance,29 waitNewBlocks, burnItemExpectSuccess,30} from './util/helpers';31import {expect} from 'chai';3233describe('Number of tokens per address (NFT)', () => {34 let alice: IKeyringPair;3536 before(async () => {37 await usingApi(async (api, privateKeyWrapper) => {38 alice = privateKeyWrapper('//Alice');39 });40 });4142 it.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {4344 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});45 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 20});46 for(let i = 0; i < 10; i++){47 await createItemExpectSuccess(alice, collectionId, 'NFT');48 }49 await createItemExpectFailure(alice, collectionId, 'NFT');50 for(let i = 1; i < 11; i++) {51 await burnItemExpectSuccess(alice, collectionId, i);52 }53 await destroyCollectionExpectSuccess(collectionId);54 });5556 it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {5758 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});59 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 1});60 await createItemExpectSuccess(alice, collectionId, 'NFT');61 await createItemExpectFailure(alice, collectionId, 'NFT');62 await burnItemExpectSuccess(alice, collectionId, 1);63 await destroyCollectionExpectSuccess(collectionId);64 });65});6667describe('Number of tokens per address (ReFungible)', () => {68 let alice: IKeyringPair;6970 before(async () => {71 await usingApi(async (api, privateKeyWrapper) => {72 alice = privateKeyWrapper('//Alice');73 });74 });7576 it.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async () => {77 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});78 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 20});79 for(let i = 0; i < 10; i++){80 await createItemExpectSuccess(alice, collectionId, 'ReFungible');81 }82 await createItemExpectFailure(alice, collectionId, 'ReFungible');83 for(let i = 1; i < 11; i++) {84 await burnItemExpectSuccess(alice, collectionId, i, 100);85 }86 await destroyCollectionExpectSuccess(collectionId);87 });8889 it('Collection limits allow lower number than chain limits, collection limits are enforced', async () => {90 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});91 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 1});92 await createItemExpectSuccess(alice, collectionId, 'ReFungible');93 await createItemExpectFailure(alice, collectionId, 'ReFungible');94 await burnItemExpectSuccess(alice, collectionId, 1, 100);95 await destroyCollectionExpectSuccess(collectionId);96 });97});9899describe.skip('Sponsor timeout (NFT) (only for special chain limits test)', () => {100 let alice: IKeyringPair;101 let bob: IKeyringPair;102 let charlie: IKeyringPair;103104 before(async () => {105 await usingApi(async (api, privateKeyWrapper) => {106 alice = privateKeyWrapper('//Alice');107 bob = privateKeyWrapper('//Bob');108 charlie = privateKeyWrapper('//Charlie');109 });110 });111112 it.skip('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {113 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});114 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});115 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');116 await setCollectionSponsorExpectSuccess(collectionId, alice.address);117 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');118 await transferExpectSuccess(collectionId, tokenId, alice, bob);119 const aliceBalanceBefore = await getFreeBalance(alice);120121 // check setting SponsorTimeout = 5, fail122 await waitNewBlocks(5);123 await transferExpectSuccess(collectionId, tokenId, bob, charlie);124 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);125 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);126127 // check setting SponsorTimeout = 7, success128 await waitNewBlocks(2); // 5 + 2129 await transferExpectSuccess(collectionId, tokenId, charlie, bob);130 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);131 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;132 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);133 await destroyCollectionExpectSuccess(collectionId);134 });135136 it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {137138 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});139 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});140 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');141 await setCollectionSponsorExpectSuccess(collectionId, alice.address);142 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');143 await transferExpectSuccess(collectionId, tokenId, alice, bob);144 const aliceBalanceBefore = await getFreeBalance(alice);145146 // check setting SponsorTimeout = 1, fail147 await waitNewBlocks(1);148 await transferExpectSuccess(collectionId, tokenId, bob, charlie);149 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);150 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);151152 // check setting SponsorTimeout = 5, success153 await waitNewBlocks(4);154 await transferExpectSuccess(collectionId, tokenId, charlie, bob);155 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);156 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;157 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);158 await destroyCollectionExpectSuccess(collectionId);159 });160});161162describe.skip('Sponsor timeout (Fungible) (only for special chain limits test)', () => {163 let alice: IKeyringPair;164 let bob: IKeyringPair;165 let charlie: IKeyringPair;166167 before(async () => {168 await usingApi(async (api, privateKeyWrapper) => {169 alice = privateKeyWrapper('//Alice');170 bob = privateKeyWrapper('//Bob');171 charlie = privateKeyWrapper('//Charlie');172 });173 });174175 it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {176 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});177 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});178 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');179 await setCollectionSponsorExpectSuccess(collectionId, alice.address);180 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');181 await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');182 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');183 const aliceBalanceBefore = await getFreeBalance(alice);184185 // check setting SponsorTimeout = 5, fail186 await waitNewBlocks(5);187 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');188 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);189 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);190191 // check setting SponsorTimeout = 7, success192 await waitNewBlocks(2); // 5 + 2193 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');194 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);195 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;196 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);197198 await destroyCollectionExpectSuccess(collectionId);199 });200201 it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {202203 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});204 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});205 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');206 await setCollectionSponsorExpectSuccess(collectionId, alice.address);207 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');208 await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');209 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');210 const aliceBalanceBefore = await getFreeBalance(alice);211212 // check setting SponsorTimeout = 1, fail213 await waitNewBlocks(1);214 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');215 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);216 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);217218 // check setting SponsorTimeout = 5, success219 await waitNewBlocks(4);220 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');221 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);222 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;223 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);224225 await destroyCollectionExpectSuccess(collectionId);226 });227});228229describe.skip('Sponsor timeout (ReFungible) (only for special chain limits test)', () => {230 let alice: IKeyringPair;231 let bob: IKeyringPair;232 let charlie: IKeyringPair;233234 before(async () => {235 await usingApi(async (api, privateKeyWrapper) => {236 alice = privateKeyWrapper('//Alice');237 bob = privateKeyWrapper('//Bob');238 charlie = privateKeyWrapper('//Charlie');239 });240 });241242 it('Collection limits have greater timeout value than chain limits, collection limits are enforced', async () => {243 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});244 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 7});245 const tokenId = await createItemExpectSuccess(alice, collectionId, 'ReFungible');246 await setCollectionSponsorExpectSuccess(collectionId, alice.address);247 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');248 await transferExpectSuccess(collectionId, tokenId, alice, bob, 100, 'ReFungible');249 const aliceBalanceBefore = await getFreeBalance(alice);250251 // check setting SponsorTimeout = 5, fail252 await waitNewBlocks(5);253 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');254 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);255 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);256257 // check setting SponsorTimeout = 7, success258 await waitNewBlocks(2); // 5 + 2259 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');260 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);261 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;262 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);263 await destroyCollectionExpectSuccess(collectionId);264 });265266 it('Collection limits have lower timeout value than chain limits, chain limits are enforced', async () => {267268 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});269 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 1});270 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');271 await setCollectionSponsorExpectSuccess(collectionId, alice.address);272 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');273 await transferExpectSuccess(collectionId, tokenId, alice, bob);274 const aliceBalanceBefore = await getFreeBalance(alice);275276 // check setting SponsorTimeout = 1, fail277 await waitNewBlocks(1);278 await transferExpectSuccess(collectionId, tokenId, bob, charlie);279 const aliceBalanceAfterUnsponsoredTransaction = await getFreeBalance(alice);280 expect(aliceBalanceAfterUnsponsoredTransaction).to.be.equals(aliceBalanceBefore);281282 // check setting SponsorTimeout = 5, success283 await waitNewBlocks(4);284 await transferExpectSuccess(collectionId, tokenId, charlie, bob);285 const aliceBalanceAfterSponsoredTransaction = await getFreeBalance(alice);286 expect(aliceBalanceAfterSponsoredTransaction < aliceBalanceBefore).to.be.true;287 //expect(aliceBalanceAfterSponsoredTransaction).to.be.lessThan(aliceBalanceBefore);288 await destroyCollectionExpectSuccess(collectionId);289 });290});291292describe('Collection zero limits (NFT)', () => {293 let alice: IKeyringPair;294 let bob: IKeyringPair;295 let charlie: IKeyringPair;296297 before(async () => {298 await usingApi(async (api, privateKeyWrapper) => {299 alice = privateKeyWrapper('//Alice');300 bob = privateKeyWrapper('//Bob');301 charlie = privateKeyWrapper('//Charlie');302 });303 });304305 it.skip('Limits have 0 in tokens per address field, the chain limits are applied', async () => {306 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});307 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 0});308 for(let i = 0; i < 10; i++){309 await createItemExpectSuccess(alice, collectionId, 'NFT');310 }311 await createItemExpectFailure(alice, collectionId, 'NFT');312 });313314 it('Limits have 0 in sponsor timeout, no limits are applied', async () => {315316 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});317 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});318 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');319 await setCollectionSponsorExpectSuccess(collectionId, alice.address);320 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');321 await transferExpectSuccess(collectionId, tokenId, alice, bob);322 const aliceBalanceBefore = await getFreeBalance(alice);323324 // check setting SponsorTimeout = 0, success with next block325 await waitNewBlocks(1);326 await transferExpectSuccess(collectionId, tokenId, bob, charlie);327 const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);328 expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;329 //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);330 });331});332333describe('Collection zero limits (Fungible)', () => {334 let alice: IKeyringPair;335 let bob: IKeyringPair;336 let charlie: IKeyringPair;337338 before(async () => {339 await usingApi(async (api, privateKeyWrapper) => {340 alice = privateKeyWrapper('//Alice');341 bob = privateKeyWrapper('//Bob');342 charlie = privateKeyWrapper('//Charlie');343 });344 });345346 it('Limits have 0 in sponsor timeout, no limits are applied', async () => {347 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});348 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});349 const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible');350 await setCollectionSponsorExpectSuccess(collectionId, alice.address);351 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');352 await transferExpectSuccess(collectionId, tokenId, alice, bob, 10, 'Fungible');353 const aliceBalanceBefore = await getFreeBalance(alice);354 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');355356 // check setting SponsorTimeout = 0, success with next block357 await waitNewBlocks(1);358 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 2, 'Fungible');359 const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);360 expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;361 //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);362 });363});364365describe('Collection zero limits (ReFungible)', () => {366 let alice: IKeyringPair;367 let bob: IKeyringPair;368 let charlie: IKeyringPair;369370 before(async () => {371 await usingApi(async (api, privateKeyWrapper) => {372 alice = privateKeyWrapper('//Alice');373 bob = privateKeyWrapper('//Bob');374 charlie = privateKeyWrapper('//Charlie');375 });376 });377378 it.skip('Limits have 0 in tokens per address field, the chain limits are applied', async () => {379 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});380 await setCollectionLimitsExpectSuccess(alice, collectionId, {accountTokenOwnershipLimit: 0});381 for(let i = 0; i < 10; i++){382 await createItemExpectSuccess(alice, collectionId, 'ReFungible');383 }384 await createItemExpectFailure(alice, collectionId, 'ReFungible');385 });386387 it('Limits have 0 in sponsor timeout, no limits are applied', async () => {388389 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});390 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorTransferTimeout: 0});391 const tokenId = await createItemExpectSuccess(alice, collectionId, 'ReFungible');392 await setCollectionSponsorExpectSuccess(collectionId, alice.address);393 await confirmSponsorshipExpectSuccess(collectionId, '//Alice');394 await transferExpectSuccess(collectionId, tokenId, alice, bob, 100, 'ReFungible');395 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');396 const aliceBalanceBefore = await getFreeBalance(alice);397398 // check setting SponsorTimeout = 0, success with next block399 await waitNewBlocks(1);400 await transferExpectSuccess(collectionId, tokenId, bob, charlie, 20, 'ReFungible');401 const aliceBalanceAfterSponsoredTransaction1 = await getFreeBalance(alice);402 expect(aliceBalanceAfterSponsoredTransaction1 < aliceBalanceBefore).to.be.true;403 //expect(aliceBalanceAfterSponsoredTransaction1).to.be.lessThan(aliceBalanceBefore);404 });405 406 it('Effective collection limits', async () => {407 await usingApi(async (api) => {408 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});409 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});410 411 { // Check that limits is undefined412 const collection = await api.rpc.unique.collectionById(collectionId);413 expect(collection.isSome).to.be.true;414 const limits = collection.unwrap().limits;415 expect(limits).to.be.any;416 417 expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.null;418 expect(limits.sponsoredDataSize.toHuman()).to.be.null;419 expect(limits.sponsoredDataRateLimit.toHuman()).to.be.null;420 expect(limits.tokenLimit.toHuman()).to.be.null;421 expect(limits.sponsorTransferTimeout.toHuman()).to.be.null;422 expect(limits.sponsorApproveTimeout.toHuman()).to.be.null;423 expect(limits.ownerCanTransfer.toHuman()).to.be.true;424 expect(limits.ownerCanDestroy.toHuman()).to.be.null;425 expect(limits.transfersEnabled.toHuman()).to.be.null;426 }427 428 { // Check that limits is undefined for non-existent collection429 const limits = await api.rpc.unique.effectiveCollectionLimits(11111);430 expect(limits.toHuman()).to.be.null;431 }432 433 { // Check that default values defined for collection limits434 const limitsOpt = await api.rpc.unique.effectiveCollectionLimits(collectionId);435 expect(limitsOpt.isNone).to.be.false;436 const limits = limitsOpt.unwrap();437 438 expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.eq('100,000');439 expect(limits.sponsoredDataSize.toHuman()).to.be.eq('2,048');440 expect(limits.sponsoredDataRateLimit.toHuman()).to.be.eq('SponsoringDisabled');441 expect(limits.tokenLimit.toHuman()).to.be.eq('4,294,967,295');442 expect(limits.sponsorTransferTimeout.toHuman()).to.be.eq('5');443 expect(limits.sponsorApproveTimeout.toHuman()).to.be.eq('5');444 expect(limits.ownerCanTransfer.toHuman()).to.be.true;445 expect(limits.ownerCanDestroy.toHuman()).to.be.true;446 expect(limits.transfersEnabled.toHuman()).to.be.true;447 }448449 { //Check the values for collection limits450 await setCollectionLimitsExpectSuccess(alice, collectionId, {451 accountTokenOwnershipLimit: 99_999,452 sponsoredDataSize: 1024,453 tokenLimit: 123,454 transfersEnabled: false,455 });456457 const limitsOpt = await api.rpc.unique.effectiveCollectionLimits(collectionId);458 expect(limitsOpt.isNone).to.be.false;459 const limits = limitsOpt.unwrap();460 461 expect(limits.accountTokenOwnershipLimit.toHuman()).to.be.eq('99,999');462 expect(limits.sponsoredDataSize.toHuman()).to.be.eq('1,024');463 expect(limits.sponsoredDataRateLimit.toHuman()).to.be.eq('SponsoringDisabled');464 expect(limits.tokenLimit.toHuman()).to.be.eq('123');465 expect(limits.sponsorTransferTimeout.toHuman()).to.be.eq('5');466 expect(limits.sponsorApproveTimeout.toHuman()).to.be.eq('5');467 expect(limits.ownerCanTransfer.toHuman()).to.be.true;468 expect(limits.ownerCanDestroy.toHuman()).to.be.true;469 expect(limits.transfersEnabled.toHuman()).to.be.false;470 }471 });472 });473});474475tests/src/nesting/graphs.test.tsdiffbeforeafterboth--- a/tests/src/nesting/graphs.test.ts
+++ b/tests/src/nesting/graphs.test.ts
@@ -3,7 +3,7 @@
import {expect} from 'chai';
import {tokenIdToCross} from '../eth/util/helpers';
import usingApi, {executeTransaction} from '../substrate/substrate-api';
-import {getCreateCollectionResult, transferExpectSuccess} from '../util/helpers';
+import {getCreateCollectionResult, transferExpectSuccess, setCollectionLimitsExpectSuccess} from '../util/helpers';
/**
* ```dot
@@ -36,6 +36,7 @@
await usingApi(async (api, privateKeyWrapper) => {
const alice = privateKeyWrapper('//Alice');
const collection = await buildComplexObjectGraph(api, alice);
+ await setCollectionLimitsExpectSuccess(alice, collection, {ownerCanTransfer: true});
// to self
await expect(
tests/src/nesting/nest.test.tsdiffbeforeafterboth--- a/tests/src/nesting/nest.test.ts
+++ b/tests/src/nesting/nest.test.ts
@@ -15,6 +15,7 @@
transferExpectFailure,
transferExpectSuccess,
transferFromExpectSuccess,
+ setCollectionLimitsExpectSuccess,
} from '../util/helpers';
import {IKeyringPair} from '@polkadot/types/types';
@@ -92,6 +93,7 @@
it('Checks token children', async () => {
await usingApi(async api => {
const collectionA = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+ await setCollectionLimitsExpectSuccess(alice, collectionA, {ownerCanTransfer: true});
await setCollectionPermissionsExpectSuccess(alice, collectionA, {nesting: {tokenOwner: true}});
const collectionB = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
tests/src/transferFrom.test.tsdiffbeforeafterboth--- a/tests/src/transferFrom.test.ts
+++ b/tests/src/transferFrom.test.ts
@@ -99,6 +99,7 @@
it('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async () => {
const collectionId = await createCollectionExpectSuccess();
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);
await transferFromExpectSuccess(collectionId, itemId, alice, bob, charlie);
@@ -257,6 +258,7 @@
await usingApi(async () => {
// nft
const nftCollectionId = await createCollectionExpectSuccess();
+ await setCollectionLimitsExpectSuccess(alice, nftCollectionId, {ownerCanTransfer: true});
const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
await approveExpectFail(nftCollectionId, newNftTokenId, alice, bob);
@@ -266,6 +268,7 @@
it('transferFrom burnt token before approve Fungible', async () => {
await usingApi(async () => {
const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
+ await setCollectionLimitsExpectSuccess(alice, fungibleCollectionId, {ownerCanTransfer: true});
const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
@@ -276,6 +279,7 @@
it('transferFrom burnt token before approve ReFungible', async () => {
await usingApi(async () => {
const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
+ await setCollectionLimitsExpectSuccess(alice, reFungibleCollectionId, {ownerCanTransfer: true});
const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);
await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, alice, bob);
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -921,6 +921,18 @@
});
}
+export async function adminApproveFromExpectFail(
+ collectionId: number,
+ tokenId: number, admin: IKeyringPair, owner: CrossAccountId | string, approved: CrossAccountId | string, amount: number | bigint = 1,
+) {
+ await usingApi(async (api: ApiPromise) => {
+ const approveUniqueTx = api.tx.unique.approve(normalizeAccountId(approved), collectionId, tokenId, amount);
+ const events = await expect(submitTransactionAsync(admin, approveUniqueTx)).to.be.rejected;
+ const result = getGenericResult(events);
+ expect(result.success).to.be.false;
+ });
+}
+
export async function
getFreeBalance(account: IKeyringPair): Promise<bigint> {
let balance = 0n;