git.delta.rocks / unique-network / refs/commits / 77e366b9e580

difftreelog

tests(nesting): revert majority of last commit + refactor token and collection naming convention

Fahrrader2022-09-27parent: #415e2e0.patch.diff
in: master

6 files changed

modifiedtests/src/fungible.test.tsdiffbeforeafterboth
15// 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/>.
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {itSub, usingPlaygrounds, expect, U128_MAX} from './util/playgrounds';18import {itSub, usingPlaygrounds, expect} from './util/playgrounds';
19
20const U128_MAX = (1n << 128n) - 1n;
1921
20describe('integration test: Fungible functionality:', () => {22describe('integration test: Fungible functionality:', () => {
21 let alice: IKeyringPair;23 let alice: IKeyringPair;
modifiedtests/src/nesting/graphs.test.tsdiffbeforeafterboth
1616
17import {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';
20import {UniqueHelper} from '../util/playgrounds/unique';19import {UniqueHelper, UniqueNFToken} from '../util/playgrounds/unique';
2120
22/**21/**
23 * ```dot22 * ```dot
26 * 8 -> 525 * 8 -> 5
27 * ```26 * ```
28 */27 */
29async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<ITokenNonfungible[]> {28async function buildComplexObjectGraph(helper: UniqueHelper, sender: IKeyringPair): Promise<UniqueNFToken[]> {
30 const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});29 const collection = await helper.nft.mintCollection(sender, {permissions: {nesting: {tokenOwner: true}}});
31 const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));30 const tokens = await collection.mintMultipleTokens(sender, Array(8).fill({owner: {Substrate: sender.address}}));
3231
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
1616
17import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';
18import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from '../util/playgrounds';18import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds, expect} from '../util/playgrounds';
19import {ICollectionBase, ICollectionNFT, ITokenNonfungible, ICollectionRFT, ITokenRefungible} from '../util/playgrounds/types';19import {UniqueHelper, UniqueBaseCollection, UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection, UniqueRFToken} from '../util/playgrounds/unique';
20import {UniqueHelper} from '../util/playgrounds/unique';
2120
22// ---------- COLLECTION PROPERTIES21// ---------- COLLECTION PROPERTIES
2322
37 expect(await collection.getProperties()).to.be.empty;36 expect(await collection.getProperties()).to.be.empty;
38 });37 });
3938
40 async function testSetsPropertiesForCollection(collection: ICollectionBase) {39 async function testSetsPropertiesForCollection(collection: UniqueBaseCollection) {
41 // As owner40 // As owner
42 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;41 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled;
4342
61 await testSetsPropertiesForCollection(await helper.rft.mintCollection(alice));60 await testSetsPropertiesForCollection(await helper.rft.mintCollection(alice));
62 });61 });
6362
64 async function testCheckValidNames(collection: ICollectionBase) {63 async function testCheckValidNames(collection: UniqueBaseCollection) {
65 // alpha symbols64 // alpha symbols
66 await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;65 await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled;
6766
95 await testCheckValidNames(await helper.rft.mintCollection(alice));94 await testCheckValidNames(await helper.rft.mintCollection(alice));
96 });95 });
9796
98 async function testChangesProperties(collection: ICollectionBase) {97 async function testChangesProperties(collection: UniqueBaseCollection) {
99 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;98 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled;
10099
101 // Mutate the properties100 // Mutate the properties
116 await testChangesProperties(await helper.rft.mintCollection(alice));115 await testChangesProperties(await helper.rft.mintCollection(alice));
117 });116 });
118117
119 async function testDeleteProperties(collection: ICollectionBase) {118 async function testDeleteProperties(collection: UniqueBaseCollection) {
120 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;119 await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled;
121120
122 await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled;121 await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled;
147 });146 });
148 });147 });
149 148
150 async function testFailsSetPropertiesIfNotOwnerOrAdmin(collection: ICollectionBase) { 149 async function testFailsSetPropertiesIfNotOwnerOrAdmin(collection: UniqueBaseCollection) {
151 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))150 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))
152 .to.be.rejectedWith(/common\.NoPermission/);151 .to.be.rejectedWith(/common\.NoPermission/);
153152
162 await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.rft.mintCollection(alice));161 await testFailsSetPropertiesIfNotOwnerOrAdmin(await helper.rft.mintCollection(alice));
163 });162 });
164 163
165 async function testFailsSetPropertiesThatExeedLimits(collection: ICollectionBase) {164 async function testFailsSetPropertiesThatExeedLimits(collection: UniqueBaseCollection) {
166 const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();165 const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber();
167 166
168 // Mute the general tx parsing error, too many bytes to process167 // Mute the general tx parsing error, too many bytes to process
191 await testFailsSetPropertiesThatExeedLimits(await helper.rft.mintCollection(alice));190 await testFailsSetPropertiesThatExeedLimits(await helper.rft.mintCollection(alice));
192 });191 });
193 192
194 async function testFailsSetMorePropertiesThanAllowed(collection: ICollectionBase) {193 async function testFailsSetMorePropertiesThanAllowed(collection: UniqueBaseCollection) {
195 const propertiesToBeSet = [];194 const propertiesToBeSet = [];
196 for (let i = 0; i < 65; i++) {195 for (let i = 0; i < 65; i++) {
197 propertiesToBeSet.push({196 propertiesToBeSet.push({
214 await testFailsSetMorePropertiesThanAllowed(await helper.rft.mintCollection(alice));213 await testFailsSetMorePropertiesThanAllowed(await helper.rft.mintCollection(alice));
215 });214 });
216 215
217 async function testFailsSetPropertiesWithInvalidNames(collection: ICollectionBase) {216 async function testFailsSetPropertiesWithInvalidNames(collection: UniqueBaseCollection) {
218 const invalidProperties = [217 const invalidProperties = [
219 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],218 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],
220 [{key: 'Mr/Sandman', value: 'Bring me a gene'}],219 [{key: 'Mr/Sandman', value: 'Bring me a gene'}],
281 expect(propertyRights).to.be.empty;280 expect(propertyRights).to.be.empty;
282 });281 });
283 282
284 async function testSetsAccessRightsToProperties(collection: ICollectionNFT | ICollectionRFT) { 283 async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {
285 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}]))284 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}]))
286 .to.be.fulfilled;285 .to.be.fulfilled;
287286
305 await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice));304 await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice));
306 });305 });
307 306
308 async function testChangesAccessRightsToProperty(collection: ICollectionNFT | ICollectionRFT) {307 async function testChangesAccessRightsToProperty(collection: UniqueNFTCollection | UniqueRFTCollection) {
309 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]))308 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]))
310 .to.be.fulfilled;309 .to.be.fulfilled;
311310
338 });337 });
339 });338 });
340339
341 async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: ICollectionNFT | ICollectionRFT) {340 async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: UniqueNFTCollection | UniqueRFTCollection) {
342 await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]))341 await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]))
343 .to.be.rejectedWith(/common\.NoPermission/);342 .to.be.rejectedWith(/common\.NoPermission/);
344343
354 await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice));353 await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice));
355 });354 });
356355
357 async function testPreventFromAddingTooManyPossibleProperties(collection: ICollectionNFT | ICollectionRFT) { 356 async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) {
358 const constitution = [];357 const constitution = [];
359 for (let i = 0; i < 65; i++) {358 for (let i = 0; i < 65; i++) {
360 constitution.push({359 constitution.push({
378 await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice));377 await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice));
379 });378 });
380379
381 async function testPreventAccessRightsModifiedIfConstant(collection: ICollectionNFT | ICollectionRFT) {380 async function testPreventAccessRightsModifiedIfConstant(collection: UniqueNFTCollection | UniqueRFTCollection) {
382 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))381 await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]))
383 .to.be.fulfilled;382 .to.be.fulfilled;
384383
399 await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice));398 await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice));
400 });399 });
401400
402 async function testPreventsAddingPropertiesWithInvalidNames(collection: ICollectionNFT | ICollectionRFT) {401 async function testPreventsAddingPropertiesWithInvalidNames(collection: UniqueNFTCollection | UniqueRFTCollection) {
403 const invalidProperties = [402 const invalidProperties = [
404 [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],403 [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],
405 [{key: 'G#4', permission: {tokenOwner: true}}],404 [{key: 'G#4', permission: {tokenOwner: true}}],
469 ];468 ];
470 });469 });
471 470
472 async function testReadsYetEmptyProperties(token: ITokenNonfungible | ITokenRefungible) {471 async function testReadsYetEmptyProperties(token: UniqueNFToken | UniqueRFToken) {
473 const properties = await token.getProperties();472 const properties = await token.getProperties();
474 expect(properties).to.be.empty;473 expect(properties).to.be.empty;
475474
489 await testReadsYetEmptyProperties(token);488 await testReadsYetEmptyProperties(token);
490 });489 });
491490
492 async function testAssignPropertiesAccordingToPermissions(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {491 async function testAssignPropertiesAccordingToPermissions(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
493 await token.collection.addAdmin(alice, {Substrate: bob.address});492 await token.collection.addAdmin(alice, {Substrate: bob.address});
494 await token.transfer(alice, {Substrate: charlie.address}, pieces);493 await token.transfer(alice, {Substrate: charlie.address}, pieces);
495494
535 await testAssignPropertiesAccordingToPermissions(token, 100n);534 await testAssignPropertiesAccordingToPermissions(token, 100n);
536 });535 });
537536
538 async function testChangesPropertiesAccordingPermission(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {537 async function testChangesPropertiesAccordingPermission(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
539 await token.collection.addAdmin(alice, {Substrate: bob.address});538 await token.collection.addAdmin(alice, {Substrate: bob.address});
540 await token.transfer(alice, {Substrate: charlie.address}, pieces);539 await token.transfer(alice, {Substrate: charlie.address}, pieces);
541540
588 await testChangesPropertiesAccordingPermission(token, 100n);587 await testChangesPropertiesAccordingPermission(token, 100n);
589 });588 });
590589
591 async function testDeletePropertiesAccordingPermission(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {590 async function testDeletePropertiesAccordingPermission(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
592 await token.collection.addAdmin(alice, {Substrate: bob.address});591 await token.collection.addAdmin(alice, {Substrate: bob.address});
593 await token.transfer(alice, {Substrate: charlie.address}, pieces);592 await token.transfer(alice, {Substrate: charlie.address}, pieces);
594593
799 return (await (mode == 'NFT' ? api.query.nonfungible : api.query.refungible).tokenProperties(collectionId, tokenId)).toJSON().consumedSpace;798 return (await (mode == 'NFT' ? api.query.nonfungible : api.query.refungible).tokenProperties(collectionId, tokenId)).toJSON().consumedSpace;
800 }799 }
801800
802 async function prepare(token: ITokenNonfungible | ITokenRefungible, pieces: bigint): Promise<number> {801 async function prepare(token: UniqueNFToken | UniqueRFToken, pieces: bigint): Promise<number> {
803 await token.collection.addAdmin(alice, {Substrate: bob.address});802 await token.collection.addAdmin(alice, {Substrate: bob.address});
804 await token.transfer(alice, {Substrate: charlie.address}, pieces);803 await token.transfer(alice, {Substrate: charlie.address}, pieces);
805804
823 return originalSpace;822 return originalSpace;
824 }823 }
825824
826 async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {825 async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
827 const originalSpace = await prepare(token, pieces);826 const originalSpace = await prepare(token, pieces);
828827
829 let i = 0;828 let i = 0;
858 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token, 100n);857 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(token, 100n);
859 });858 });
860859
861 async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {860 async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
862 const originalSpace = await prepare(token, pieces);861 const originalSpace = await prepare(token, pieces);
863862
864 let i = 0;863 let i = 0;
893 await testForbidsChangingDeletingPropertiesIfPropertyImmutable(token, 100n);892 await testForbidsChangingDeletingPropertiesIfPropertyImmutable(token, 100n);
894 });893 });
895894
896 async function testForbidsAddingPropertiesIfPropertyNotDeclared(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {895 async function testForbidsAddingPropertiesIfPropertyNotDeclared(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
897 const originalSpace = await prepare(token, pieces);896 const originalSpace = await prepare(token, pieces);
898897
899 await expect(898 await expect(
929 await testForbidsAddingPropertiesIfPropertyNotDeclared(token, 100n);928 await testForbidsAddingPropertiesIfPropertyNotDeclared(token, 100n);
930 });929 });
931930
932 async function testForbidsAddingTooManyProperties(token: ITokenNonfungible | ITokenRefungible, pieces: bigint) {931 async function testForbidsAddingTooManyProperties(token: UniqueNFToken | UniqueRFToken, pieces: bigint) {
933 const originalSpace = await prepare(token, pieces);932 const originalSpace = await prepare(token, pieces);
934933
935 await expect(934 await expect(
984 });983 });
985 });984 });
986985
987 async function prepare(helper: UniqueHelper): Promise<ITokenRefungible> {986 async function prepare(helper: UniqueHelper): Promise<UniqueRFToken> {
988 const collection = await helper.rft.mintCollection(alice);987 const collection = await helper.rft.mintCollection(alice);
989 const token = await collection.mintToken(alice, 100n);988 const token = await collection.mintToken(alice, 100n);
990 989
modifiedtests/src/util/playgrounds/index.tsdiffbeforeafterboth
12chai.use(chaiAsPromised);12chai.use(chaiAsPromised);
13export const expect = chai.expect;13export const expect = chai.expect;
14
15export const U128_MAX = (1n << 128n) - 1n;
16
17const MICROUNIQUE = 1_000_000_000_000n;
18const MILLIUNIQUE = 1_000n * MICROUNIQUE;
19const CENTIUNIQUE = 10n * MILLIUNIQUE;
20export const UNIQUE = 100n * CENTIUNIQUE;
2114
22export const usingPlaygrounds = async (code: (helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>, url: string = config.substrateUrl) => {15export const usingPlaygrounds = async (code: (helper: DevUniqueHelper, privateKey: (seed: string) => IKeyringPair) => Promise<void>, url: string = config.substrateUrl) => {
23 const silentConsole = new SilentConsole();16 const silentConsole = new SilentConsole();
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
2// SPDX-License-Identifier: Apache-2.02// SPDX-License-Identifier: Apache-2.0
33
4import {IKeyringPair} from '@polkadot/types/types';4import {IKeyringPair} from '@polkadot/types/types';
5import {UniqueHelper} from './unique';
65
7export interface IEvent {6export interface IEvent {
8 section: string;7 section: string;
107 }106 }
108}107}
109108
110export interface ITokenAddress {109export interface IToken {
111 collectionId: number;110 collectionId: number;
112 tokenId: number;111 tokenId: number;
113}112}
169export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';168export type TUniqueNetworks = 'opal' | 'quartz' | 'unique';
170export type TSigner = IKeyringPair; // | 'string'169export type TSigner = IKeyringPair; // | 'string'
171
172export 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: any
183 } | 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}
207
208export interface ICollectionNFT extends ICollectionBase {
209 getTokenObject: (tokenId: number) => ITokenNonfungible; // todo:playgrounds
210 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:playgrounds
219 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:playgrounds
226 mintMultipleTokens: (signer: TSigner, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]) => Promise<ITokenNonfungible[]>;// todo:playgrounds
227 burnToken: (signer: TSigner, tokenId: number) => Promise<{
228 success: boolean,
229 token: number | null
230 }>;
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}
238
239export 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:playgrounds
259 burnToken: (signer: TSigner, tokenId: number, amount: bigint) => Promise<{
260 success: boolean,
261 token: number | null
262 }>;
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}
268
269export 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}
282
283export 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}
292
293export 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:playgrounds
303 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 | null
312 }>;
313 burnFrom: (signer: TSigner, fromAddressObj: ICrossAccountId) => Promise<boolean>;
314}
315
316export 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 | null
334 }>;
335 burnFrom: (signer: TSigner, fromAddressObj: ICrossAccountId, amount: bigint) => Promise<boolean>;
336}
337170
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
9import {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, ITokenAddress, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks, ICollectionBase, ICollectionNFT, ICollectionRFT, ITokenBase, ITokenNonfungible, ITokenRefungible, ICollectionFT} from './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';
1313
14export 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 };
5757
58 static getTokenAccount(token: ITokenAddress): ICrossAccountId {58 static getTokenAccount(token: IToken): ICrossAccountId {
59 return {Ethereum: this.getTokenAddress(token)};59 return {Ethereum: this.getTokenAddress(token)};
60 }60 }
6161
62 static getTokenAccountInLowerCase(token: ITokenAddress): ICrossAccountId {62 static getTokenAccountInLowerCase(token: IToken): ICrossAccountId {
63 return {Ethereum: this.getTokenAddress(token).toLowerCase()};63 return {Ethereum: this.getTokenAddress(token).toLowerCase()};
64 }64 }
6565
66 static getTokenAddress(token: ITokenAddress): string {66 static getTokenAddress(token: IToken): string {
67 return nesting.tokenIdToAddress(token.collectionId, token.tokenId);67 return nesting.tokenIdToAddress(token.collectionId, token.tokenId);
68 }68 }
6969
1218 * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")1218 * @example mintCollection(aliceKeyring, {name: 'New', description: "New collection", tokenPrefix: "NEW"}, "NFT")
1219 * @returns object of the created collection1219 * @returns object of the created collection
1220 */1220 */
1221 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueCollectionBase> {1221 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueBaseCollection> {
1222 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1222 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object
1223 collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1223 collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};
1224 for (const key of ['name', 'description', 'tokenPrefix']) {1224 for (const key of ['name', 'description', 'tokenPrefix']) {
1260 * @example getTokenObject(10, 5);1260 * @example getTokenObject(10, 5);
1261 * @returns instance of UniqueNFTToken1261 * @returns instance of UniqueNFTToken
1262 */1262 */
1263 getTokenObject(collectionId: number, tokenId: number): UniqueNFTToken {1263 getTokenObject(collectionId: number, tokenId: number): UniqueNFToken {
1264 return new UniqueNFTToken(tokenId, this.getCollectionObject(collectionId));1264 return new UniqueNFToken(tokenId, this.getCollectionObject(collectionId));
1265 }1265 }
12661266
1267 /**1267 /**
1352 * @example getTokenChildren(10, 5);1352 * @example getTokenChildren(10, 5);
1353 * @returns tokens whose depth of nesting is <= 51353 * @returns tokens whose depth of nesting is <= 5
1354 */1354 */
1355 async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<ITokenAddress[]> {1355 async getTokenChildren(collectionId: number, tokenId: number, blockHashAt?: string): Promise<IToken[]> {
1356 let children;1356 let children;
1357 if(typeof blockHashAt === 'undefined') {1357 if(typeof blockHashAt === 'undefined') {
1358 children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);1358 children = await this.helper.callRpc('api.rpc.unique.tokenChildren', [collectionId, tokenId]);
1373 * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});1373 * @example nestToken(aliceKeyring, {collectionId: 10, tokenId: 5}, {collectionId: 10, tokenId: 4});
1374 * @returns ```true``` if extrinsic success, otherwise ```false```1374 * @returns ```true``` if extrinsic success, otherwise ```false```
1375 */1375 */
1376 async nestToken(signer: TSigner, tokenObj: ITokenAddress, rootTokenObj: ITokenAddress): Promise<boolean> {1376 async nestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken): Promise<boolean> {
1377 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1377 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);
1378 const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);1378 const result = await this.transferToken(signer, tokenObj.collectionId, tokenObj.tokenId, rootTokenAddress);
1379 if(!result) {1379 if(!result) {
1391 * @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..."});
1392 * @returns ```true``` if extrinsic success, otherwise ```false```1392 * @returns ```true``` if extrinsic success, otherwise ```false```
1393 */1393 */
1394 async unnestToken(signer: TSigner, tokenObj: ITokenAddress, rootTokenObj: ITokenAddress, toAddressObj: ICrossAccountId): Promise<boolean> {1394 async unnestToken(signer: TSigner, tokenObj: IToken, rootTokenObj: IToken, toAddressObj: ICrossAccountId): Promise<boolean> {
1395 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);1395 const rootTokenAddress = this.helper.util.getTokenAccount(rootTokenObj);
1396 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);
1397 if(!result) {1397 if(!result) {
1422 * @param data token data1422 * @param data token data
1423 * @returns created token object1423 * @returns created token object
1424 */1424 */
1425 async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }): Promise<UniqueNFTToken> {1425 async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; properties?: IProperty[]; }): Promise<UniqueNFToken> {
1426 const creationResult = await this.helper.executeExtrinsic(1426 const creationResult = await this.helper.executeExtrinsic(
1427 signer,1427 signer,
1428 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1428 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {
1453 * }]);1453 * }]);
1454 * @returns ```true``` if extrinsic success, otherwise ```false```1454 * @returns ```true``` if extrinsic success, otherwise ```false```
1455 */1455 */
1456 async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFTToken[]> {1456 async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, properties?: IProperty[]}[]): Promise<UniqueNFToken[]> {
1457 const creationResult = await this.helper.executeExtrinsic(1457 const creationResult = await this.helper.executeExtrinsic(
1458 signer,1458 signer,
1459 'api.tx.unique.createMultipleItemsEx', [collectionId, {NFT: tokens}],1459 'api.tx.unique.createMultipleItemsEx', [collectionId, {NFT: tokens}],
1460 true,1460 true,
1461 );1461 );
1462 const collection = this.getCollectionObject(collectionId);1462 const collection = this.getCollectionObject(collectionId);
1463 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1463 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
1464 }1464 }
14651465
1466 /**1466 /**
1481 * }]);1481 * }]);
1482 * @returns array of newly created tokens1482 * @returns array of newly created tokens
1483 */1483 */
1484 async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[]): Promise<UniqueNFTToken[]> {1484 async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {properties?: IProperty[]}[]): Promise<UniqueNFToken[]> {
1485 const rawTokens = [];1485 const rawTokens = [];
1486 for (const token of tokens) {1486 for (const token of tokens) {
1487 const raw = {NFT: {properties: token.properties}};1487 const raw = {NFT: {properties: token.properties}};
1493 true,1493 true,
1494 );1494 );
1495 const collection = this.getCollectionObject(collectionId);1495 const collection = this.getCollectionObject(collectionId);
1496 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1496 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
1497 }1497 }
14981498
1499 /**1499 /**
1530 * @example getTokenObject(10, 5);1530 * @example getTokenObject(10, 5);
1531 * @returns instance of UniqueNFTToken1531 * @returns instance of UniqueNFTToken
1532 */1532 */
1533 getTokenObject(collectionId: number, tokenId: number): UniqueRFTToken {1533 getTokenObject(collectionId: number, tokenId: number): UniqueRFToken {
1534 return new UniqueRFTToken(tokenId, this.getCollectionObject(collectionId));1534 return new UniqueRFToken(tokenId, this.getCollectionObject(collectionId));
1535 }1535 }
15361536
1537 /**1537 /**
1609 * @example mintToken(aliceKeyring, {collectionId: 10, owner: {Substrate: '5GHoZe9c73RYbVzq...'}, pieces: 10000n});1609 * @example mintToken(aliceKeyring, {collectionId: 10, owner: {Substrate: '5GHoZe9c73RYbVzq...'}, pieces: 10000n});
1610 * @returns created token object1610 * @returns created token object
1611 */1611 */
1612 async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }): Promise<UniqueRFTToken> {1612 async mintToken(signer: TSigner, data: { collectionId: number; owner: ICrossAccountId | string; pieces: bigint; properties?: IProperty[]; }): Promise<UniqueRFToken> {
1613 const creationResult = await this.helper.executeExtrinsic(1613 const creationResult = await this.helper.executeExtrinsic(
1614 signer,1614 signer,
1615 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1615 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {
1626 return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);1626 return this.getTokenObject(data.collectionId, createdTokens.tokens[0].tokenId);
1627 }1627 }
16281628
1629 async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFTToken[]> {1629 async mintMultipleTokens(signer: TSigner, collectionId: number, tokens: {owner: ICrossAccountId, pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFToken[]> {
1630 throw Error('Not implemented');1630 throw Error('Not implemented');
1631 const creationResult = await this.helper.executeExtrinsic(1631 const creationResult = await this.helper.executeExtrinsic(
1632 signer,1632 signer,
1633 'api.tx.unique.createMultipleItemsEx', [collectionId, {RefungibleMultipleOwners: tokens}],1633 'api.tx.unique.createMultipleItemsEx', [collectionId, {RefungibleMultipleOwners: tokens}],
1634 true, // `Unable to mint RFT tokens for ${label}`,1634 true, // `Unable to mint RFT tokens for ${label}`,
1635 );1635 );
1636 const collection = this.getCollectionObject(collectionId);1636 const collection = this.getCollectionObject(collectionId);
1637 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1637 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
1638 }1638 }
16391639
1640 /**1640 /**
1646 * @example mintMultipleTokensWithOneOwner(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, [{pieces: 100000n, properties: [{key: "gender", value: "male"}]}]);1646 * @example mintMultipleTokensWithOneOwner(aliceKeyring, 10, {Substrate: "5GHoZe9c73RYbVzq..."}, [{pieces: 100000n, properties: [{key: "gender", value: "male"}]}]);
1647 * @returns array of newly created RFT tokens1647 * @returns array of newly created RFT tokens
1648 */1648 */
1649 async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFTToken[]> {1649 async mintMultipleTokensWithOneOwner(signer: TSigner, collectionId: number, owner: ICrossAccountId, tokens: {pieces: bigint, properties?: IProperty[]}[]): Promise<UniqueRFToken[]> {
1650 const rawTokens = [];1650 const rawTokens = [];
1651 for (const token of tokens) {1651 for (const token of tokens) {
1652 const raw = {ReFungible: {pieces: token.pieces, properties: token.properties}};1652 const raw = {ReFungible: {pieces: token.pieces, properties: token.properties}};
1658 true,1658 true,
1659 );1659 );
1660 const collection = this.getCollectionObject(collectionId);1660 const collection = this.getCollectionObject(collectionId);
1661 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: ITokenAddress) => collection.getTokenObject(x.tokenId));1661 return this.helper.util.extractTokensFromCreationResult(creationResult).tokens.map((x: IToken) => collection.getTokenObject(x.tokenId));
1662 }1662 }
16631663
1664 /**1664 /**
19841984
19851985
1986class BalanceGroup extends HelperGroup {1986class BalanceGroup extends HelperGroup {
1987 /**1987 /**
1988 * Representation of the native token in the smallest unit1988 * Representation of the native token in the smallest unit - one OPAL (OPL), QUARTZ (QTZ), or UNIQUE (UNQ).
1989 * @example getOneTokenNominal()1989 * @example getOneTokenNominal()
1990 * @returns ```BigInt``` representation of the native token in the smallest unit, e.g. ```1_000_000_000_000_000_000n``` for QTZ.1990 * @returns ```BigInt``` representation of the native token in the smallest unit, e.g. ```1_000_000_000_000_000_000n``` for QTZ.
1991 */1991 */
1992 getOneTokenNominal(): bigint {1992 getOneTokenNominal(): bigint {
1993 const chainProperties = this.helper.chain.getChainProperties();1993 const chainProperties = this.helper.chain.getChainProperties();
1994 return 10n ** BigInt((chainProperties.tokenDecimals || [18])[0]);1994 return 10n ** BigInt((chainProperties.tokenDecimals || [18])[0]);
2223}2223}
22242224
22252225
2226class UniqueCollectionBase implements ICollectionBase {2226export class UniqueBaseCollection {
2227 helper: UniqueHelper;2227 helper: UniqueHelper;
2228 collectionId: number;2228 collectionId: number;
22292229
2326}2326}
23272327
23282328
2329class UniqueNFTCollection extends UniqueCollectionBase implements ICollectionNFT {2329export class UniqueNFTCollection extends UniqueBaseCollection {
2330 getTokenObject(tokenId: number) {2330 getTokenObject(tokenId: number) {
2331 return new UniqueNFTToken(tokenId, this);2331 return new UniqueNFToken(tokenId, this);
2332 }2332 }
23332333
2334 async getTokensByAddress(addressObj: ICrossAccountId) {2334 async getTokensByAddress(addressObj: ICrossAccountId) {
2403 return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2403 return await this.helper.nft.setTokenPropertyPermissions(signer, this.collectionId, permissions);
2404 }2404 }
24052405
2406 async nestToken(signer: TSigner, tokenId: number, toTokenObj: ITokenAddress) {2406 async nestToken(signer: TSigner, tokenId: number, toTokenObj: IToken) {
2407 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);
2408 }2408 }
24092409
2410 async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: ITokenAddress, toAddressObj: ICrossAccountId) {2410 async unnestToken(signer: TSigner, tokenId: number, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {
2411 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);
2412 }2412 }
2413}2413}
24142414
24152415
2416class UniqueRFTCollection extends UniqueCollectionBase implements ICollectionRFT {2416export class UniqueRFTCollection extends UniqueBaseCollection {
2417 getTokenObject(tokenId: number) {2417 getTokenObject(tokenId: number) {
2418 return new UniqueRFTToken(tokenId, this);2418 return new UniqueRFToken(tokenId, this);
2419 }2419 }
24202420
2421 async getToken(tokenId: number, blockHashAt?: string) {2421 async getToken(tokenId: number, blockHashAt?: string) {
2496}2496}
24972497
24982498
2499class UniqueFTCollection extends UniqueCollectionBase implements ICollectionFT {2499export class UniqueFTCollection extends UniqueBaseCollection {
2500 async getBalance(addressObj: ICrossAccountId) {2500 async getBalance(addressObj: ICrossAccountId) {
2501 return await this.helper.ft.getBalance(this.collectionId, addressObj);2501 return await this.helper.ft.getBalance(this.collectionId, addressObj);
2502 }2502 }
2543}2543}
25442544
25452545
2546class UniqueTokenBase implements ITokenBase {2546export class UniqueBaseToken {
2547 collection: UniqueNFTCollection | UniqueRFTCollection;2547 collection: UniqueNFTCollection | UniqueRFTCollection;
2548 collectionId: number;2548 collectionId: number;
2549 tokenId: number;2549 tokenId: number;
2580}2580}
25812581
25822582
2583class UniqueNFTToken extends UniqueTokenBase implements ITokenNonfungible {2583export class UniqueNFToken extends UniqueBaseToken {
2584 collection: UniqueNFTCollection;2584 collection: UniqueNFTCollection;
25852585
2586 constructor(tokenId: number, collection: UniqueNFTCollection) {2586 constructor(tokenId: number, collection: UniqueNFTCollection) {
2604 return await this.collection.getTokenChildren(this.tokenId, blockHashAt);2604 return await this.collection.getTokenChildren(this.tokenId, blockHashAt);
2605 }2605 }
26062606
2607 async nest(signer: TSigner, toTokenObj: ITokenAddress) {2607 async nest(signer: TSigner, toTokenObj: IToken) {
2608 return await this.collection.nestToken(signer, this.tokenId, toTokenObj);2608 return await this.collection.nestToken(signer, this.tokenId, toTokenObj);
2609 }2609 }
26102610
2611 async unnest(signer: TSigner, fromTokenObj: ITokenAddress, toAddressObj: ICrossAccountId) {2611 async unnest(signer: TSigner, fromTokenObj: IToken, toAddressObj: ICrossAccountId) {
2612 return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);2612 return await this.collection.unnestToken(signer, this.tokenId, fromTokenObj, toAddressObj);
2613 }2613 }
26142614
2637 }2637 }
2638}2638}
26392639
2640class UniqueRFTToken extends UniqueTokenBase implements ITokenRefungible {2640export class UniqueRFToken extends UniqueBaseToken {
2641 collection: UniqueRFTCollection;2641 collection: UniqueRFTCollection;
26422642
2643 constructor(tokenId: number, collection: UniqueRFTCollection) {2643 constructor(tokenId: number, collection: UniqueRFTCollection) {