1234567891011121314151617import {expect} from 'chai';18import {IKeyringPair} from '@polkadot/types/types';19import {EthUniqueHelper, itEth, usingEthPlaygrounds} from './util';20import {IEvent, TCollectionMode} from '../util/playgrounds/types';21import {Pallets, requirePalletsOrSkip} from '../util';22import {CollectionLimitField, TokenPermissionField, NormalizedEvent, CreateCollectionData} from './util/playgrounds/types';2324let donor: IKeyringPair;2526before(async function () {27 await usingEthPlaygrounds(async (_helper, privateKey) => {28 donor = await privateKey({url: import.meta.url});29 });30});3132function clearEvents(ethEvents: NormalizedEvent[] | null, subEvents: IEvent[]) {33 if(ethEvents !== null) {34 ethEvents.splice(0);35 }36 subEvents.splice(0);37}3839async function testCollectionCreatedAndDestroy(helper: EthUniqueHelper, mode: TCollectionMode) {40 const owner = await helper.eth.createAccountWithBalance(donor);41 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionCreated', 'CollectionDestroyed']}]);42 const {collectionAddress, events: ethEvents} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();4344 await helper.wait.newBlocks(1);45 {46 expect(ethEvents).to.containSubset([47 {48 event: 'CollectionCreated',49 args: {50 owner: owner,51 collectionId: collectionAddress,52 },53 },54 ]);55 expect(subEvents).to.containSubset([{method: 'CollectionCreated'}]);56 clearEvents(ethEvents, subEvents);57 }58 {59 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);60 const result = await collectionHelper.methods.destroyCollection(collectionAddress).send({from:owner});61 await helper.wait.newBlocks(1);62 expect(result.events).to.containSubset({63 CollectionDestroyed: {64 returnValues: {65 collectionId: collectionAddress,66 },67 },68 });69 expect(subEvents).to.containSubset([{method: 'CollectionDestroyed'}]);70 }71 unsubscribe();72}7374async function testCollectionPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) {75 const owner = await helper.eth.createAccountWithBalance(donor);76 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();77 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);78 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);7980 const ethEvents: any = [];81 collectionHelper.events.allEvents((_: any, event: any) => {82 ethEvents.push(event);83 });84 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPropertySet', 'CollectionPropertyDeleted']}]);85 {86 await collection.methods.setCollectionProperties([{key: 'A', value: [0,1,2,3]}]).send({from:owner});87 await helper.wait.newBlocks(1);88 expect(ethEvents).to.containSubset([89 {90 event: 'CollectionChanged',91 returnValues: {92 collectionId: collectionAddress,93 },94 },95 ]);96 expect(subEvents).to.containSubset([{method: 'CollectionPropertySet'}]);97 clearEvents(ethEvents, subEvents);98 }99 {100 await collection.methods.deleteCollectionProperties(['A']).send({from:owner});101 await helper.wait.newBlocks(1);102 expect(ethEvents).to.containSubset([103 {104 event: 'CollectionChanged',105 returnValues: {106 collectionId: collectionAddress,107 },108 },109 ]);110 expect(subEvents).to.containSubset([{method: 'CollectionPropertyDeleted'}]);111 }112 unsubscribe();113}114115async function testPropertyPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) {116 const owner = await helper.eth.createAccountWithBalance(donor);117 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();118 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);119 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);120 const ethEvents: any = [];121 collectionHelper.events.allEvents((_: any, event: any) => {122 ethEvents.push(event);123 });124 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]);125 await collection.methods.setTokenPropertyPermissions([126 ['A', [127 [TokenPermissionField.Mutable, true],128 [TokenPermissionField.TokenOwner, true],129 [TokenPermissionField.CollectionAdmin, true]],130 ],131 ]).send({from: owner});132 await helper.wait.newBlocks(1);133 expect(ethEvents).to.containSubset([134 {135 event: 'CollectionChanged',136 returnValues: {137 collectionId: collectionAddress,138 },139 },140 ]);141 expect(subEvents).to.containSubset([{method: 'PropertyPermissionSet'}]);142 unsubscribe();143}144145async function testAllowListAddressAddedAndRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {146 const owner = await helper.eth.createAccountWithBalance(donor);147 const user = helper.ethCrossAccount.createAccount();148 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();149 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);150 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);151 const ethEvents: any[] = [];152 collectionHelper.events.allEvents((_: any, event: any) => {153 ethEvents.push(event);154 });155156 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['AllowListAddressAdded', 'AllowListAddressRemoved']}]);157 {158 await collection.methods.addToCollectionAllowListCross(user).send({from: owner});159 await helper.wait.newBlocks(1);160 expect(ethEvents).to.containSubset([161 {162 event: 'CollectionChanged',163 returnValues: {164 collectionId: collectionAddress,165 },166 },167 ]);168 expect(subEvents).to.containSubset([{method: 'AllowListAddressAdded'}]);169 clearEvents(ethEvents, subEvents);170 }171 {172 await collection.methods.removeFromCollectionAllowListCross(user).send({from: owner});173 await helper.wait.newBlocks(1);174 expect(ethEvents).to.containSubset([175 {176 event: 'CollectionChanged',177 returnValues: {178 collectionId: collectionAddress,179 },180 },181 ]);182 expect(subEvents).to.containSubset([{method: 'AllowListAddressRemoved'}]);183 }184 unsubscribe();185}186187async function testCollectionAdminAddedAndRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {188 const owner = await helper.eth.createAccountWithBalance(donor);189 const user = helper.ethCrossAccount.createAccount();190 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();191 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);192 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);193 const ethEvents: any = [];194 collectionHelper.events.allEvents((_: any, event: any) => {195 ethEvents.push(event);196 });197 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionAdminAdded', 'CollectionAdminRemoved']}]);198 {199 await collection.methods.addCollectionAdminCross(user).send({from: owner});200 await helper.wait.newBlocks(1);201 expect(ethEvents).to.containSubset([202 {203 event: 'CollectionChanged',204 returnValues: {205 collectionId: collectionAddress,206 },207 },208 ]);209 expect(subEvents).to.containSubset([{method: 'CollectionAdminAdded'}]);210 clearEvents(ethEvents, subEvents);211 }212 {213 await collection.methods.removeCollectionAdminCross(user).send({from: owner});214 await helper.wait.newBlocks(1);215 expect(ethEvents).to.containSubset([216 {217 event: 'CollectionChanged',218 returnValues: {219 collectionId: collectionAddress,220 },221 },222 ]);223 expect(subEvents).to.containSubset([{method: 'CollectionAdminRemoved'}]);224 }225 unsubscribe();226}227228async function testCollectionLimitSet(helper: EthUniqueHelper, mode: TCollectionMode) {229 const owner = await helper.eth.createAccountWithBalance(donor);230 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();231 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);232 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);233 const ethEvents: any = [];234 collectionHelper.events.allEvents((_: any, event: any) => {235 ethEvents.push(event);236 });237 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionLimitSet']}]);238 {239 await collection.methods.setCollectionLimit({field: CollectionLimitField.OwnerCanTransfer, value: {status: true, value: 0}}).send({from: owner});240 await helper.wait.newBlocks(1);241 expect(ethEvents).to.containSubset([242 {243 event: 'CollectionChanged',244 returnValues: {245 collectionId: collectionAddress,246 },247 },248 ]);249 expect(subEvents).to.containSubset([{method: 'CollectionLimitSet'}]);250 }251 unsubscribe();252}253254async function testCollectionOwnerChanged(helper: EthUniqueHelper, mode: TCollectionMode) {255 const owner = await helper.eth.createAccountWithBalance(donor);256 const newOwner = helper.ethCrossAccount.createAccount();257 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();258 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);259 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);260 const ethEvents: any = [];261 collectionHelper.events.allEvents((_: any, event: any) => {262 ethEvents.push(event);263 });264 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionOwnerChanged']}]);265 {266 await collection.methods.changeCollectionOwnerCross(newOwner).send({from: owner});267 await helper.wait.newBlocks(1);268 expect(ethEvents).to.containSubset([269 {270 event: 'CollectionChanged',271 returnValues: {272 collectionId: collectionAddress,273 },274 },275 ]);276 expect(subEvents).to.containSubset([{method: 'CollectionOwnerChanged'}]);277 }278 unsubscribe();279}280281async function testCollectionPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) {282 const owner = await helper.eth.createAccountWithBalance(donor);283 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();284 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);285 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);286 const ethEvents: any = [];287 collectionHelper.events.allEvents((_: any, event: any) => {288 ethEvents.push(event);289 });290 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['CollectionPermissionSet']}]);291 {292 await collection.methods.setCollectionMintMode(true).send({from: owner});293 await helper.wait.newBlocks(1);294 expect(ethEvents).to.containSubset([295 {296 event: 'CollectionChanged',297 returnValues: {298 collectionId: collectionAddress,299 },300 },301 ]);302 expect(subEvents).to.containSubset([{method: 'CollectionPermissionSet'}]);303 clearEvents(ethEvents, subEvents);304 }305 {306 await collection.methods.setCollectionAccess(1).send({from: owner});307 await helper.wait.newBlocks(1);308 expect(ethEvents).to.containSubset([309 {310 event: 'CollectionChanged',311 returnValues: {312 collectionId: collectionAddress,313 },314 },315 ]);316 expect(subEvents).to.containSubset([{method: 'CollectionPermissionSet'}]);317 }318 unsubscribe();319}320321async function testCollectionSponsorSetAndConfirmedAndThenRemoved(helper: EthUniqueHelper, mode: TCollectionMode) {322 const owner = await helper.eth.createAccountWithBalance(donor);323 const sponsor = await helper.ethCrossAccount.createAccountWithBalance(donor);324 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();325 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);326 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);327 const ethEvents: any = [];328 collectionHelper.events.allEvents((_: any, event: any) => {329 ethEvents.push(event);330 });331 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{332 section: 'common', names: ['CollectionSponsorSet', 'SponsorshipConfirmed', 'CollectionSponsorRemoved',333 ]}]);334 {335 await collection.methods.setCollectionSponsorCross(sponsor).send({from: owner});336 await helper.wait.newBlocks(1);337 expect(ethEvents).to.containSubset([{338 event: 'CollectionChanged',339 returnValues: {340 collectionId: collectionAddress,341 },342 }]);343 expect(subEvents).to.containSubset([{method: 'CollectionSponsorSet'}]);344 clearEvents(ethEvents, subEvents);345 }346 {347 await collection.methods.confirmCollectionSponsorship().send({from: sponsor.eth});348 await helper.wait.newBlocks(1);349 expect(ethEvents).to.containSubset([350 {351 event: 'CollectionChanged',352 returnValues: {353 collectionId: collectionAddress,354 },355 },356 ]);357 expect(subEvents).to.containSubset([{method: 'SponsorshipConfirmed'}]);358 clearEvents(ethEvents, subEvents);359 }360 {361 await collection.methods.removeCollectionSponsor().send({from: owner});362 await helper.wait.newBlocks(1);363 expect(ethEvents).to.containSubset([364 {365 event: 'CollectionChanged',366 returnValues: {367 collectionId: collectionAddress,368 },369 },370 ]);371 expect(subEvents).to.containSubset([{method: 'CollectionSponsorRemoved'}]);372 }373 unsubscribe();374}375376async function testTokenPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) {377 const owner = await helper.eth.createAccountWithBalance(donor);378 const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('A', 'B', 'C', mode, 18)).send();379 const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner);380 const result = await collection.methods.mint(owner).send({from: owner});381 const tokenId = result.events.Transfer.returnValues.tokenId;382 await collection.methods.setTokenPropertyPermissions([383 ['A', [384 [TokenPermissionField.Mutable, true],385 [TokenPermissionField.TokenOwner, true],386 [TokenPermissionField.CollectionAdmin, true]],387 ],388 ]).send({from: owner});389390 const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['TokenPropertySet', 'TokenPropertyDeleted']}]);391 {392 const result = await collection.methods.setProperties(tokenId, [{key: 'A', value: [1,2,3]}]).send({from: owner});393 await helper.wait.newBlocks(1);394 expect(result.events.TokenChanged).to.be.like({395 event: 'TokenChanged',396 returnValues: {397 tokenId: tokenId,398 },399 });400 expect(subEvents).to.containSubset([{method: 'TokenPropertySet'}]);401 clearEvents(null, subEvents);402 }403 {404 const result = await collection.methods.deleteProperties(tokenId, ['A']).send({from: owner});405 await helper.wait.newBlocks(1);406 expect(result.events.TokenChanged).to.be.like({407 event: 'TokenChanged',408 returnValues: {409 tokenId: tokenId,410 },411 });412 expect(subEvents).to.containSubset([{method: 'TokenPropertyDeleted'}]);413 }414 unsubscribe();415}416417describe('[FT] Sync sub & eth events', () => {418 const mode: TCollectionMode = 'ft';419420 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {421 await testCollectionCreatedAndDestroy(helper, mode);422 });423424 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {425 await testCollectionPropertySetAndDeleted(helper, mode);426 });427428 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {429 await testAllowListAddressAddedAndRemoved(helper, mode);430 });431432 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {433 await testCollectionAdminAddedAndRemoved(helper, mode);434 });435436 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {437 await testCollectionLimitSet(helper, mode);438 });439440 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {441 await testCollectionOwnerChanged(helper, mode);442 });443444 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {445 await testCollectionPermissionSet(helper, mode);446 });447448 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {449 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);450 });451});452453describe('[NFT] Sync sub & eth events', () => {454 const mode: TCollectionMode = 'nft';455456 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {457 await testCollectionCreatedAndDestroy(helper, mode);458 });459460 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {461 await testCollectionPropertySetAndDeleted(helper, mode);462 });463464 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {465 await testPropertyPermissionSet(helper, mode);466 });467468 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {469 await testAllowListAddressAddedAndRemoved(helper, mode);470 });471472 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {473 await testCollectionAdminAddedAndRemoved(helper, mode);474 });475476 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {477 await testCollectionLimitSet(helper, mode);478 });479480 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {481 await testCollectionOwnerChanged(helper, mode);482 });483484 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {485 await testCollectionPermissionSet(helper, mode);486 });487488 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {489 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);490 });491492 itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => {493 await testTokenPropertySetAndDeleted(helper, mode);494 });495});496497describe('[RFT] Sync sub & eth events', () => {498 const mode: TCollectionMode = 'rft';499500 before(async function() {501 await usingEthPlaygrounds(async (helper, privateKey) => {502 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);503 const _donor = await privateKey({url: import.meta.url});504 });505 });506507 itEth('CollectionCreated and CollectionDestroyed events', async ({helper}) => {508 await testCollectionCreatedAndDestroy(helper, mode);509 });510511 itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => {512 await testCollectionPropertySetAndDeleted(helper, mode);513 });514515 itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => {516 await testPropertyPermissionSet(helper, mode);517 });518519 itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => {520 await testAllowListAddressAddedAndRemoved(helper, mode);521 });522523 itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => {524 await testCollectionAdminAddedAndRemoved(helper, mode);525 });526527 itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => {528 await testCollectionLimitSet(helper, mode);529 });530531 itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => {532 await testCollectionOwnerChanged(helper, mode);533 });534535 itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => {536 await testCollectionPermissionSet(helper, mode);537 });538539 itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => {540 await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode);541 });542543 itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => {544 await testTokenPropertySetAndDeleted(helper, mode);545 });546});