difftreelog
tests(nesting+properties): collection and token interfaces + make lower case not default for token addresses + more consts from old helpers included
in: master
8 files changed
tests/src/fungible.test.tsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {itSub, usingPlaygrounds, expect} from './util/playgrounds';18import {itSub, usingPlaygrounds, expect, U128_MAX} from './util/playgrounds';1920const U128_MAX = (1n << 128n) - 1n;211922describe('integration test: Fungible functionality:', () => {20describe('integration test: Fungible functionality:', () => {23 let alice: IKeyringPair;21 let alice: IKeyringPair;tests/src/nesting/graphs.test.tsdiffbeforeafterboth161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {expect, itSub, usingPlaygrounds} from '../util/playgrounds';18import {expect, itSub, usingPlaygrounds} from '../util/playgrounds';19import {ITokenNonfungible} from '../util/playgrounds/types';19import {UniqueHelper, UniqueNFTToken} from '../util/playgrounds/unique';20import {UniqueHelper} from '../util/playgrounds/unique';202121/**22/**22 * ```dot23 * ```dot25 * 8 -> 526 * 8 -> 526 * ```27 * ```27 */28 */28async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<UniqueNFTToken[]> {29async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<ITokenNonfungible[]> {29 const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});30 const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});30 const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));31 const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));3132tests/src/nesting/nest.test.tsdiffbeforeafterboth35 // Create an immediately nested token35 // Create an immediately nested token36 const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());36 const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount());37 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});37 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});38 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());38 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());39 39 40 // Create a token to be nested40 // Create a token to be nested41 const newToken = await collection.mintToken(alice);41 const newToken = await collection.mintToken(alice);424243 // Nest43 // Nest44 await newToken.nest(alice, targetToken);44 await newToken.nest(alice, targetToken);45 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});45 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});46 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());46 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());474748 // Move bundle to different user48 // Move bundle to different user49 await targetToken.transfer(alice, {Substrate: bob.address});49 await targetToken.transfer(alice, {Substrate: bob.address});50 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});50 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});51 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());51 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());52 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});52 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});53 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());53 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());545455 // Unnest55 // Unnest56 await newToken.unnest(bob, targetToken, {Substrate: bob.address});56 await newToken.unnest(bob, targetToken, {Substrate: bob.address});656566 // Create a nested token66 // Create a nested token67 const tokenC = await collection.mintToken(alice, tokenA.nestingAccount());67 const tokenC = await collection.mintToken(alice, tokenA.nestingAccount());68 expect(await tokenC.getOwner()).to.be.deep.equal(tokenA.nestingAccount());68 expect(await tokenC.getOwner()).to.be.deep.equal(tokenA.nestingAccountInLowerCase());69 69 70 // Transfer the nested token to another token70 // Transfer the nested token to another token71 await expect(tokenC.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount())).to.be.fulfilled;71 await expect(tokenC.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount())).to.be.fulfilled;72 expect(await tokenC.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});72 expect(await tokenC.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address});73 expect(await tokenC.getOwner()).to.be.deep.equal(tokenB.nestingAccount());73 expect(await tokenC.getOwner()).to.be.deep.equal(tokenB.nestingAccountInLowerCase());74 });74 });757576 itSub('Checks token children', async ({helper}) => {76 itSub('Checks token children', async ({helper}) => {150 // Create an immediately nested token150 // Create an immediately nested token151 const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());151 const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());152 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});152 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});153 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());153 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());154154155 // Create a token to be nested and nest155 // Create a token to be nested and nest156 const newToken = await collection.mintToken(bob);156 const newToken = await collection.mintToken(bob);157 await newToken.nest(bob, targetToken);157 await newToken.nest(bob, targetToken);158 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});158 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});159 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());159 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());160 });160 });161161162 itSub('Admin (NFT): Admin and Token Owner can operate together', async ({helper}) => {162 itSub('Admin (NFT): Admin and Token Owner can operate together', async ({helper}) => {167 // Create an immediately nested token by an administrator167 // Create an immediately nested token by an administrator168 const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());168 const nestedToken = await collection.mintToken(bob, targetToken.nestingAccount());169 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});169 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});170 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());170 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());171171172 // Create a token to be nested and nest172 // Create a token to be nested and nest173 const newToken = await collection.mintToken(alice, {Substrate: charlie.address});173 const newToken = await collection.mintToken(alice, {Substrate: charlie.address});174 await newToken.nest(charlie, targetToken);174 await newToken.nest(charlie, targetToken);175 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});175 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});176 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());176 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());177 });177 });178178179 itSub('Admin (NFT): allows an Admin to nest a token (Restricted nesting)', async ({helper}) => {179 itSub('Admin (NFT): allows an Admin to nest a token (Restricted nesting)', async ({helper}) => {187 // Create an immediately nested token187 // Create an immediately nested token188 const nestedToken = await collectionB.mintToken(bob, targetToken.nestingAccount());188 const nestedToken = await collectionB.mintToken(bob, targetToken.nestingAccount());189 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});189 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});190 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());190 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());191191192 // Create a token to be nested and nest192 // Create a token to be nested and nest193 const newToken = await collectionB.mintToken(bob);193 const newToken = await collectionB.mintToken(bob);194 await newToken.nest(bob, targetToken);194 await newToken.nest(bob, targetToken);195 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});195 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});196 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());196 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());197 });197 });198198199 // ---------- Non-Fungible ----------199 // ---------- Non-Fungible ----------207 // Create an immediately nested token207 // Create an immediately nested token208 const nestedToken = await collection.mintToken(charlie, targetToken.nestingAccount());208 const nestedToken = await collection.mintToken(charlie, targetToken.nestingAccount());209 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});209 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});210 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());210 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());211211212 // Create a token to be nested and nest212 // Create a token to be nested and nest213 const newToken = await collection.mintToken(charlie);213 const newToken = await collection.mintToken(charlie);214 await newToken.nest(charlie, targetToken);214 await newToken.nest(charlie, targetToken);215 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});215 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});216 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());216 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());217 });217 });218218219 itSub('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {219 itSub('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => {233 // Create an immediately nested token233 // Create an immediately nested token234 const nestedToken = await collectionB.mintToken(charlie, targetToken.nestingAccount());234 const nestedToken = await collectionB.mintToken(charlie, targetToken.nestingAccount());235 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});235 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});236 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());236 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());237237238 // Create a token to be nested and nest238 // Create a token to be nested and nest239 const newToken = await collectionB.mintToken(charlie);239 const newToken = await collectionB.mintToken(charlie);240 await newToken.nest(charlie, targetToken);240 await newToken.nest(charlie, targetToken);241 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});241 expect(await newToken.getTopmostOwner()).to.be.deep.equal({Substrate: charlie.address});242 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());242 expect(await newToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());243 });243 });244244245 // ---------- Fungible ----------245 // ---------- Fungible ----------424424425 expect(await targetToken.getChildren()).to.be.length(1);425 expect(await targetToken.getChildren()).to.be.length(1);426 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});426 expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: bob.address});427 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());427 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());428 });428 });429429430 itSub('Admin (NFT): disallows an Admin to nest a token from an unlisted collection (Restricted nesting)', async ({helper}) => {430 itSub('Admin (NFT): disallows an Admin to nest a token from an unlisted collection (Restricted nesting)', async ({helper}) => {tests/src/nesting/properties.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617/*import usingApi, {executeTransaction} from '../substrate/substrate-api';18import {19 addCollectionAdminExpectSuccess,20 CollectionMode,21 createCollectionExpectSuccess,22 setCollectionPermissionsExpectSuccess,23 createItemExpectSuccess,24 getCreateCollectionResult,25 transferExpectSuccess,26} from '../util/helpers';*/27import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';28import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from '../util/playgrounds';18import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from '../util/playgrounds';29import {UniqueCollectionBase, UniqueHelper, UniqueNFTCollection, UniqueNFTToken, UniqueRFTCollection, UniqueRFTToken} from '../util/playgrounds/unique';19import {ICollectionBase, ICollectionNFT, ITokenNonfungible, ICollectionRFT, ITokenRefungible} from '../util/playgrounds/types';20import {UniqueHelper} from '../util/playgrounds/unique';302131// ---------- COLLECTION PROPERTIES22// ---------- COLLECTION PROPERTIES322346 expect(await collection.getProperties()).to.be.empty;37 expect(await collection.getProperties()).to.be.empty;47 });38 });483949 async function testSetsPropertiesForCollection(collection: UniqueCollectionBase) {40 async function testSetsPropertiesForCollection(collection: ICollectionBase) {50 // As owner41 // As owner51 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;42 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;524370 await testSetsPropertiesForCollection(await helper.rft.mintCollection(alice));61 await testSetsPropertiesForCollection(await helper.rft.mintCollection(alice));71 });62 });726373 async function testCheckValidNames(collection: UniqueCollectionBase) {64 async function testCheckValidNames(collection: ICollectionBase) {74 // alpha symbols65 // alpha symbols75 await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;66 await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;7667104 await testCheckValidNames(await helper.rft.mintCollection(alice));95 await testCheckValidNames(await helper.rft.mintCollection(alice));105 });96 });10697107 async function testChangesProperties(collection: UniqueCollectionBase) {98 async function testChangesProperties(collection: ICollectionBase) {108 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;99 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;109100110 // Mutate the properties101 // Mutate the properties125 await testChangesProperties(await helper.rft.mintCollection(alice));116 await testChangesProperties(await helper.rft.mintCollection(alice));126 });117 });127118128 async function testDeleteProperties(collection: UniqueCollectionBase) {119 async function testDeleteProperties(collection: ICollectionBase) {129 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;120 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;130121131 await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled;122 await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled;156 });147 });157 });148 });158 149 159 async function testFailsSetPropertiesIfNotOwnerOrAdmin(collection: UniqueCollectionBase) { 150 async function testFailsSetPropertiesIfNotOwnerOrAdmin(collection: ICollectionBase) { 160 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))151 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))161 .to.be.rejectedWith(/common\.NoPermission/);152 .to.be.rejectedWith(/common\.NoPermission/);162153171 await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.rft.mintCollection(alice));162 await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.rft.mintCollection(alice));172 });163 });173 164 174 async function testFailsSetPropertiesThatExeedLimits(collection: UniqueCollectionBase) {165 async function testFailsSetPropertiesThatExeedLimits(collection: ICollectionBase) {175 const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();166 const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();176 167 177 // Mute the general tx parsing error, too many bytes to process168 // Mute the general tx parsing error, too many bytes to process200 await testFailsSetPropertiesThatExeedLimits(await helper.rft.mintCollection(alice));191 await testFailsSetPropertiesThatExeedLimits(await helper.rft.mintCollection(alice));201 });192 });202 193 203 async function testFailsSetMorePropertiesThanAllowed(collection: UniqueCollectionBase) {194 async function testFailsSetMorePropertiesThanAllowed(collection: ICollectionBase) {204 const propertiesToBeSet = [];195 const propertiesToBeSet = [];205 for (let i = 0; i < 65; i++) {196 for (let i = 0; i < 65; i++) {206 propertiesToBeSet.push({197 propertiesToBeSet.push({223 await testFailsSetMorePropertiesThanAllowed(await helper.rft.mintCollection(alice));214 await testFailsSetMorePropertiesThanAllowed(await helper.rft.mintCollection(alice));224 });215 });225 216 226 async function testFailsSetPropertiesWithInvalidNames(collection: UniqueCollectionBase) {217 async function testFailsSetPropertiesWithInvalidNames(collection: ICollectionBase) {227 const invalidProperties = [218 const invalidProperties = [228 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],219 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],229 [{key: 'Mr/Sandman', value: 'Bring me a gene'}],220 [{key: 'Mr/Sandman', value: 'Bring me a gene'}],290 expect(propertyRights).to.be.empty;281 expect(propertyRights).to.be.empty;291 });282 });292 283 293 async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) { 284 async function testSetsAccessRightsToProperties(collection: ICollectionNFT | ICollectionRFT) { 294 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}]))285 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}]))295 .to.be.fulfilled;286 .to.be.fulfilled;296287314 await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice));305 await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice));315 });306 });316 307 317 async function testChangesAccessRightsToProperty(collection: UniqueNFTCollection | UniqueRFTCollection) {308 async function testChangesAccessRightsToProperty(collection: ICollectionNFT | ICollectionRFT) {318 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]))309 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]))319 .to.be.fulfilled;310 .to.be.fulfilled;320311347 });338 });348 });339 });349340350 async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: UniqueNFTCollection | UniqueRFTCollection) {341 async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: ICollectionNFT | ICollectionRFT) {351 await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]))342 await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]))352 .to.be.rejectedWith(/common\.NoPermission/);343 .to.be.rejectedWith(/common\.NoPermission/);353344363 await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice));354 await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice));364 });355 });365356366 async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) { 357 async function testPreventFromAddingTooManyPossibleProperties(collection: ICollectionNFT | ICollectionRFT) { 367 const constitution = [];358 const constitution = [];368 for (let i = 0; i < 65; i++) {359 for (let i = 0; i < 65; i++) {369 constitution.push({360 constitution.push({387 await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice));378 await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice));388 });379 });389380390 async function testPreventAccessRightsModifiedIfConstant(collection: UniqueNFTCollection | UniqueRFTCollection) {381 async function testPreventAccessRightsModifiedIfConstant(collection: ICollectionNFT | ICollectionRFT) {391 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))382 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))392 .to.be.fulfilled;383 .to.be.fulfilled;393384408 await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice));399 await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice));409 });400 });410401411 async function testPreventsAddingPropertiesWithInvalidNames(collection: UniqueNFTCollection | UniqueRFTCollection) {402 async function testPreventsAddingPropertiesWithInvalidNames(collection: ICollectionNFT | ICollectionRFT) {412 const invalidProperties = [403 const invalidProperties = [413 [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],404 [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],414 [{key: 'G#4', permission: {tokenOwner: true}}],405 [{key: 'G#4', permission: {tokenOwner: true}}],478 ];469 ];479 });470 });480 471 481 async function testReadsYetEmptyProperties(token: UniqueNFTToken | UniqueRFTToken) {472 async function testReadsYetEmptyProperties(token: ITokenNonfungible | ITokenRefungible) {482 const properties = await token.getProperties();473 const properties = await token.getProperties();483 expect(properties).to.be.empty;474 expect(properties).to.be.empty;484475498 await testReadsYetEmptyProperties(token);489 await testReadsYetEmptyProperties(token);499 });490 });500491501 async function testAssignPropertiesAccordingToPermissions(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {492 async function testAssignPropertiesAccordingToPermissions(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {502 await token.collection.addAdmin(alice, {Substrate: bob.address});493 await token.collection.addAdmin(alice, {Substrate: bob.address});503 await token.transfer(alice, {Substrate: charlie.address}, pieces);494 await token.transfer(alice, {Substrate: charlie.address}, pieces);504495544 await testAssignPropertiesAccordingToPermissions(token, 100n);535 await testAssignPropertiesAccordingToPermissions(token, 100n);545 });536 });546537547 async function testChangesPropertiesAccordingPermission(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {538 async function testChangesPropertiesAccordingPermission(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {548 await token.collection.addAdmin(alice, {Substrate: bob.address});539 await token.collection.addAdmin(alice, {Substrate: bob.address});549 await token.transfer(alice, {Substrate: charlie.address}, pieces);540 await token.transfer(alice, {Substrate: charlie.address}, pieces);550541597 await testChangesPropertiesAccordingPermission(token, 100n);588 await testChangesPropertiesAccordingPermission(token, 100n);598 });589 });599590600 async function testDeletePropertiesAccordingPermission(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {591 async function testDeletePropertiesAccordingPermission(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {601 await token.collection.addAdmin(alice, {Substrate: bob.address});592 await token.collection.addAdmin(alice, {Substrate: bob.address});602 await token.transfer(alice, {Substrate: charlie.address}, pieces);593 await token.transfer(alice, {Substrate: charlie.address}, pieces);603594808 return (await (mode == 'NFT' ? api.query.nonfungible : api.query.refungible).tokenProperties(collectionId, tokenId)).toJSON().consumedSpace;799 return (await (mode == 'NFT' ? api.query.nonfungible : api.query.refungible).tokenProperties(collectionId, tokenId)).toJSON().consumedSpace;809 }800 }810801811 async function prepare(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint): Promise<number> {802 async function prepare(token: ITokenNonfungible | ITokenRefungible, pieces: bigint): Promise<number> {812 await token.collection.addAdmin(alice, {Substrate: bob.address});803 await token.collection.addAdmin(alice, {Substrate: bob.address});813 await token.transfer(alice, {Substrate: charlie.address}, pieces);804 await token.transfer(alice, {Substrate: charlie.address}, pieces);814805832 return originalSpace;823 return originalSpace;833 }824 }834825835 async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {826 async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {836 const originalSpace = await prepare(token, pieces);827 const originalSpace = await prepare(token, pieces);837828838 let i = 0;829 let i = 0;867 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token, 100n);858 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token, 100n);868 });859 });869860870 async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {861 async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {871 const originalSpace = await prepare(token, pieces);862 const originalSpace = await prepare(token, pieces);872863873 let i = 0;864 let i = 0;902 await testForbidsChangingDeletingPropertiesIfPropertyImmutable(token, 100n);893 await testForbidsChangingDeletingPropertiesIfPropertyImmutable(token, 100n);903 });894 });904895905 async function testForbidsAddingPropertiesIfPropertyNotDeclared(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {896 async function testForbidsAddingPropertiesIfPropertyNotDeclared(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {906 const originalSpace = await prepare(token, pieces);897 const originalSpace = await prepare(token, pieces);907898908 await expect(899 await expect(938 await testForbidsAddingPropertiesIfPropertyNotDeclared(token, 100n);929 await testForbidsAddingPropertiesIfPropertyNotDeclared(token, 100n);939 });930 });940931941 async function testForbidsAddingTooManyProperties(token: UniqueNFTToken | UniqueRFTToken, pieces: bigint) {932 async function testForbidsAddingTooManyProperties(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {942 const originalSpace = await prepare(token, pieces);933 const originalSpace = await prepare(token, pieces);943934944 await expect(935 await expect(993 });984 });994 });985 });995986996 async function prepare(helper: UniqueHelper): Promise<UniqueRFTToken> {987 async function prepare(helper: UniqueHelper): Promise<ITokenRefungible> {997 const collection = await helper.rft.mintCollection(alice);988 const collection = await helper.rft.mintCollection(alice);998 const token = await collection.mintToken(alice, 100n);989 const token = await collection.mintToken(alice, 100n);999 990 tests/src/nesting/unnest.test.tsdiffbeforeafterboth105105106 // Try to unnest106 // Try to unnest107 await expect(nestedToken.unnest(bob, targetToken, {Substrate: alice.address})).to.be.rejectedWith(/common\.ApprovedValueTooLow/);107 await expect(nestedToken.unnest(bob, targetToken, {Substrate: alice.address})).to.be.rejectedWith(/common\.ApprovedValueTooLow/);108 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());108 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());109109110 // Try to burn110 // Try to burn111 await expect(nestedToken.burnFrom(bob, targetToken.nestingAccount())).to.be.rejectedWith(/common\.ApprovedValueTooLow/);111 await expect(nestedToken.burnFrom(bob, targetToken.nestingAccount())).to.be.rejectedWith(/common\.ApprovedValueTooLow/);112 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount());112 expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccountInLowerCase());113 });113 });114114115 // todo another test for creating excessive depth matryoshka with Ethereum?115 // todo another test for creating excessive depth matryoshka with Ethereum?tests/src/util/playgrounds/index.tsdiffbeforeafterboth13chai.use(chaiAsPromised);12chai.use(chaiAsPromised);14export const expect = chai.expect;13export const expect = chai.expect;1415export const U128_MAX = (1n << 128n) - 1n;1617const MICROUNIQUE = 1_000_000_000_000n;18const MILLIUNIQUE = 1_000n * MICROUNIQUE;19const CENTIUNIQUE = 10n * MILLIUNIQUE;20export const UNIQUE = 100n * CENTIUNIQUE;152116export const usingPlaygrounds = async (code: (helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>, url: string = config.substrateUrl) => {22export const usingPlaygrounds = async (code: (helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>, url: string = config.substrateUrl) => {17 const silentConsole = new SilentConsole();23 const silentConsole = new SilentConsole();tests/src/util/playgrounds/types.tsdiffbeforeafterboth2// SPDX-License-Identifier: Apache-2.02// SPDX-License-Identifier: Apache-2.0334import {IKeyringPair} from '@polkadot/types/types';4import {IKeyringPair} from '@polkadot/types/types';5import {UniqueHelper} from './unique';566export interface IEvent {7export interface IEvent {7 section: string;8 section: string;106 }107 }107}108}108109109export interface IToken {110export interface ITokenAddress {110 collectionId: number;111 collectionId: number;111 tokenId: number;112 tokenId: number;112}113}168export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';169export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';169export type TSigner = IKeyringPair; // | 'string'170export type TSigner = IKeyringPair; // | 'string'171172export interface ICollectionBase {173 helper: UniqueHelper;174 collectionId: number;175 getData: () => Promise<{176 id: number;177 name: string;178 description: string;179 tokensCount: number;180 admins: ICrossAccountId[];181 normalizedOwner: TSubstrateAccount;182 raw: any183 } | null>;184 getLastTokenId: () => Promise<number>;185 isTokenExists: (tokenId: number) => Promise<boolean>;186 getAdmins: () => Promise<ICrossAccountId[]>;187 getAllowList: () => Promise<ICrossAccountId[]>;188 getEffectiveLimits: () => Promise<ICollectionLimits>;189 getProperties: (propertyKeys?: string[]) => Promise<IProperty[]>;190 getTokenNextSponsored: (tokenId: number, addressObj: ICrossAccountId) => Promise<number | null>;191 setSponsor: (signer: TSigner, sponsorAddress: TSubstrateAccount) => Promise<boolean>;192 confirmSponsorship: (signer: TSigner) => Promise<boolean>;193 removeSponsor: (signer: TSigner) => Promise<boolean>;194 setLimits: (signer: TSigner, limits: ICollectionLimits) => Promise<boolean>;195 changeOwner: (signer: TSigner, ownerAddress: TSubstrateAccount) => Promise<boolean>;196 addAdmin: (signer: TSigner, adminAddressObj: ICrossAccountId) => Promise<boolean>;197 addToAllowList: (signer: TSigner, addressObj: ICrossAccountId) => Promise<boolean>;198 removeFromAllowList: (signer: TSigner, addressObj: ICrossAccountId) => Promise<boolean>;199 removeAdmin: (signer: TSigner, adminAddressObj: ICrossAccountId) => Promise<boolean>;200 setProperties: (signer: TSigner, properties: IProperty[]) => Promise<boolean>;201 deleteProperties: (signer: TSigner, propertyKeys: string[]) => Promise<boolean>;202 setPermissions: (signer: TSigner, permissions: ICollectionPermissions) => Promise<boolean>;203 enableNesting: (signer: TSigner, permissions: INestingPermissions) => Promise<boolean>;204 disableNesting: (signer: TSigner) => Promise<boolean>;205 burn: (signer: TSigner) => Promise<boolean>;206}207208export interface ICollectionNFT extends ICollectionBase {209 getTokenObject: (tokenId: number) => ITokenNonfungible; // todo:playgrounds210 getTokensByAddress: (addressObj: ICrossAccountId) => Promise<number[]>;211 getToken: (tokenId: number, blockHashAt?: string) => Promise<{212 properties: IProperty[];213 owner: ICrossAccountId;214 normalizedOwner: ICrossAccountId;215 }| null>;216 getTokenOwner: (tokenId: number, blockHashAt?: string) => Promise<ICrossAccountId>;217 getTokenTopmostOwner: (tokenId: number, blockHashAt?: string) => Promise<ICrossAccountId | null>;218 getTokenChildren: (tokenId: number, blockHashAt?: string) => Promise<ITokenAddress[]>; // todo:playgrounds219 getPropertyPermissions: (propertyKeys?: string[]) => Promise<ITokenPropertyPermission[]>;220 getTokenProperties: (tokenId: number, propertyKeys?: string[]) => Promise<IProperty[]>;221 transferToken: (signer: TSigner, tokenId: number, addressObj: ICrossAccountId) => Promise<boolean>;222 transferTokenFrom: (signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) => Promise<boolean>;223 approveToken: (signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId) => Promise<boolean>;224 isTokenApproved: (tokenId: number, toAddressObj: ICrossAccountId) => Promise<boolean>;225 mintToken: (signer: TSigner, owner: ICrossAccountId, properties?: IProperty[]) => Promise<ITokenNonfungible>;// todo:playgrounds226 mintMultipleTokens: (signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]) => Promise<ITokenNonfungible[]>;// todo:playgrounds227 burnToken: (signer: TSigner, tokenId: number) => Promise<{228 success: boolean,229 token: number | null230 }>;231 burnTokenFrom: (signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId) => Promise<boolean>;232 setTokenProperties: (signer: TSigner, tokenId: number, properties: IProperty[]) => Promise<boolean>;233 deleteTokenProperties: (signer: TSigner, tokenId: number, propertyKeys: string[]) => Promise<boolean>;234 setTokenPropertyPermissions: (signer: TSigner, permissions: ITokenPropertyPermission[]) => Promise<boolean>;235 nestToken: (signer: TSigner, tokenId: number, toTokenObj: ITokenAddress) => Promise<boolean>;236 unnestToken: (signer: TSigner, tokenId: number, fromTokenObj: ITokenAddress, toAddressObj: ICrossAccountId) => Promise<boolean>;237}238239export interface ICollectionRFT extends ICollectionBase {240 getTokenObject: (tokenId: number) => ITokenRefungible;241 getToken: (tokenId: number, blockHashAt?: string) => Promise<{242 properties: IProperty[];243 owner: ICrossAccountId;244 normalizedOwner: ICrossAccountId;245 }| null>;246 getTokensByAddress: (addressObj: ICrossAccountId) => Promise<number[]>;247 getTop10TokenOwners: (tokenId: number) => Promise<ICrossAccountId[]>;248 getTokenBalance: (tokenId: number, addressObj: ICrossAccountId) => Promise<bigint>;249 getTokenTotalPieces: (tokenId: number) => Promise<bigint>;250 getTokenApprovedPieces: (tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) => Promise<bigint>;251 getPropertyPermissions: (propertyKeys?: string[] | null) => Promise<ITokenPropertyPermission[]>;252 getTokenProperties: (tokenId: number, propertyKeys?: string[]) => Promise<IProperty[]>;253 transferToken: (signer: TSigner, tokenId: number, addressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;254 transferTokenFrom: (signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;255 approveToken: (signer: TSigner, tokenId: number, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;256 repartitionToken: (signer: TSigner, tokenId: number, amount: bigint) => Promise<boolean>;257 mintToken: (signer: TSigner, pieces: bigint, owner: ICrossAccountId, properties?: IProperty[]) => Promise<ITokenRefungible>;258 mintMultipleTokens: (signer: TSigner, tokens: {pieces: bigint, owner: ICrossAccountId, properties?: IProperty[]}[]) => Promise<ITokenRefungible[]>; // todo:playgrounds259 burnToken: (signer: TSigner, tokenId: number, amount: bigint) => Promise<{260 success: boolean,261 token: number | null262 }>;263 burnTokenFrom: (signer: TSigner, tokenId: number, fromAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;264 setTokenProperties: (signer: TSigner, tokenId: number, properties: IProperty[]) => Promise<boolean>;265 deleteTokenProperties: (signer: TSigner, tokenId: number, propertyKeys: string[]) => Promise<boolean>;266 setTokenPropertyPermissions: (signer: TSigner, permissions: ITokenPropertyPermission[]) => Promise<boolean>;267}268269export interface ICollectionFT extends ICollectionBase {270 getBalance: (addressObj: ICrossAccountId) => Promise<bigint>;271 getTotalPieces: () => Promise<bigint>;272 getApprovedTokens: (fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) => Promise<bigint>;273 getTop10Owners: () => Promise<ICrossAccountId[]>;274 mint: (signer: TSigner, amount: bigint, owner: ICrossAccountId) => Promise<boolean>;275 mintWithOneOwner: (signer: TSigner, tokens: {value: bigint}[], owner: ICrossAccountId) => Promise<boolean>;276 transfer: (signer: TSigner, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;277 transferFrom: (signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;278 burnTokens: (signer: TSigner, amount: bigint) => Promise<boolean>;279 burnTokensFrom: (signer: TSigner, fromAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;280 approveTokens: (signer: TSigner, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;281}282283export interface ITokenBase extends ITokenAddress {284 collection: ICollectionNFT | ICollectionRFT;285 getNextSponsored: (addressObj: ICrossAccountId) => Promise<number|null>;286 getProperties: (propertyKeys?: string[]) => Promise<IProperty[]>;287 setProperties: (signer: TSigner, properties: IProperty[]) => Promise<boolean>;288 deleteProperties: (signer: TSigner, propertyKeys: string[]) => Promise<boolean>;289 nestingAccount: () => ICrossAccountId;290 nestingAccountInLowerCase: () => ICrossAccountId;291}292293export interface ITokenNonfungible extends ITokenBase {294 collection: ICollectionNFT;295 getData: (blockHashAt?: string) => Promise<{296 properties: IProperty[];297 owner: ICrossAccountId;298 normalizedOwner: ICrossAccountId;299 }| null>;300 getOwner: (blockHashAt?: string) => Promise<ICrossAccountId>;301 getTopmostOwner: (blockHashAt?: string) => Promise<ICrossAccountId | null>;302 getChildren: (blockHashAt?: string) => Promise<ITokenAddress[]>; // todo:playgrounds303 nest: (signer: TSigner, toTokenObj: ITokenAddress) => Promise<boolean>;304 unnest: (signer: TSigner, fromTokenObj: ITokenAddress, toAddressObj: ICrossAccountId) => Promise<boolean>;305 transfer: (signer: TSigner, addressObj: ICrossAccountId) => Promise<boolean>;306 transferFrom: (signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) => Promise<boolean>;307 approve: (signer: TSigner, toAddressObj: ICrossAccountId) => Promise<boolean>;308 isApproved: (toAddressObj: ICrossAccountId) => Promise<boolean>;309 burn: (signer: TSigner) => Promise<{310 success: boolean,311 token: number | null312 }>;313 burnFrom: (signer: TSigner, fromAddressObj: ICrossAccountId) => Promise<boolean>;314}315316export interface ITokenRefungible extends ITokenBase {317 collection: ICollectionRFT;318 getData: (blockHashAt?: string) => Promise<{319 properties: IProperty[];320 owner: ICrossAccountId;321 normalizedOwner: ICrossAccountId;322 }| null>;323 getTop10Owners: () => Promise<ICrossAccountId[]>;324 getBalance: (addressObj: ICrossAccountId) => Promise<bigint>;325 getTotalPieces: () => Promise<bigint>;326 getApprovedPieces: (fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) => Promise<bigint>;327 transfer: (signer: TSigner, addressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;328 transferFrom: (signer: TSigner, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;329 approve: (signer: TSigner, toAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;330 repartition: (signer: TSigner, amount: bigint) => Promise<boolean>;331 burn: (signer: TSigner, amount: bigint) => Promise<{332 success: boolean,333 token: number | null334 }>;335 burnFrom: (signer: TSigner, fromAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;336}170337tests/src/util/playgrounds/unique.tsdiffbeforeafterboth9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';11import {IKeyringPair} from '@polkadot/types/types';11import {IKeyringPair} from '@polkadot/types/types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISubstrateBalance, ITokenAddress, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks, ICollectionBase, ICollectionNFT, ICollectionRFT, ITokenBase, ITokenNonfungible, ITokenRefungible, ICollectionFT} from './types';131314export const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {14export const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {15 const address = {} as ICrossAccountId;15 const address = {} as ICrossAccountId;55 RPC: 'rpc',55 RPC: 'rpc',56 };56 };5758 static getTokenAccount(token: ITokenAddress): ICrossAccountId {59 return {Ethereum: this.getTokenAddress(token)};60 }576158 static getTokenAccount(token: IToken) {62 static getTokenAccountInLowerCase(token: ITokenAddress): ICrossAccountId {59 return {Ethereum: this.getTokenAddress(token).toLowerCase()};63 return {Ethereum: this.getTokenAddress(token).toLowerCase()};60 }64 }616562 static getTokenAddress(token: IToken) {66 static getTokenAddress(token: ITokenAddress): string {63 return nesting.tokenIdToAddress(token.collectionId, token.tokenId);67 return nesting.tokenIdToAddress(token.collectionId, token.tokenId);64 }68 }65691348 * @example getTokenChildren(10, 5);1352 * @example getTokenChildren(10, 5);1349 * @returns tokens whose depth of nesting is <= 51353 * @returns tokens whose depth of nesting is <= 51350 */1354 */1351 async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {1355 async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<ITokenAddress[]> {1352 let children;1356 let children;1353 if(typeof blockHashAt === 'undefined') {1357 if(typeof blockHashAt === 'undefined') {1354 children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);1358 children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);1369 * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});1373 * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});1370 * @returns ```true``` if extrinsic success, otherwise ```false```1374 * @returns ```true``` if extrinsic success, otherwise ```false```1371 */1375 */1372 async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken): Promise<boolean> {1376 async nestToken(signer: TSigner, tokenObj: ITokenAddress, rootTokenObj: ITokenAddress): Promise<boolean> {1373 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1377 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1374 const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);1378 const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);1375 if(!result) {1379 if(!result) {1387 * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});1391 * @example unnestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4}, {Substrate: "5DyN4Y92vZCjv38fg..."});1388 * @returns ```true``` if extrinsic success, otherwise ```false```1392 * @returns ```true``` if extrinsic success, otherwise ```false```1389 */1393 */1390 async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {1394 async unnestToken(signer: TSigner, tokenObj: ITokenAddress, rootTokenObj: ITokenAddress, toAddressObj: ICrossAccountId): Promise<boolean> {1391 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1395 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1392 const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);1396 const result = await this.transferTokenFrom(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress, toAddressObj);1393 if(!result) {1397 if(!result) {1456 true,1460 true,1457 );1461 );1458 const collection = this.getCollectionObject(collectionId);1462 const collection = this.getCollectionObject(collectionId);1459 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1463 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1460 }1464 }146114651462 /**1466 /**1489 true,1493 true,1490 );1494 );1491 const collection = this.getCollectionObject(collectionId);1495 const collection = this.getCollectionObject(collectionId);1492 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1496 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1493 }1497 }149414981495 /**1499 /**1630 true, // `Unable to mint RFT tokens for ${label}`,1634 true, // `Unable to mint RFT tokens for ${label}`,1631 );1635 );1632 const collection = this.getCollectionObject(collectionId);1636 const collection = this.getCollectionObject(collectionId);1633 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1637 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1634 }1638 }163516391636 /**1640 /**1654 true,1658 true,1655 );1659 );1656 const collection = this.getCollectionObject(collectionId);1660 const collection = this.getCollectionObject(collectionId);1657 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));1661 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1658 }1662 }165916631660 /**1664 /**2219}2223}22202224222122252222export class UniqueCollectionBase {2226class UniqueCollectionBase implements ICollectionBase {2223 helper: UniqueHelper;2227 helper: UniqueHelper;2224 collectionId: number;2228 collectionId: number;222522292256 return await this.helper.collection.getProperties(this.collectionId, propertyKeys);2260 return await this.helper.collection.getProperties(this.collectionId, propertyKeys);2257 }2261 }22622263 async getTokenNextSponsored(tokenId: number, addressObj: ICrossAccountId) {2264 return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);2265 }225822662259 async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {2267 async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {2260 return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);2268 return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);2300 return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys);2308 return await this.helper.collection.deleteProperties(signer, this.collectionId, propertyKeys);2301 }2309 }23022303 async getTokenNextSponsored(tokenId: number, addressObj: ICrossAccountId) {2304 return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);2305 }230623102307 async setPermissions(signer: TSigner, permissions: ICollectionPermissions) {2311 async setPermissions(signer: TSigner, permissions: ICollectionPermissions) {2308 return await this.helper.collection.setPermissions(signer, this.collectionId, permissions);2312 return await this.helper.collection.setPermissions(signer, this.collectionId, permissions);2322}2326}23232327232423282325export class UniqueNFTCollection extends UniqueCollectionBase {2329class UniqueNFTCollection extends UniqueCollectionBase implements ICollectionNFT {2326 getTokenObject(tokenId: number) {2330 getTokenObject(tokenId: number) {2327 return new UniqueNFTToken(tokenId, this);2331 return new UniqueNFTToken(tokenId, this);2328 }2332 }2399 return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2403 return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2400 }2404 }240124052402 async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {2406 async nestToken(signer: TSigner, tokenId: number, toTokenObj: ITokenAddress) {2403 return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);2407 return await this.helper.nft.nestToken(signer, {collectionId: this.collectionId, tokenId}, toTokenObj);2404 }2408 }240524092406 async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {2410 async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: ITokenAddress, toAddressObj: ICrossAccountId) {2407 return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);2411 return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);2408 }2412 }2409}2413}24102414241124152412export class UniqueRFTCollection extends UniqueCollectionBase {2416class UniqueRFTCollection extends UniqueCollectionBase implements ICollectionRFT {2413 getTokenObject(tokenId: number) {2417 getTokenObject(tokenId: number) {2414 return new UniqueRFTToken(tokenId, this);2418 return new UniqueRFTToken(tokenId, this);2415 }2419 }2434 return await this.helper.rft.getTokenTotalPieces(this.collectionId, tokenId);2438 return await this.helper.rft.getTokenTotalPieces(this.collectionId, tokenId);2435 }2439 }24402441 async getTokenApprovedPieces(tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {2442 return await this.helper.rft.getTokenApprovedPieces(this.collectionId, tokenId, toAddressObj, fromAddressObj);2443 }243624442437 async getPropertyPermissions(propertyKeys: string[] | null = null) {2445 async getPropertyPermissions(propertyKeys: string[] | null = null) {2438 return await this.helper.rft.getPropertyPermissions(this.collectionId, propertyKeys);2446 return await this.helper.rft.getPropertyPermissions(this.collectionId, propertyKeys);2454 return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, amount);2462 return await this.helper.rft.approveToken(signer, this.collectionId, tokenId, toAddressObj, amount);2455 }2463 }24562457 async getTokenApprovedPieces(tokenId: number, fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {2458 return await this.helper.rft.getTokenApprovedPieces(this.collectionId, tokenId, toAddressObj, fromAddressObj);2459 }246024642461 async repartitionToken(signer: TSigner, tokenId: number, amount: bigint) {2465 async repartitionToken(signer: TSigner, tokenId: number, amount: bigint) {2462 return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount);2466 return await this.helper.rft.repartitionToken(signer, this.collectionId, tokenId, amount);2492}2496}24932497249424982495export class UniqueFTCollection extends UniqueCollectionBase {2499class UniqueFTCollection extends UniqueCollectionBase implements ICollectionFT {2500 async getBalance(addressObj: ICrossAccountId) {2501 return await this.helper.ft.getBalance(this.collectionId, addressObj);2502 }25032504 async getTotalPieces() {2505 return await this.helper.ft.getTotalPieces(this.collectionId);2506 }25072508 async getApprovedTokens(fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {2509 return await this.helper.ft.getApprovedTokens(this.collectionId, fromAddressObj, toAddressObj);2510 }25112512 async getTop10Owners() {2513 return await this.helper.ft.getTop10Owners(this.collectionId);2514 }25152496 async mint(signer: TSigner, amount=1n, owner: ICrossAccountId = {Substrate: signer.address}) {2516 async mint(signer: TSigner, amount=1n, owner: ICrossAccountId = {Substrate: signer.address}) {2497 return await this.helper.ft.mintTokens(signer, this.collectionId, amount, owner);2517 return await this.helper.ft.mintTokens(signer, this.collectionId, amount, owner);2501 return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, tokens, owner);2521 return await this.helper.ft.mintMultipleTokensWithOneOwner(signer, this.collectionId, tokens, owner);2502 }2522 }25032504 async getBalance(addressObj: ICrossAccountId) {2505 return await this.helper.ft.getBalance(this.collectionId, addressObj);2506 }25072508 async getTop10Owners() {2509 return await this.helper.ft.getTop10Owners(this.collectionId);2510 }251125232512 async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {2524 async transfer(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {2513 return await this.helper.ft.transfer(signer, this.collectionId, toAddressObj, amount);2525 return await this.helper.ft.transfer(signer, this.collectionId, toAddressObj, amount);2525 return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount);2537 return await this.helper.ft.burnTokensFrom(signer, this.collectionId, fromAddressObj, amount);2526 }2538 }25272528 async getTotalPieces() {2529 return await this.helper.ft.getTotalPieces(this.collectionId);2530 }253125392532 async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {2540 async approveTokens(signer: TSigner, toAddressObj: ICrossAccountId, amount=1n) {2533 return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);2541 return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);2534 }2542 }25352536 async getApprovedTokens(fromAddressObj: ICrossAccountId, toAddressObj: ICrossAccountId) {2537 return await this.helper.ft.getApprovedTokens(this.collectionId, fromAddressObj, toAddressObj);2538 }2539}2543}25402544254125452542export class UniqueTokenBase implements IToken {2546class UniqueTokenBase implements ITokenBase {2543 collection: UniqueNFTCollection | UniqueRFTCollection;2547 collection: UniqueNFTCollection | UniqueRFTCollection;2544 collectionId: number;2548 collectionId: number;2545 tokenId: number;2549 tokenId: number;2570 return this.collection.helper.util.getTokenAccount(this);2574 return this.collection.helper.util.getTokenAccount(this);2571 }2575 }25762577 nestingAccountInLowerCase() {2578 return this.collection.helper.util.getTokenAccountInLowerCase(this);2579 }2572}2580}25732581257425822575export class UniqueNFTToken extends UniqueTokenBase {2583class UniqueNFTToken extends UniqueTokenBase implements ITokenNonfungible {2576 collection: UniqueNFTCollection;2584 collection: UniqueNFTCollection;257725852578 constructor(tokenId: number, collection: UniqueNFTCollection) {2586 constructor(tokenId: number, collection: UniqueNFTCollection) {2596 return await this.collection.getTokenChildren(this.tokenId, blockHashAt);2604 return await this.collection.getTokenChildren(this.tokenId, blockHashAt);2597 }2605 }259826062599 async nest(signer: TSigner, toTokenObj: IToken) {2607 async nest(signer: TSigner, toTokenObj: ITokenAddress) {2600 return await this.collection.nestToken(signer, this.tokenId, toTokenObj);2608 return await this.collection.nestToken(signer, this.tokenId, toTokenObj);2601 }2609 }260226102603 async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {2611 async unnest(signer: TSigner, fromTokenObj: ITokenAddress, toAddressObj: ICrossAccountId) {2604 return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);2612 return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);2605 }2613 }260626142629 }2637 }2630}2638}263126392632export class UniqueRFTToken extends UniqueTokenBase {2640class UniqueRFTToken extends UniqueTokenBase implements ITokenRefungible {2633 collection: UniqueRFTCollection;2641 collection: UniqueRFTCollection;263426422635 constructor(tokenId: number, collection: UniqueRFTCollection) {2643 constructor(tokenId: number, collection: UniqueRFTCollection) {2653 return await this.collection.getTokenTotalPieces(this.tokenId);2661 return await this.collection.getTokenTotalPieces(this.tokenId);2654 }2662 }26632664 async getApprovedPieces(fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) {2665 return await this.collection.getTokenApprovedPieces(this.tokenId, fromAddressObj, toAccountObj);2666 }265526672656 async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=1n) {2668 async transfer(signer: TSigner, addressObj: ICrossAccountId, amount=1n) {2657 return await this.collection.transferToken(signer, this.tokenId, addressObj, amount);2669 return await this.collection.transferToken(signer, this.tokenId, addressObj, amount);2665 return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount);2677 return await this.collection.approveToken(signer, this.tokenId, toAddressObj, amount);2666 }2678 }26672668 async getApprovedPieces(fromAddressObj: ICrossAccountId, toAccountObj: ICrossAccountId) {2669 return await this.collection.getTokenApprovedPieces(this.tokenId, fromAddressObj, toAccountObj);2670 }267126792672 async repartition(signer: TSigner, amount: bigint) {2680 async repartition(signer: TSigner, amount: bigint) {2673 return await this.collection.repartitionToken(signer, this.tokenId, amount);2681 return await this.collection.repartitionToken(signer, this.tokenId, amount);