difftreelog
CORE-410 Adapt collection properties tests for ReFungible collections
in: master
4 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -833,7 +833,7 @@
),
);
<T as Config>::Currency::settle(
- &owner.as_sub(),
+ owner.as_sub(),
imbalance,
WithdrawReasons::TRANSFER,
ExistenceRequirement::KeepAlive,
tests/src/nesting/properties.test.tsdiffbeforeafterboth--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -2,6 +2,7 @@
import usingApi, {executeTransaction} from '../substrate/substrate-api';
import {
addCollectionAdminExpectSuccess,
+ CollectionMode,
createCollectionExpectSuccess,
setCollectionPermissionsExpectSuccess,
createItemExpectSuccess,
@@ -23,9 +24,9 @@
});
});
- it('Makes sure collectionById supplies required fields', async () => {
+ async function testMakeSureSuppliesRequired(mode: CollectionMode) {
await usingApi(async api => {
- const collectionId = await createCollectionExpectSuccess();
+ const collectionId = await createCollectionExpectSuccess({mode: mode});
const collectionOption = await api.rpc.unique.collectionById(collectionId);
expect(collectionOption.isSome).to.be.true;
@@ -57,6 +58,14 @@
expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);
expect(collection.properties.toHuman()).to.be.deep.equal(collectionProperties);
});
+ }
+
+ it('Makes sure collectionById supplies required fields for NFT', async () => {
+ await testMakeSureSuppliesRequired({type: 'NFT'});
+ });
+
+ it('Makes sure collectionById supplies required fields for ReFungible', async () => {
+ await testMakeSureSuppliesRequired({type: 'ReFungible'});
});
});
@@ -79,9 +88,10 @@
});
});
- it('Sets properties for a collection', async () => {
+
+ async function testSetsPropertiesForCollection(mode: string) {
await usingApi(async api => {
- const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));
+ const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: mode}));
const {collectionId} = getCreateCollectionResult(events);
// As owner
@@ -106,48 +116,54 @@
{key: 'black_hole', value: ''},
]);
});
+ }
+ it('Sets properties for a NFT collection', async () => {
+ await testSetsPropertiesForCollection('NFT');
});
+ it('Sets properties for a ReFungible collection', async () => {
+ await testSetsPropertiesForCollection('ReFungible');
+ });
- it('Check valid names for collection properties keys', async () => {
+ async function testCheckValidNames(mode: string) {
await usingApi(async api => {
- const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));
+ const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: mode}));
const {collectionId} = getCreateCollectionResult(events);
-
+
// alpha symbols
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'alpha'}]),
)).to.not.be.rejected;
-
+
// numeric symbols
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: '123'}]),
)).to.not.be.rejected;
-
+
// underscore symbol
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'black_hole'}]),
)).to.not.be.rejected;
-
+
// dash symbol
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'semi-automatic'}]),
)).to.not.be.rejected;
-
+
// underscore symbol
await expect(executeTransaction(
api,
bob,
api.tx.unique.setCollectionProperties(collectionId, [{key: 'build.rs'}]),
)).to.not.be.rejected;
-
+
const propertyKeys = ['alpha', '123', 'black_hole', 'semi-automatic', 'build.rs'];
const properties = (await api.rpc.unique.collectionProperties(collectionId, propertyKeys)).toHuman();
expect(properties).to.be.deep.equal([
@@ -158,54 +174,72 @@
{key: 'build.rs', value: ''},
]);
});
+ }
+ it('Check valid names for NFT collection properties keys', async () => {
+ await testCheckValidNames('NFT');
});
+ it('Check valid names for ReFungible collection properties keys', async () => {
+ await testCheckValidNames('ReFungible');
+ });
- it('Changes properties of a collection', async () => {
+ async function testChangesProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole'}]),
)).to.not.be.rejected;
-
+
// Mutate the properties
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'bonded'}, {key: 'black_hole', value: 'LIGO'}]),
)).to.not.be.rejected;
-
+
const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();
expect(properties).to.be.deep.equal([
{key: 'electron', value: 'bonded'},
{key: 'black_hole', value: 'LIGO'},
]);
});
+ }
+ it('Changes properties of a NFT collection', async () => {
+ await testChangesProperties({type: 'NFT'});
});
+ it('Changes properties of a ReFungible collection', async () => {
+ await testChangesProperties({type: 'ReFungible'});
+ });
- it('Deletes properties of a collection', async () => {
+ async function testDeleteProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]),
)).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.deleteCollectionProperties(collection, ['electron']),
)).to.not.be.rejected;
-
+
const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();
expect(properties).to.be.deep.equal([
{key: 'black_hole', value: 'LIGO'},
]);
- });
+ });
+ }
+ it('Deletes properties of a NFT collection', async () => {
+ await testDeleteProperties({type: 'NFT'});
+ });
+ it('Deletes properties of a ReFungible collection', async () => {
+ await testDeleteProperties({type: 'ReFungible'});
});
});
@@ -217,10 +251,10 @@
});
});
- it('Fails to set properties in a collection if not its onwer/administrator', async () => {
+ async function testFailsSetPropertiesIfNotOwnerOrAdmin(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
bob,
@@ -230,14 +264,20 @@
const properties = (await api.query.common.collectionProperties(collection)).toJSON();
expect(properties.map).to.be.empty;
expect(properties.consumedSpace).to.equal(0);
- });
+ });
+ }
+ it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {
+ await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});
+ });
+ it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {
+ await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});
});
- it('Fails to set properties that exceed the limits', async () => {
+ async function testFailsSetPropertiesThatExeedLimits(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
+ const collection = await createCollectionExpectSuccess({mode: mode});
const spaceLimit = (await api.query.common.collectionProperties(collection)).toJSON().spaceLimit as number;
-
+
// Mute the general tx parsing error, too many bytes to process
{
console.error = () => {};
@@ -247,10 +287,10 @@
api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))}]),
)).to.be.rejected;
}
-
+
let properties = (await api.rpc.unique.collectionProperties(collection, ['electron'])).toJSON();
expect(properties).to.be.empty;
-
+
await expect(executeTransaction(
api,
alice,
@@ -259,16 +299,22 @@
{key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))},
]),
)).to.be.rejectedWith(/common\.NoSpaceForProperty/);
-
+
properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black hole'])).toJSON();
expect(properties).to.be.empty;
- });
+ });
+ }
+ it('Fails to set properties that exceed the limits (NFT)', async () => {
+ await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});
+ });
+ it('Fails to set properties that exceed the limits (ReFungible)', async () => {
+ await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});
});
- it('Fails to set more properties than it is allowed', async () => {
+ async function testFailsSetMorePropertiesThanAllowed(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const propertiesToBeSet = [];
for (let i = 0; i < 65; i++) {
propertiesToBeSet.push({
@@ -276,29 +322,35 @@
value: Math.random() > 0.5 ? 'high' : 'low',
});
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, propertiesToBeSet),
)).to.be.rejectedWith(/common\.PropertyLimitReached/);
-
+
const properties = (await api.query.common.collectionProperties(collection)).toJSON();
expect(properties.map).to.be.empty;
expect(properties.consumedSpace).to.equal(0);
- });
+ });
+ }
+ it('Fails to set more properties than it is allowed (NFT)', async () => {
+ await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});
+ });
+ it('Fails to set more properties than it is allowed (ReFungible)', async () => {
+ await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});
});
-
- it('Fails to set properties with invalid names', async () => {
+
+ async function testFailsSetPropertiesWithInvalidNames(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const invalidProperties = [
[{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],
[{key: 'Mr/Sandman', value: 'Bring me a gene'}],
[{key: 'déjà vu', value: 'hmm...'}],
];
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(executeTransaction(
api,
@@ -306,13 +358,13 @@
api.tx.unique.setCollectionProperties(collection, invalidProperties[i]),
), `on rejecting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setCollectionProperties(collection, [{key: '', value: 'nothing must not exist'}]),
), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);
-
+
await expect(executeTransaction(
api,
alice,
@@ -320,14 +372,14 @@
{key: 'CRISPR-Cas9', value: 'rewriting nature!'},
]),
), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;
-
+
const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat('');
-
+
const properties = (await api.rpc.unique.collectionProperties(collection, keys)).toHuman();
expect(properties).to.be.deep.equal([
{key: 'CRISPR-Cas9', value: 'rewriting nature!'},
]);
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(executeTransaction(
api,
@@ -336,7 +388,13 @@
), `on trying to delete the non-existent badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
});
+ }
+ it('Fails to set properties with invalid names (NFT)', async () => {
+ await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});
});
+ it('Fails to set properties with invalid names (ReFungible)', async () => {
+ await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});
+ });
});
// ---------- ACCESS RIGHTS
@@ -357,53 +415,65 @@
});
});
- it('Sets access rights to properties of a collection', async () => {
+ async function testSetsAccessRightsToProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true}}]),
)).to.not.be.rejected;
-
+
await addCollectionAdminExpectSuccess(alice, collection, bob.address);
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}]),
)).to.not.be.rejected;
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery', 'mindgame'])).toHuman();
expect(propertyRights).to.be.deep.equal([
{key: 'skullduggery', permission: {'mutable': true, 'collectionAdmin': false, 'tokenOwner': false}},
{key: 'mindgame', permission: {'mutable': false, 'collectionAdmin': true, 'tokenOwner': false}},
]);
- });
+ });
+ }
+ it('Sets access rights to properties of a collection (NFT)', async () => {
+ await testSetsAccessRightsToProperties({type: 'NFT'});
});
+ it('Sets access rights to properties of a collection (ReFungible)', async () => {
+ await testSetsAccessRightsToProperties({type: 'ReFungible'});
+ });
- it('Changes access rights to properties of a collection', async () => {
+ async function testChangesAccessRightsToProperty(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]),
)).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]),
)).to.not.be.rejected;
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();
expect(propertyRights).to.be.deep.equal([
{key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},
]);
});
+ }
+ it('Changes access rights to properties of a NFT collection', async () => {
+ await testChangesAccessRightsToProperty({type: 'NFT'});
+ });
+ it('Changes access rights to properties of a ReFungible collection', async () => {
+ await testChangesAccessRightsToProperty({type: 'ReFungible'});
});
});
@@ -415,25 +485,31 @@
});
});
- it('Prevents from setting access rights to properties of a collection if not an onwer/admin', async () => {
+ async function testPreventsFromSettingAccessRightsNotAdminOrOwner(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
bob,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]),
)).to.be.rejectedWith(/common\.NoPermission/);
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toJSON();
expect(propertyRights).to.be.empty;
});
+ }
+ it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {
+ await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});
});
+ it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {
+ await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});
+ });
- it('Prevents from adding too many possible properties', async () => {
+ async function testPreventFromAddingTooManyPossibleProperties(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const constitution = [];
for (let i = 0; i < 65; i++) {
constitution.push({
@@ -441,51 +517,63 @@
permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {},
});
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, constitution),
)).to.be.rejectedWith(/common\.PropertyLimitReached/);
-
+
const propertyRights = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();
expect(propertyRights).to.be.empty;
- });
+ });
+ }
+ it('Prevents from adding too many possible properties (NFT)', async () => {
+ await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});
+ });
+ it('Prevents from adding too many possible properties (ReFungible)', async () => {
+ await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});
});
- it('Prevents access rights to be modified if constant', async () => {
+ async function testPreventAccessRightsModifiedIfConstant(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]),
)).to.not.be.rejected;
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {}}]),
)).to.be.rejectedWith(/common\.NoPermission/);
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();
expect(propertyRights).to.deep.equal([
{key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},
]);
- });
+ });
+ }
+ it('Prevents access rights to be modified if constant (NFT)', async () => {
+ await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});
});
+ it('Prevents access rights to be modified if constant (ReFungible)', async () => {
+ await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});
+ });
- it('Prevents adding properties with invalid names', async () => {
+ async function testPreventsAddingPropertiesWithInvalidNames(mode: CollectionMode) {
await usingApi(async api => {
- const collection = await createCollectionExpectSuccess();
-
+ const collection = await createCollectionExpectSuccess({mode: mode});
+
const invalidProperties = [
[{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],
[{key: 'G#4', permission: {tokenOwner: true}}],
[{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}],
];
-
+
for (let i = 0; i < invalidProperties.length; i++) {
await expect(executeTransaction(
api,
@@ -493,13 +581,13 @@
api.tx.unique.setTokenPropertyPermissions(collection, invalidProperties[i]),
), `on setting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);
}
-
+
await expect(executeTransaction(
api,
alice,
api.tx.unique.setTokenPropertyPermissions(collection, [{key: '', permission: {}}]),
), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);
-
+
const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string
await expect(executeTransaction(
api,
@@ -508,14 +596,20 @@
{key: correctKey, permission: {collectionAdmin: true}},
]),
), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;
-
+
const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat('');
-
+
const propertyRights = (await api.rpc.unique.propertyPermissions(collection, keys)).toHuman();
expect(propertyRights).to.be.deep.equal([
{key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},
]);
});
+ }
+ it('Prevents adding properties with invalid names (NFT)', async () => {
+ await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});
+ });
+ it('Prevents adding properties with invalid names (ReFungible)', async () => {
+ await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});
});
});
tests/src/refungible.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 {default as usingApi, executeTransaction} from './substrate/substrate-api';18import {IKeyringPair} from '@polkadot/types/types';19import {20 createCollectionExpectSuccess,21 getBalance,22 createMultipleItemsExpectSuccess,23 isTokenExists,24 getLastTokenId,25 getAllowance,26 approve,27 transferFrom,28 createCollection,29 createRefungibleToken,30 transfer,31 burnItem,32 repartitionRFT,33 createCollectionWithPropsExpectSuccess,34 getDetailedCollectionInfo,35} from './util/helpers';3637import chai from 'chai';38import chaiAsPromised from 'chai-as-promised';39chai.use(chaiAsPromised);40const expect = chai.expect;4142let alice: IKeyringPair;43let bob: IKeyringPair;4445describe('integration test: Refungible functionality:', () => {46 before(async () => {47 await usingApi(async (api, privateKeyWrapper) => {48 alice = privateKeyWrapper('//Alice');49 bob = privateKeyWrapper('//Bob');50 });51 });5253 it('Create refungible collection and token', async () => {54 await usingApi(async api => {55 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});56 expect(createCollectionResult.success).to.be.true; 57 const collectionId = createCollectionResult.collectionId;5859 const itemCountBefore = await getLastTokenId(api, collectionId);60 const result = await createRefungibleToken(api, alice, collectionId, 100n);6162 const itemCountAfter = await getLastTokenId(api, collectionId);6364 // What to expect65 // tslint:disable-next-line:no-unused-expression66 expect(result.success).to.be.true;67 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);68 expect(collectionId).to.be.equal(result.collectionId);69 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());70 });71 });7273 it('Transfer token pieces', async () => {74 await usingApi(async api => {75 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;76 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;7778 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);79 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;8081 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);82 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);83 await expect(transfer(api, collectionId, tokenId, alice, bob, 41n)).to.eventually.be.rejected;84 });85 });8687 it('Create multiple tokens', async () => {88 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});89 const args = [90 {ReFungible: {pieces: 1}},91 {ReFungible: {pieces: 2}},92 {ReFungible: {pieces: 100}},93 ];94 await createMultipleItemsExpectSuccess(alice, collectionId, args);9596 await usingApi(async api => { 97 const tokenId = await getLastTokenId(api, collectionId);98 expect(tokenId).to.be.equal(3);99 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);100 });101 });102103 it('Burn some pieces', async () => {104 await usingApi(async api => { 105 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;106 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;107 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;108 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);109 expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true;110 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;111 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);112 });113 });114115 it('Burn all pieces', async () => {116 await usingApi(async api => { 117 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;118 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;119 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;120 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);121 expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true;122 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;123 });124 });125126 it('Burn some pieces for multiple users', async () => {127 await usingApi(async api => { 128 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;129 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;130 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;131132 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);133 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;134135 136 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);137 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);138 expect(await burnItem(api, alice, collectionId, tokenId, 40n)).to.be.true;139140 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);141 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;142 expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true;143144 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n);145 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;146 expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true;147 148 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;149 });150 });151152 it('Set allowance for token', async () => {153 await usingApi(async api => {154 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;155 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;156157 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);158159 expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;160 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);161162 expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;163 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);164 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);165 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);166 });167 });168169 it('Repartition', async () => {170 await usingApi(async api => {171 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;172 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;173174 expect(await repartitionRFT(api, collectionId, alice, tokenId, 200n)).to.be.true;175 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(200n);176177 expect(await transfer(api, collectionId, tokenId, alice, bob, 110n)).to.be.true;178 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(90n);179 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(110n);180181 await expect(repartitionRFT(api, collectionId, alice, tokenId, 80n)).to.eventually.be.rejected;182183 expect(await transfer(api, collectionId, tokenId, alice, bob, 90n)).to.be.true;184 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);185 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(200n);186187 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;188 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;189 });190 });191});192193describe('Test Refungible properties:', () => {194 before(async () => {195 await usingApi(async (api, privateKeyWrapper) => {196 alice = privateKeyWrapper('//Alice');197 bob = privateKeyWrapper('//Bob');198 });199 });200 201 it('Сreate new collection with properties', async () => {202 await usingApi(async api => {203 const properties = [{key: 'key1', value: 'val1'}];204 const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];205 const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},206 properties: properties,207 propPerm: propertyPermissions, 208 });209 const collection = (await getDetailedCollectionInfo(api, collectionId))!;210 expect(collection.properties.toHuman()).to.be.deep.equal(properties);211 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);212 });213 });214215 it('Set properties for exist collection', async () => {216 await usingApi(async api => {217 const collectionId = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},218 });219220 const properties = [221 {key: 'key1', value: 'val1'},222 {key: 'key2', value: 'val2'},223 ];224 await expect(executeTransaction(225 api, 226 alice, 227 api.tx.unique.setCollectionProperties(collectionId, properties), 228 )).to.not.be.rejected;229230 const propertyPermissions = [231 {key: 'key1', permission: {collectionAdmin: true, mutable: false, tokenOwner: true}},232 {key: 'key2', permission: {collectionAdmin: false, mutable: true, tokenOwner: false}},233 ];234 await expect(executeTransaction(235 api, 236 alice, 237 api.tx.unique.setTokenPropertyPermissions(collectionId, propertyPermissions), 238 )).to.not.be.rejected;239240 const collection = (await getDetailedCollectionInfo(api, collectionId))!;241 expect(collection.properties.toHuman()).to.be.deep.equal(properties);242 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);243 });244 });245});1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {default as usingApi, executeTransaction} from './substrate/substrate-api';18import {IKeyringPair} from '@polkadot/types/types';19import {20 createCollectionExpectSuccess,21 getBalance,22 createMultipleItemsExpectSuccess,23 isTokenExists,24 getLastTokenId,25 getAllowance,26 approve,27 transferFrom,28 createCollection,29 createRefungibleToken,30 transfer,31 burnItem,32 repartitionRFT,33 createCollectionWithPropsExpectSuccess,34 getDetailedCollectionInfo,35} from './util/helpers';3637import chai from 'chai';38import chaiAsPromised from 'chai-as-promised';39chai.use(chaiAsPromised);40const expect = chai.expect;4142let alice: IKeyringPair;43let bob: IKeyringPair;4445describe('integration test: Refungible functionality:', () => {46 before(async () => {47 await usingApi(async (api, privateKeyWrapper) => {48 alice = privateKeyWrapper('//Alice');49 bob = privateKeyWrapper('//Bob');50 });51 });5253 it('Create refungible collection and token', async () => {54 await usingApi(async api => {55 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});56 expect(createCollectionResult.success).to.be.true; 57 const collectionId = createCollectionResult.collectionId;5859 const itemCountBefore = await getLastTokenId(api, collectionId);60 const result = await createRefungibleToken(api, alice, collectionId, 100n);6162 const itemCountAfter = await getLastTokenId(api, collectionId);6364 // What to expect65 // tslint:disable-next-line:no-unused-expression66 expect(result.success).to.be.true;67 expect(itemCountAfter).to.be.equal(itemCountBefore + 1);68 expect(collectionId).to.be.equal(result.collectionId);69 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());70 });71 });7273 it('Transfer token pieces', async () => {74 await usingApi(async api => {75 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;76 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;7778 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);79 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;8081 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);82 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);83 await expect(transfer(api, collectionId, tokenId, alice, bob, 41n)).to.eventually.be.rejected;84 });85 });8687 it('Create multiple tokens', async () => {88 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});89 const args = [90 {ReFungible: {pieces: 1}},91 {ReFungible: {pieces: 2}},92 {ReFungible: {pieces: 100}},93 ];94 await createMultipleItemsExpectSuccess(alice, collectionId, args);9596 await usingApi(async api => { 97 const tokenId = await getLastTokenId(api, collectionId);98 expect(tokenId).to.be.equal(3);99 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);100 });101 });102103 it('Burn some pieces', async () => {104 await usingApi(async api => { 105 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;106 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;107 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;108 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);109 expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true;110 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;111 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n);112 });113 });114115 it('Burn all pieces', async () => {116 await usingApi(async api => { 117 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;118 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;119 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;120 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);121 expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true;122 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;123 });124 });125126 it('Burn some pieces for multiple users', async () => {127 await usingApi(async api => { 128 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;129 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;130 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;131132 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);133 expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;134135 136 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n);137 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n);138 expect(await burnItem(api, alice, collectionId, tokenId, 40n)).to.be.true;139140 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);141 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;142 expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true;143144 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n);145 expect(await isTokenExists(api, collectionId, tokenId)).to.be.true;146 expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true;147 148 expect(await isTokenExists(api, collectionId, tokenId)).to.be.false;149 });150 });151152 it('Set allowance for token', async () => {153 await usingApi(async api => {154 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;155 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;156157 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n);158159 expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true;160 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n);161162 expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true;163 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n);164 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n);165 expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n);166 });167 });168169 it('Repartition', async () => {170 await usingApi(async api => {171 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;172 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;173174 expect(await repartitionRFT(api, collectionId, alice, tokenId, 200n)).to.be.true;175 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(200n);176177 expect(await transfer(api, collectionId, tokenId, alice, bob, 110n)).to.be.true;178 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(90n);179 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(110n);180181 await expect(repartitionRFT(api, collectionId, alice, tokenId, 80n)).to.eventually.be.rejected;182183 expect(await transfer(api, collectionId, tokenId, alice, bob, 90n)).to.be.true;184 expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n);185 expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(200n);186187 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;188 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;189 });190 });191});192193describe('Test Refungible properties:', () => {194 before(async () => {195 await usingApi(async (api, privateKeyWrapper) => {196 alice = privateKeyWrapper('//Alice');197 bob = privateKeyWrapper('//Bob');198 });199 });200 201 it('Сreate new collection with properties', async () => {202 await usingApi(async api => {203 const properties = [{key: 'key1', value: 'val1'}];204 const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];205 const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},206 properties: properties,207 propPerm: propertyPermissions, 208 });209 const collection = (await getDetailedCollectionInfo(api, collectionId))!;210 expect(collection.properties.toHuman()).to.be.deep.equal(properties);211 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);212 });213 });214});tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -284,7 +284,7 @@
type: 'ReFungible';
}
-type CollectionMode = Nft | Fungible | ReFungible;
+export type CollectionMode = Nft | Fungible | ReFungible;
export type Property = {
key: any,