difftreelog
Merge branch 'develop' into tests/feed-alices
126 files changed
tests/src/.outdated/addToContractAllowList.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/balance-transfer-contract/calls.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/.outdated/balance-transfer-contract/metadata.jsondiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/admVsOwnerChanges.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/admVsOwnerData.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/admVsOwnerTake.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/adminDestroyCollection.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/adminLimitsOff.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/adminRightsOff.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/setSponsorNewOwner.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/sponsorPayments.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/tokenLimitsOff.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/collision-tests/turnsOffMinting.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/contracts.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/enableContractSponsoring.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/eth/scheduling.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/flipper/flipper.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/.outdated/flipper/metadata.jsondiffbeforeafterbothno changes
tests/src/.outdated/load_test_sc/loadtester.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/.outdated/load_test_sc/metadata.jsondiffbeforeafterbothno changes
tests/src/.outdated/overflow.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/removeFromContractAllowList.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/scheduler.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/setChainLimits.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/setContractSponsoringRateLimit.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/toggleContractAllowList.test.tsdiffbeforeafterbothno changes
tests/src/.outdated/transfer_contract/metadata.jsondiffbeforeafterbothno changes
tests/src/.outdated/transfer_contract/nft_transfer.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/.outdated/xcmTransfer.test.tsdiffbeforeafterbothno changes
tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth110 const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor);110 const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor);111 const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});111 const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});112112113 const chainAdminLimit = (helper.api!.consts.common.collectionAdminsLimit as any).toNumber();113 const chainAdminLimit = (helper.getApi().consts.common.collectionAdminsLimit as any).toNumber();114 expect(chainAdminLimit).to.be.equal(5);114 expect(chainAdminLimit).to.be.equal(5);115115116 for (let i = 0; i < chainAdminLimit; i++) {116 for (let i = 0; i < chainAdminLimit; i++) {tests/src/addToContractAllowList.test.tsdiffbeforeafterbothno changes
tests/src/app-promotion.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 {18import {itSub, usingPlaygrounds, Pallets, requirePalletsOrSkip} from './util/playgrounds';19 normalizeAccountId,20 getModuleNames,21 Pallets,22} from './util/helpers';23import {itSub, usingPlaygrounds} from './util/playgrounds';24import {encodeAddress} from '@polkadot/util-crypto';19import {encodeAddress} from '@polkadot/util-crypto';25import {stringToU8a} from '@polkadot/util';20import {stringToU8a} from '@polkadot/util';26import {SponsoringMode} from './eth/util/helpers';27import {DevUniqueHelper} from './util/playgrounds/unique.dev';21import {DevUniqueHelper} from './util/playgrounds/unique.dev';28import {itEth, expect} from './eth/util/playgrounds';22import {itEth, expect, SponsoringMode} from './eth/util/playgrounds';292330let alice: IKeyringPair;24let alice: IKeyringPair;31let palletAdmin: IKeyringPair;25let palletAdmin: IKeyringPair;42describe('App promotion', () => {36describe('App promotion', () => {43 before(async function () {37 before(async function () {44 await usingPlaygrounds(async (helper, privateKey) => {38 await usingPlaygrounds(async (helper, privateKey) => {45 if (!getModuleNames(helper.api!).includes(Pallets.AppPromotion)) this.skip();39 requirePalletsOrSkip(this, helper, [Pallets.AppPromotion]);46 alice = await privateKey({filename: __filename});40 alice = await privateKey({filename: __filename});47 [palletAdmin] = await helper.arrange.createAccounts([100n], alice);41 [palletAdmin] = await helper.arrange.createAccounts([100n], alice);48 await helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})));42 const api = helper.getApi();43 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})));49 nominal = helper.balance.getOneTokenNominal();44 nominal = helper.balance.getOneTokenNominal();50 await helper.balance.transferToSubstrate(alice, palletAdmin.address, 1000n * nominal);45 await helper.balance.transferToSubstrate(alice, palletAdmin.address, 1000n * nominal);51 await helper.balance.transferToSubstrate(alice, palletAddress, 1000n * nominal);46 await helper.balance.transferToSubstrate(alice, palletAddress, 1000n * nominal);231 226 232 describe('admin adress', () => {227 describe('admin adress', () => {233 itSub('can be set by sudo only', async ({helper}) => {228 itSub('can be set by sudo only', async ({helper}) => {229 const api = helper.getApi();234 const nonAdmin = accounts.pop()!;230 const nonAdmin = accounts.pop()!;235 // nonAdmin can not set admin not from himself nor as a sudo231 // nonAdmin can not set admin not from himself nor as a sudo236 await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address}))).to.be.rejected;232 await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address}))).to.be.rejected;237 await expect(helper.signTransaction(nonAdmin, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address})))).to.be.rejected;233 await expect(helper.signTransaction(nonAdmin, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address})))).to.be.rejected;238 234 239 // Alice can235 // Alice can240 await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.fulfilled;236 await expect(helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.fulfilled;241 });237 });242 238 243 itSub('can be any valid CrossAccountId', async ({helper}) => {239 itSub('can be any valid CrossAccountId', async ({helper}) => {244 // We are not going to set an eth address as a sponsor,240 // We are not going to set an eth address as a sponsor,245 // but we do want to check, it doesn't break anything;241 // but we do want to check, it doesn't break anything;242 const api = helper.getApi();246 const account = accounts.pop()!;243 const account = accounts.pop()!;247 const ethAccount = helper.address.substrateToEth(account.address); 244 const ethAccount = helper.address.substrateToEth(account.address); 248 // Alice sets Ethereum address as a sudo. Then Substrate address back...245 // Alice sets Ethereum address as a sudo. Then Substrate address back...249 await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Ethereum: ethAccount})))).to.be.fulfilled;246 await expect(helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Ethereum: ethAccount})))).to.be.fulfilled;250 await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.fulfilled;247 await expect(helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.fulfilled;251 248 252 // ...It doesn't break anything;249 // ...It doesn't break anything;253 const collection = await helper.nft.mintCollection(account, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});250 const collection = await helper.nft.mintCollection(account, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});254 await expect(helper.signTransaction(account, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;251 await expect(helper.signTransaction(account, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;255 });252 });256 253 257 itSub('can be reassigned', async ({helper}) => {254 itSub('can be reassigned', async ({helper}) => {255 const api = helper.getApi();258 const [oldAdmin, newAdmin, collectionOwner] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];256 const [oldAdmin, newAdmin, collectionOwner] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];259 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});257 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});260 258 261 await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress(normalizeAccountId(oldAdmin))))).to.be.fulfilled;259 await expect(helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: oldAdmin.address})))).to.be.fulfilled;262 await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress(normalizeAccountId(newAdmin))))).to.be.fulfilled;260 await expect(helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: newAdmin.address})))).to.be.fulfilled;263 await expect(helper.signTransaction(oldAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;261 await expect(helper.signTransaction(oldAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;264 262 265 await expect(helper.signTransaction(newAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled;263 await expect(helper.signTransaction(newAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled;266 });264 });267 });265 });268 266 269 describe('collection sponsoring', () => {267 describe('collection sponsoring', () => {270 before(async function () {268 before(async function () {271 await usingPlaygrounds(async (helper) => {269 await usingPlaygrounds(async (helper) => {272 const tx = helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address}));270 const api = helper.getApi();271 const tx = api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address}));273 await helper.signTransaction(alice, tx);272 await helper.signTransaction(alice, tx);274 });273 });275 });274 });276 275 277 itSub('should actually sponsor transactions', async ({helper}) => {276 itSub('should actually sponsor transactions', async ({helper}) => {277 const api = helper.getApi();278 const [collectionOwner, tokenSender, receiver] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];278 const [collectionOwner, tokenSender, receiver] = [accounts.pop()!, accounts.pop()!, accounts.pop()!];279 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'Name', description: 'Description', tokenPrefix: 'Prefix', limits: {sponsorTransferTimeout: 0}});279 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'Name', description: 'Description', tokenPrefix: 'Prefix', limits: {sponsorTransferTimeout: 0}});280 const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address});280 const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address});281 await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId));281 await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId));282 const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress);282 const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress);283 283 284 await token.transfer(tokenSender, {Substrate: receiver.address});284 await token.transfer(tokenSender, {Substrate: receiver.address});291 });291 });292 292 293 itSub('can not be set by non admin', async ({helper}) => {293 itSub('can not be set by non admin', async ({helper}) => {294 const api = helper.getApi();294 const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];295 const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];295 296 296 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});297 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});297 298 298 await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;299 await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;299 expect((await collection.getData())?.raw.sponsorship).to.equal('Disabled');300 expect((await collection.getData())?.raw.sponsorship).to.equal('Disabled');300 });301 });301 302 302 itSub('should set pallet address as confirmed admin', async ({helper}) => {303 itSub('should set pallet address as confirmed admin', async ({helper}) => {304 const api = helper.getApi();303 const [collectionOwner, oldSponsor] = [accounts.pop()!, accounts.pop()!];305 const [collectionOwner, oldSponsor] = [accounts.pop()!, accounts.pop()!];304 306 305 // Can set sponsoring for collection without sponsor307 // Can set sponsoring for collection without sponsor306 const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'});308 const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'});307 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithoutSponsor.collectionId))).to.be.fulfilled;309 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithoutSponsor.collectionId))).to.be.fulfilled;308 expect((await collectionWithoutSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});310 expect((await collectionWithoutSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});309 311 310 // Can set sponsoring for collection with unconfirmed sponsor312 // Can set sponsoring for collection with unconfirmed sponsor311 const collectionWithUnconfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Unconfirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address});313 const collectionWithUnconfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Unconfirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address});312 expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: oldSponsor.address});314 expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: oldSponsor.address});313 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithUnconfirmedSponsor.collectionId))).to.be.fulfilled;315 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithUnconfirmedSponsor.collectionId))).to.be.fulfilled;314 expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});316 expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});315 317 316 // Can set sponsoring for collection with confirmed sponsor318 // Can set sponsoring for collection with confirmed sponsor317 const collectionWithConfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Confirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address});319 const collectionWithConfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Confirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address});318 await collectionWithConfirmedSponsor.confirmSponsorship(oldSponsor);320 await collectionWithConfirmedSponsor.confirmSponsorship(oldSponsor);319 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithConfirmedSponsor.collectionId))).to.be.fulfilled;321 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithConfirmedSponsor.collectionId))).to.be.fulfilled;320 expect((await collectionWithConfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});322 expect((await collectionWithConfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});321 });323 });322 324 323 itSub('can be overwritten by collection owner', async ({helper}) => { 325 itSub('can be overwritten by collection owner', async ({helper}) => { 326 const api = helper.getApi();324 const [collectionOwner, newSponsor] = [accounts.pop()!, accounts.pop()!];327 const [collectionOwner, newSponsor] = [accounts.pop()!, accounts.pop()!];325 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});328 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});326 const collectionId = collection.collectionId;329 const collectionId = collection.collectionId;327 330 328 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionId))).to.be.fulfilled;331 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionId))).to.be.fulfilled;329 332 330 // Collection limits still can be changed by the owner333 // Collection limits still can be changed by the owner331 expect(await collection.setLimits(collectionOwner, {sponsorTransferTimeout: 0})).to.be.true;334 expect(await collection.setLimits(collectionOwner, {sponsorTransferTimeout: 0})).to.be.true;338 });341 });339 342 340 itSub('should not overwrite collection limits set by the owner earlier', async ({helper}) => {343 itSub('should not overwrite collection limits set by the owner earlier', async ({helper}) => {344 const api = helper.getApi();341 const limits = {ownerCanDestroy: true, ownerCanTransfer: true, sponsorTransferTimeout: 0};345 const limits = {ownerCanDestroy: true, ownerCanTransfer: true, sponsorTransferTimeout: 0};342 const collectionWithLimits = await helper.nft.mintCollection(alice, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits});346 const collectionWithLimits = await helper.nft.mintCollection(alice, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits});343 347 344 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithLimits.collectionId))).to.be.fulfilled;348 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithLimits.collectionId))).to.be.fulfilled;345 expect((await collectionWithLimits.getData())?.raw.limits).to.be.deep.contain(limits);349 expect((await collectionWithLimits.getData())?.raw.limits).to.be.deep.contain(limits);346 });350 });347 351 348 itSub('should reject transaction if collection doesn\'t exist', async ({helper}) => {352 itSub('should reject transaction if collection doesn\'t exist', async ({helper}) => {353 const api = helper.getApi();349 const collectionOwner = accounts.pop()!;354 const collectionOwner = accounts.pop()!;350 355 351 // collection has never existed356 // collection has never existed352 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(999999999))).to.be.rejected;357 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(999999999))).to.be.rejected;353 // collection has been burned358 // collection has been burned354 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});359 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});355 await collection.burn(collectionOwner);360 await collection.burn(collectionOwner);356 361 357 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;362 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected;358 });363 });359 });364 });360 365 361 describe('stopSponsoringCollection', () => {366 describe('stopSponsoringCollection', () => {362 itSub('can not be called by non-admin', async ({helper}) => { 367 itSub('can not be called by non-admin', async ({helper}) => {368 const api = helper.getApi();363 const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];369 const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!];364 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});370 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});365 371 366 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled;372 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled;367 373 368 await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.rejected;374 await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.rejected;369 expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});375 expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress});370 });376 });371 377 372 itSub('should set sponsoring as disabled', async ({helper}) => {378 itSub('should set sponsoring as disabled', async ({helper}) => {379 const api = helper.getApi();373 const [collectionOwner, recepient] = [accounts.pop()!, accounts.pop()!];380 const [collectionOwner, recepient] = [accounts.pop()!, accounts.pop()!];374 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}});381 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}});375 const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address});382 const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address});376 383 377 await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId));384 await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId));378 await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId));385 await helper.signTransaction(palletAdmin, api.tx.appPromotion.stopSponsoringCollection(collection.collectionId));379 386 380 expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled');387 expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled');381 388 387 });394 });388 395 389 itSub('should not affect collection which is not sponsored by pallete', async ({helper}) => {396 itSub('should not affect collection which is not sponsored by pallete', async ({helper}) => {397 const api = helper.getApi();390 const collectionOwner = accounts.pop()!;398 const collectionOwner = accounts.pop()!;391 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address});399 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address});392 await collection.confirmSponsorship(collectionOwner);400 await collection.confirmSponsorship(collectionOwner);393 401 394 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.rejected;402 await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.rejected;395 403 396 expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: collectionOwner.address});404 expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: collectionOwner.address});397 });405 });415 await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address]);423 await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address]);416 424 417 expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; 425 expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; 418 expect((await helper.api!.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); 426 expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); 419 expect((await helper.api!.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({427 expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({420 confirmed: {428 confirmed: {421 substrate: palletAddress,429 substrate: palletAddress,422 },430 },431 await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.fulfilled;439 await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.fulfilled;432 440 433 // Contract is self sponsored441 // Contract is self sponsored434 expect((await helper.api!.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.be.deep.equal({442 expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.be.deep.equal({435 confirmed: {443 confirmed: {436 ethereum: flipper.options.address.toLowerCase(),444 ethereum: flipper.options.address.toLowerCase(),437 },445 },462 await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;470 await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;463 471 464 expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; 472 expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; 465 expect((await helper.api!.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); 473 expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); 466 expect((await helper.api!.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({474 expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({467 confirmed: {475 confirmed: {468 ethereum: flipper.options.address.toLowerCase(),476 ethereum: flipper.options.address.toLowerCase(),469 },477 },482 await expect(helper.executeExtrinsic(nonAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true)).to.be.rejectedWith('appPromotion.NoPermission');490 await expect(helper.executeExtrinsic(nonAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true)).to.be.rejectedWith('appPromotion.NoPermission');483 491 484 // contract still self-sponsored 492 // contract still self-sponsored 485 expect((await helper.api!.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({493 expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({486 confirmed: {494 confirmed: {487 ethereum: flipper.options.address.toLowerCase(),495 ethereum: flipper.options.address.toLowerCase(),488 },496 },505 await helper.eth.transferBalanceFromSubstrate(alice, flipper.options.address, 1000n); // transferBalanceToEth(api, alice, flipper.options.address, 1000n);513 await helper.eth.transferBalanceFromSubstrate(alice, flipper.options.address, 1000n); // transferBalanceToEth(api, alice, flipper.options.address, 1000n);506 514 507 // Set promotion to the Flipper515 // Set promotion to the Flipper508 await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorContract(flipper.options.address));516 await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true);509 517 510 // Caller calls Flipper518 // Caller calls Flipper511 await flipper.methods.flip().send({from: caller});519 await flipper.methods.flip().send({from: caller});536 await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.stopSponsoringContract', [flipper.options.address], true);544 await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.stopSponsoringContract', [flipper.options.address], true);537 545 538 expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false; 546 expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false; 539 expect((await helper.api!.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); 547 expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); 540 expect((await helper.api!.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({548 expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({541 disabled: null,549 disabled: null,542 });550 });543 551 717// Wait while promotion period less than specified block, to avoid boundary cases725// Wait while promotion period less than specified block, to avoid boundary cases718// 0 if this should be the beginning of the period.726// 0 if this should be the beginning of the period.719async function waitPromotionPeriodDoesntEnd(helper: DevUniqueHelper, waitBlockLessThan = LOCKING_PERIOD / 3n) {727async function waitPromotionPeriodDoesntEnd(helper: DevUniqueHelper, waitBlockLessThan = LOCKING_PERIOD / 3n) {720 const relayBlockNumber = (await helper.api!.query.parachainSystem.validationData()).value.relayParentNumber.toNumber(); // await helper.chain.getLatestBlockNumber();728 const relayBlockNumber = (await helper.callRpc('api.query.parachainSystem.validationData', [])).value.relayParentNumber.toNumber(); // await helper.chain.getLatestBlockNumber();721 const currentPeriodBlock = BigInt(relayBlockNumber) % LOCKING_PERIOD;729 const currentPeriodBlock = BigInt(relayBlockNumber) % LOCKING_PERIOD;722730723 if (currentPeriodBlock > waitBlockLessThan) {731 if (currentPeriodBlock > waitBlockLessThan) {tests/src/approve.test.tsdiffbeforeafterboth60 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});60 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});61 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});61 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});62 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;62 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;63 await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));63 await helper.signTransaction(alice, helper.constructApiCall('api.tx.unique.approve', [{Substrate: bob.address}, collectionId, tokenId, 0]));64 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;64 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;65 });65 });6666275 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});275 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address});276 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});276 await helper.nft.approveToken(alice, collectionId, tokenId, {Substrate: bob.address});277 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;277 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.true;278 await helper.signTransaction(alice, helper.api?.tx.unique.approve({Substrate: bob.address}, collectionId, tokenId, 0));278 await helper.signTransaction(alice, helper.constructApiCall('api.tx.unique.approve', [{Substrate: bob.address}, collectionId, tokenId, 0]));279 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;279 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: bob.address})).to.be.false;280 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});280 const transferTokenFromTx = async () => helper.nft.transferTokenFrom(bob, collectionId, tokenId, {Substrate: bob.address}, {Substrate: bob.address});281 await expect(transferTokenFromTx()).to.be.rejected;281 await expect(transferTokenFromTx()).to.be.rejected;328 itSub('1 for NFT', async ({helper}) => {328 itSub('1 for NFT', async ({helper}) => {329 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});329 const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});330 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});330 const {tokenId} = await helper.nft.mintToken(alice, {collectionId: collectionId, owner: bob.address});331 const approveTx = async () => helper.signTransaction(bob, helper.api?.tx.unique.approve({Substrate: charlie.address}, collectionId, tokenId, 2));331 const approveTx = async () => helper.signTransaction(bob, helper.constructApiCall('api.tx.unique.approve', [{Substrate: charlie.address}, collectionId, tokenId, 2]));332 await expect(approveTx()).to.be.rejected;332 await expect(approveTx()).to.be.rejected;333 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;333 expect(await helper.nft.isTokenApproved(collectionId, tokenId, {Substrate: charlie.address})).to.be.false;334 });334 });tests/src/balance-transfer-contract/calls.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/balance-transfer-contract/metadata.jsondiffbeforeafterbothno changes
tests/src/block-production.test.tsdiffbeforeafterboth373738describe('Block Production smoke test', () => {38describe('Block Production smoke test', () => {39 itSub('Node produces new blocks', async ({helper}) => {39 itSub('Node produces new blocks', async ({helper}) => {40 const blocks: number[] | undefined = await getBlocks(helper.api!);40 const blocks: number[] | undefined = await getBlocks(helper.getApi());41 expect(blocks[0]).to.be.lessThan(blocks[1]);41 expect(blocks[0]).to.be.lessThan(blocks[1]);42 });42 });43});43});tests/src/calibrate.tsdiffbeforeafterboth1import {ApiPromise} from '@polkadot/api';2import {IKeyringPair} from '@polkadot/types/types';1import {IKeyringPair} from '@polkadot/types/types';3import Web3 from 'web3';24import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, recordEthFee, usingWeb3} from './eth/util/helpers';3import {usingEthPlaygrounds, EthUniqueHelper} from './eth/util/playgrounds';5import usingApi, {executeTransaction} from './substrate/substrate-api';46import {createCollectionExpectSuccess, createItemExpectSuccess, transferExpectSuccess, UNIQUE, waitNewBlocks} from './util/helpers';7import nonFungibleAbi from './eth/nonFungibleAbi.json';859function linearRegression(points: { x: bigint, y: bigint }[]) {6function linearRegression(points: { x: bigint, y: bigint }[]) {10 let sumxy = 0n;7 let sumxy = 0n;59 }).reduce((a, b) => a + b, 0n) / BigInt(points.length));56 }).reduce((a, b) => a + b, 0n) / BigInt(points.length));60}57}615862async function calibrateWeightToFee(api: ApiPromise, privateKey: (account: string) => IKeyringPair) {59async function calibrateWeightToFee(helper: EthUniqueHelper, privateKey: (account: string) => IKeyringPair) {63 const alice = privateKey('//Alice');60 const alice = privateKey('//Alice');64 const bob = privateKey('//Bob');61 const bob = privateKey('//Bob');65 const dataPoints = [];62 const dataPoints = [];666367 {64 {68 const collectionId = await createCollectionExpectSuccess();65 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});69 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');66 const token = await collection.mintToken(alice, {Substrate: alice.address});70 const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();67 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);71 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');68 await token.transfer(alice, {Substrate: bob.address});72 const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();69 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);737074 console.log(`Original price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE)} UNQ`);71 console.log(`Original price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal())} UNQ`);75 }72 }767374 const api = helper.getApi();77 const defaultCoeff = (api.consts.configuration.defaultWeightToFeeCoefficient as any).toBigInt();75 const defaultCoeff = (api.consts.configuration.defaultWeightToFeeCoefficient as any).toBigInt();78 for (let i = -5; i < 5; i++) {76 for (let i = -5; i < 5; i++) {79 await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(defaultCoeff + defaultCoeff / 1000n * BigInt(i))));77 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(defaultCoeff + defaultCoeff / 1000n * BigInt(i))));807881 const coefficient = (await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt();79 const coefficient = (await api.query.configuration.weightToFeeCoefficientOverride() as any).toBigInt();82 const collectionId = await createCollectionExpectSuccess();80 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});83 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');81 const token = await collection.mintToken(alice, {Substrate: alice.address});848285 const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();83 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);86 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');84 await token.transfer(alice, {Substrate: bob.address});87 const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();85 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);888689 const transferPrice = aliceBalanceBefore - aliceBalanceAfter;87 const transferPrice = aliceBalanceBefore - aliceBalanceAfter;9088949295 // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);93 // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);969497 const perfectValue = a * UNIQUE / 10n + b;95 const perfectValue = a * helper.balance.getOneTokenNominal() / 10n + b;98 await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(perfectValue.toString())));96 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setWeightToFeeCoefficientOverride(perfectValue.toString())));9997100 {98 {101 const collectionId = await createCollectionExpectSuccess();99 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});102 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');100 const token = await collection.mintToken(alice, {Substrate: alice.address});103 const aliceBalanceBefore = (await api.query.system.account(alice.address)).data.free.toBigInt();101 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);104 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');102 await token.transfer(alice, {Substrate: bob.address});105 const aliceBalanceAfter = (await api.query.system.account(alice.address)).data.free.toBigInt();103 const aliceBalanceAfter = await helper.balance.getSubstrate(alice.address);106104107 console.log(`Calibrated price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE)} UNQ`);105 console.log(`Calibrated price: ${Number(aliceBalanceBefore - aliceBalanceAfter) / Number(helper.balance.getOneTokenNominal())} UNQ`);108 }106 }109}107}110108111async function calibrateMinGasPrice(api: ApiPromise, web3: Web3, privateKey: (account: string) => IKeyringPair) {109async function calibrateMinGasPrice(helper: EthUniqueHelper, privateKey: (account: string) => IKeyringPair) {112 const alice = privateKey('//Alice');110 const alice = privateKey('//Alice');113 const caller = await createEthAccountWithBalance(api, web3, privateKey);111 const caller = await helper.eth.createAccountWithBalance(alice);114 const receiver = createEthAccount(web3);112 const receiver = helper.eth.createAccount();115 const dataPoints = [];113 const dataPoints = [];116114117 {115 {118 const collectionId = await createCollectionExpectSuccess();116 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});119 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Ethereum: caller});117 const token = await collection.mintToken(alice, {Ethereum: caller});120118121 const address = collectionIdToAddress(collectionId);119 const address = helper.ethAddress.fromCollectionId(collection.collectionId);122 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});120 const contract = helper.ethNativeContract.collection(address, 'nft', caller);123121124 const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));122 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS}));125123126 console.log(`Original price: ${Number(cost) / Number(UNIQUE)} UNQ`);124 console.log(`Original price: ${Number(cost) / Number(helper.balance.getOneTokenNominal())} UNQ`);127 }125 }128126127 const api = helper.getApi();129 const defaultCoeff = (api.consts.configuration.defaultMinGasPrice as any).toBigInt();128 const defaultCoeff = (api.consts.configuration.defaultMinGasPrice as any).toBigInt();130 for (let i = -8; i < 8; i++) {129 for (let i = -8; i < 8; i++) {131 const gasPrice = defaultCoeff + defaultCoeff / 100000n * BigInt(i);130 const gasPrice = defaultCoeff + defaultCoeff / 100000n * BigInt(i);132 const gasPriceStr = '0x' + gasPrice.toString(16);131 const gasPriceStr = '0x' + gasPrice.toString(16);133 await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(gasPrice)));132 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(gasPrice)));134133135 const coefficient = (await api.query.configuration.minGasPriceOverride() as any).toBigInt();134 const coefficient = (await api.query.configuration.minGasPriceOverride() as any).toBigInt();136 const collectionId = await createCollectionExpectSuccess();135 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});137 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Ethereum: caller});136 const token = await collection.mintToken(alice, {Ethereum: caller});138137139 const address = collectionIdToAddress(collectionId);138 const address = helper.ethAddress.fromCollectionId(collection.collectionId);140 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, gasPrice: gasPriceStr, ...GAS_ARGS});139 const contract = helper.ethNativeContract.collection(address, 'nft', caller);141140142 const transferPrice = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));141 const transferPrice = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gasPrice: gasPriceStr, gas: helper.eth.DEFAULT_GAS}));143142144 dataPoints.push({x: transferPrice, y: coefficient});143 dataPoints.push({x: transferPrice, y: coefficient});145 }144 }149 // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);148 // console.log(`Error: ${error(dataPoints, x => a*x+b)}`);150149151 // * 0.15 = * 10000 / 66666150 // * 0.15 = * 10000 / 66666152 const perfectValue = a * UNIQUE * 1000000n / 6666666n + b;151 const perfectValue = a * helper.balance.getOneTokenNominal() * 1000000n / 6666666n + b;153 await executeTransaction(api, alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(perfectValue.toString())));152 await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setMinGasPriceOverride(perfectValue.toString())));154153155 {154 {156 const collectionId = await createCollectionExpectSuccess();155 const collection = await helper.nft.mintCollection(alice, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});157 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', {Ethereum: caller});156 const token = await collection.mintToken(alice, {Ethereum: caller});158157159 const address = collectionIdToAddress(collectionId);158 const address = helper.ethAddress.fromCollectionId(collection.collectionId);160 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});159 const contract = helper.ethNativeContract.collection(address, 'nft', caller);161160162 const cost = await recordEthFee(api, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));161 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS}));163162164 console.log(`Calibrated price: ${Number(cost) / Number(UNIQUE)} UNQ`);163 console.log(`Calibrated price: ${Number(cost) / Number(helper.balance.getOneTokenNominal())} UNQ`);165 }164 }166}165}167166168(async () => {167(async () => {169 await usingApi(async (api, privateKey) => {168 await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => {170 // Second run slightly reduces error sometimes, as price line is not actually straight, this is a curve169 // Second run slightly reduces error sometimes, as price line is not actually straight, this is a curve171170172 await calibrateWeightToFee(api, privateKey);171 await calibrateWeightToFee(helper, privateKey);173 await calibrateWeightToFee(api, privateKey);172 await calibrateWeightToFee(helper, privateKey);174173175 await usingWeb3(async web3 => {174 await calibrateMinGasPrice(helper, privateKey);176 await calibrateMinGasPrice(api, web3, privateKey);177 await calibrateMinGasPrice(api, web3, privateKey);178 });179180 await api.disconnect();175 await calibrateMinGasPrice(helper, privateKey);181 });176 });182})();177})();183178tests/src/collision-tests/admVsOwnerChanges.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/admVsOwnerData.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/admVsOwnerTake.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/adminDestroyCollection.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/adminLimitsOff.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/adminRightsOff.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/setSponsorNewOwner.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/sponsorPayments.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/tokenLimitsOff.test.tsdiffbeforeafterbothno changes
tests/src/collision-tests/turnsOffMinting.test.tsdiffbeforeafterbothno changes
tests/src/contracts.test.tsdiffbeforeafterbothno changes
tests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth178 tokenPrefix: 'COL',178 tokenPrefix: 'COL',179 }, 0);179 }, 0);180180181 const api = helper.api;182 await helper.signTransaction(alice, api?.tx.unique.createMultipleItemsEx(collection.collectionId, {181 await helper.executeExtrinsic(alice, 'api.tx.unique.createMultipleItemsEx',[collection.collectionId, {183 Fungible: new Map([182 Fungible: new Map([184 [JSON.stringify({Substrate: alice.address}), 50],183 [JSON.stringify({Substrate: alice.address}), 50],185 [JSON.stringify({Substrate: bob.address}), 100],184 [JSON.stringify({Substrate: bob.address}), 100],186 ]),185 ]),187 }));186 }], true);188187189 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(50n);188 expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(50n);190 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(100n);189 expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(100n);200 ],199 ],201 });200 });202201203 const api = helper.api;204 await helper.signTransaction(alice, api?.tx.unique.createMultipleItemsEx(collection.collectionId, {202 await helper.executeExtrinsic(alice, 'api.tx.unique.createMultipleItemsEx', [collection.collectionId, {205 RefungibleMultipleOwners: {203 RefungibleMultipleOwners: {206 users: new Map([204 users: new Map([207 [JSON.stringify({Substrate: alice.address}), 1],205 [JSON.stringify({Substrate: alice.address}), 1],211 {key: 'k', value: 'v'},209 {key: 'k', value: 'v'},212 ],210 ],213 },211 },214 }));212 }], true);215 const tokenId = await collection.getLastTokenId();213 const tokenId = await collection.getLastTokenId();216 expect(tokenId).to.be.equal(1);214 expect(tokenId).to.be.equal(1);217 expect(await collection.getTokenBalance(1, {Substrate: alice.address})).to.be.equal(1n);215 expect(await collection.getTokenBalance(1, {Substrate: alice.address})).to.be.equal(1n);228 ],226 ],229 });227 });230231 const api = helper.api;232228233 await helper.signTransaction(alice, api?.tx.unique.createMultipleItemsEx(collection.collectionId, {229 await helper.executeExtrinsic(alice, 'api.tx.unique.createMultipleItemsEx', [collection.collectionId, {234 RefungibleMultipleItems: [230 RefungibleMultipleItems: [235 {231 {236 user: {Substrate: alice.address}, pieces: 1,232 user: {Substrate: alice.address}, pieces: 1,245 ],241 ],246 },242 },247 ],243 ],248 }));244 }], true);249245250 expect(await collection.getLastTokenId()).to.be.equal(2);246 expect(await collection.getLastTokenId()).to.be.equal(2);251 expect(await collection.getTokenBalance(1, {Substrate: alice.address})).to.be.equal(1n);247 expect(await collection.getTokenBalance(1, {Substrate: alice.address})).to.be.equal(1n);tests/src/creditFeesToTreasury.test.tsdiffbeforeafterboth29/*eslint no-async-promise-executor: "off"*/29/*eslint no-async-promise-executor: "off"*/30function skipInflationBlock(api: ApiPromise): Promise<void> {30function skipInflationBlock(api: ApiPromise): Promise<void> {31 const promise = new Promise<void>(async (resolve) => {31 const promise = new Promise<void>(async (resolve) => {32 const blockInterval = (await api.consts.inflation.inflationBlockInterval).toNumber();32 const blockInterval = api.consts.inflation.inflationBlockInterval.toNumber();33 const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {33 const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {34 const currentBlock = head.number.toNumber();34 const currentBlock = head.number.toNumber();35 if (currentBlock % blockInterval < blockInterval - 10) {35 if (currentBlock % blockInterval < blockInterval - 10) {56 });56 });575758 itSub('Total issuance does not change', async ({helper}) => {58 itSub('Total issuance does not change', async ({helper}) => {59 const api = helper.api!;59 const api = helper.getApi();60 await skipInflationBlock(api);60 await skipInflationBlock(api);61 await helper.wait.newBlocks(1);61 await helper.wait.newBlocks(1);626263 const totalBefore = (await api.query.balances.totalIssuance()).toBigInt();63 const totalBefore = (await helper.callRpc('api.query.balances.totalIssuance', [])).toBigInt();646465 await helper.balance.transferToSubstrate(alice, bob.address, 1n);65 await helper.balance.transferToSubstrate(alice, bob.address, 1n);666667 const totalAfter = (await api.query.balances.totalIssuance()).toBigInt();67 const totalAfter = (await helper.callRpc('api.query.balances.totalIssuance', [])).toBigInt();686869 expect(totalAfter).to.be.equal(totalBefore);69 expect(totalAfter).to.be.equal(totalBefore);70 });70 });717172 itSub('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async ({helper}) => {72 itSub('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async ({helper}) => {73 await skipInflationBlock(helper.api!);73 await skipInflationBlock(helper.getApi());74 await helper.wait.newBlocks(1);74 await helper.wait.newBlocks(1);757576 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);76 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);89 });89 });909091 itSub('Treasury balance increased by failed tx fee', async ({helper}) => {91 itSub('Treasury balance increased by failed tx fee', async ({helper}) => {92 const api = helper.api!;92 const api = helper.getApi();93 await helper.wait.newBlocks(1);93 await helper.wait.newBlocks(1);949495 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);95 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);107 });107 });108108109 itSub('NFT Transactions also send fees to Treasury', async ({helper}) => {109 itSub('NFT Transactions also send fees to Treasury', async ({helper}) => {110 await skipInflationBlock(helper.api!);110 await skipInflationBlock(helper.getApi());111 await helper.wait.newBlocks(1);111 await helper.wait.newBlocks(1);112112113 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);113 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);125125126 itSub('Fees are sane', async ({helper}) => {126 itSub('Fees are sane', async ({helper}) => {127 const unique = helper.balance.getOneTokenNominal();127 const unique = helper.balance.getOneTokenNominal();128 await skipInflationBlock(helper.api!);128 await skipInflationBlock(helper.getApi());129 await helper.wait.newBlocks(1);129 await helper.wait.newBlocks(1);130130131 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);131 const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address);140 });140 });141141142 itSub('NFT Transfer fee is close to 0.1 Unique', async ({helper}) => {142 itSub('NFT Transfer fee is close to 0.1 Unique', async ({helper}) => {143 await skipInflationBlock(helper.api!);143 await skipInflationBlock(helper.getApi());144 await helper.wait.newBlocks(1);144 await helper.wait.newBlocks(1);145145146 const collection = await helper.nft.mintCollection(alice, {146 const collection = await helper.nft.mintCollection(alice, {tests/src/deprecated-helpers/contracthelpers.tsdiffbeforeafterbothno changes
tests/src/deprecated-helpers/eth/helpers.d.tsdiffbeforeafterbothno changes
tests/src/deprecated-helpers/eth/helpers.tsdiffbeforeafterbothno changes
tests/src/deprecated-helpers/helpers.tsdiffbeforeafterbothno changes
tests/src/deprecated-helpers/util.tsdiffbeforeafterbothno changes
tests/src/enableContractSponsoring.test.tsdiffbeforeafterbothno changes
tests/src/eth/base.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/>.161617import {18 ethBalanceViaSub,19 GAS_ARGS,20 recordEthFee,21} from './util/helpers';22import {Contract} from 'web3-eth-contract';17import {Contract} from 'web3-eth-contract';231824import {IKeyringPair} from '@polkadot/types/types';19import {IKeyringPair} from '@polkadot/types/types';37 const deployer = await helper.eth.createAccountWithBalance(donor);33 const deployer = await helper.eth.createAccountWithBalance(donor);38 const flipper = await helper.eth.deployFlipper(deployer);34 const flipper = await helper.eth.deployFlipper(deployer);393540 const cost = await recordEthFee(helper.api!, deployer, () => flipper.methods.flip().send({from: deployer}));36 const cost = await helper.eth.calculateFee({Ethereum: deployer}, () => flipper.methods.flip().send({from: deployer}));41 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))).to.be.true;37 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))).to.be.true;42 });38 });433944 itEth('Balance transfer fee is less than 0.2 UNQ', async ({helper}) => {40 itEth('Balance transfer fee is less than 0.2 UNQ', async ({helper}) => {45 const userA = await helper.eth.createAccountWithBalance(donor);41 const userA = await helper.eth.createAccountWithBalance(donor);46 const userB = helper.eth.createAccount();42 const userB = helper.eth.createAccount();47 const cost = await recordEthFee(helper.api!, userA, () => helper.web3!.eth.sendTransaction({from: userA, to: userB, value: '1000000', ...GAS_ARGS}));43 const cost = await helper.eth.calculateFee({Ethereum: userA}, () => helper.getWeb3().eth.sendTransaction({from: userA, to: userB, value: '1000000', gas: helper.eth.DEFAULT_GAS}));48 const balanceB = await ethBalanceViaSub(helper.api!, userB);44 const balanceB = await helper.balance.getEthereum(userB);49 expect(cost - balanceB < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))).to.be.true;45 expect(cost - balanceB < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))).to.be.true;50 });46 });514760 const address = helper.ethAddress.fromCollectionId(collection.collectionId);56 const address = helper.ethAddress.fromCollectionId(collection.collectionId);61 const contract = helper.ethNativeContract.collection(address, 'nft', caller);57 const contract = helper.ethNativeContract.collection(address, 'nft', caller);625863 const cost = await recordEthFee(helper.api!, caller, () => contract.methods.transfer(receiver, tokenId).send(caller));59 const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, tokenId).send(caller));646065 const fee = Number(cost) / Number(helper.balance.getOneTokenNominal());61 const fee = Number(cost) / Number(helper.balance.getOneTokenNominal());66 const expectedFee = 0.15;62 const expectedFee = 0.15;tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth1import {addToAllowListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, enablePublicMintingExpectSuccess, getDetailedCollectionInfo, setCollectionSponsorExpectSuccess, UNIQUE} from '../util/helpers';1import {IKeyringPair} from '@polkadot/types/types';2import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub} from './util/helpers';2import {usingPlaygrounds} from './../util/playgrounds/index';3import nonFungibleAbi from './nonFungibleAbi.json';4import {expect} from 'chai';3import {itEth, expect} from '../eth/util/playgrounds';5import {evmToAddress} from '@polkadot/util-crypto';647describe('evm collection sponsoring', () => {5describe('evm collection sponsoring', () => {8 itWeb3('sponsors mint transactions', async ({web3, privateKeyWrapper}) => {6 let donor: IKeyringPair;7 let alice: IKeyringPair;9 const alice = privateKeyWrapper('//Alice');8 let nominal: bigint;10911 const collection = await createCollectionExpectSuccess();10 before(async () => {11 await usingPlaygrounds(async (helper, privateKey) => {12 await setCollectionSponsorExpectSuccess(collection, alice.address);12 donor = privateKey('//Alice');13 nominal = helper.balance.getOneTokenNominal();13 await confirmSponsorshipExpectSuccess(collection);14 });15 });141615 const minter = createEthAccount(web3);17 beforeEach(async () => {18 await usingPlaygrounds(async (helper) => {16 expect(await web3.eth.getBalance(minter)).to.equal('0');19 [alice] = await helper.arrange.createAccounts([1000n], donor);20 });21 });172218 const address = collectionIdToAddress(collection);23 itEth('sponsors mint transactions', async ({helper}) => {19 const contract = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collection), {from: minter, ...GAS_ARGS});24 const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}});25 await collection.setSponsor(alice, alice.address);26 await collection.confirmSponsorship(alice);202721 await enablePublicMintingExpectSuccess(alice, collection);28 const minter = helper.eth.createAccount();22 await addToAllowListExpectSuccess(alice, collection, {Ethereum: minter});29 expect(await helper.balance.getEthereum(minter)).to.equal(0n);233031 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);32 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', minter);3334 await collection.addToAllowList(alice, {Ethereum: minter});3524 const nextTokenId = await contract.methods.nextTokenId().call();36 const nextTokenId = await contract.methods.nextTokenId().call();25 expect(nextTokenId).to.equal('1');37 expect(nextTokenId).to.equal('1');26 const result = await contract.methods.mint(minter, nextTokenId).send();38 const result = await contract.methods.mint(minter, nextTokenId).send();27 const events = normalizeEvents(result.events);39 const events = helper.eth.normalizeEvents(result.events);28 expect(events).to.be.deep.equal([40 expect(events).to.be.deep.equal([29 {41 {30 address,42 address: collectionAddress,31 event: 'Transfer',43 event: 'Transfer',32 args: {44 args: {33 from: '0x0000000000000000000000000000000000000000',45 from: '0x0000000000000000000000000000000000000000',59 // expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);71 // expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);60 // });72 // });617362 itWeb3('Remove sponsor', async ({api, web3, privateKeyWrapper}) => {74 itEth('Remove sponsor', async ({helper}) => {63 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);75 const owner = await helper.eth.createAccountWithBalance(donor);64 const collectionHelpers = evmCollectionHelpers(web3, owner);76 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);65 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});66 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);67 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);68 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);697778 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});79 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);80 const sponsor = await helper.eth.createAccountWithBalance(donor);81 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);8270 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;83 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;71 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});84 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});72 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;85 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;80 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');93 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');81 });94 });829583 itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {96 itEth('Sponsoring collection from evm address via access list', async ({helper}) => {84 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);97 const owner = await helper.eth.createAccountWithBalance(donor);85 const collectionHelpers = evmCollectionHelpers(web3, owner);98 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);9986 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});100 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});87 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);101 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);102 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);103 const collection = helper.nft.getCollectionObject(collectionId);88 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const sponsor = await helper.eth.createAccountWithBalance(donor);89 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);105 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);10690 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});107 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});91 let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;108 let collectionData = (await collection.getData())!;92 const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;93 expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;109 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));94 expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));95 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');110 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');9611197 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});112 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});98 collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;113 collectionData = (await collection.getData())!;99 expect(collectionSub.sponsorship.isConfirmed).to.be.true;114 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));100 expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));101115102 const user = createEthAccount(web3);116 const user = helper.eth.createAccount();103 const nextTokenId = await collectionEvm.methods.nextTokenId().call();117 const nextTokenId = await collectionEvm.methods.nextTokenId().call();104 expect(nextTokenId).to.be.equal('1');118 expect(nextTokenId).to.be.equal('1');105119106 const oldPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();120 const oldPermissions = (await collection.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();107 expect(oldPermissions.mintMode).to.be.false;121 expect(oldPermissions.mintMode).to.be.false;108 expect(oldPermissions.access).to.be.equal('Normal');122 expect(oldPermissions.access).to.be.equal('Normal');109123110 await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});124 await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});111 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});125 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});112 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});126 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});113127114 const newPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();128 const newPermissions = (await collection.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();115 expect(newPermissions.mintMode).to.be.true;129 expect(newPermissions.mintMode).to.be.true;116 expect(newPermissions.access).to.be.equal('AllowList');130 expect(newPermissions.access).to.be.equal('AllowList');117131118 const ownerBalanceBefore = await ethBalanceViaSub(api, owner);132 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));119 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);133 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));120134121 {135 {122 const nextTokenId = await collectionEvm.methods.nextTokenId().call();136 const nextTokenId = await collectionEvm.methods.nextTokenId().call();126 nextTokenId,140 nextTokenId,127 'Test URI',141 'Test URI',128 ).send({from: user});142 ).send({from: user});129 const events = normalizeEvents(result.events);143 const events = helper.eth.normalizeEvents(result.events);130144131 expect(events).to.be.deep.equal([145 expect(events).to.be.deep.equal([132 {146 {140 },154 },141 ]);155 ]);142156143 const ownerBalanceAfter = await ethBalanceViaSub(api, owner);157 const ownerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(owner));144 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);158 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));145159146 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');160 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');147 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);161 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);205 // }219 // }206 // });220 // });207221208 itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {222 itEth('Check that transaction via EVM spend money from sponsor address', async ({helper}) => {209 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);223 const owner = await helper.eth.createAccountWithBalance(donor);210 const collectionHelpers = evmCollectionHelpers(web3, owner);224 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);225211 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});226 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});212 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);227 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);228 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);229 const collection = helper.nft.getCollectionObject(collectionId);213 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);230 const sponsor = await helper.eth.createAccountWithBalance(donor);214 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);231 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);232215 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();233 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();216 let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;234 let collectionData = (await collection.getData())!;217 const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;218 expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;235 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));219 expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));220 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');236 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');237221 const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);238 const sponsorCollection = helper.ethNativeContract.collection(collectionIdAddress, 'nft', sponsor);222 await sponsorCollection.methods.confirmCollectionSponsorship().send();239 await sponsorCollection.methods.confirmCollectionSponsorship().send();223 collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;240 collectionData = (await collection.getData())!;224 expect(collectionSub.sponsorship.isConfirmed).to.be.true;241 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));225 expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));226242227 const user = createEthAccount(web3);243 const user = helper.eth.createAccount();228 await collectionEvm.methods.addCollectionAdmin(user).send();244 await collectionEvm.methods.addCollectionAdmin(user).send();229 245 230 const ownerBalanceBefore = await ethBalanceViaSub(api, owner);246 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));231 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);247 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));232 248233 249 const userCollectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', user);234 const userCollectionEvm = evmCollection(web3, user, collectionIdAddress);235 const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();250 const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();236 expect(nextTokenId).to.be.equal('1');251 expect(nextTokenId).to.be.equal('1');237 result = await userCollectionEvm.methods.mintWithTokenURI(252 result = await userCollectionEvm.methods.mintWithTokenURI(240 'Test URI',255 'Test URI',241 ).send();256 ).send();242257243 const events = normalizeEvents(result.events);258 const events = helper.eth.normalizeEvents(result.events);244 const address = collectionIdToAddress(collectionId);259 const address = helper.ethAddress.fromCollectionId(collectionId);245260246 expect(events).to.be.deep.equal([261 expect(events).to.be.deep.equal([247 {262 {256 ]);271 ]);257 expect(await userCollectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');272 expect(await userCollectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');258 273 259 const ownerBalanceAfter = await ethBalanceViaSub(api, owner);274 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));260 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);275 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);261 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);276 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));262 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;277 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;263 });278 });264});279});tests/src/eth/contractSponsoring.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/>.161617import {IKeyringPair} from '@polkadot/types/types';17import * as solc from 'solc';18import * as solc from 'solc';18import {expect} from 'chai';19import {EthUniqueHelper} from './util/playgrounds/unique.dev';20import {itEth, expect, SponsoringMode, usingEthPlaygrounds} from '../eth/util/playgrounds';19import {expectSubstrateEventsAtBlock} from '../util/helpers';21import {usingPlaygrounds} from '../util/playgrounds';20import Web3 from 'web3';22import {CompiledContract} from './util/playgrounds/types';212322import {24describe('Sponsoring EVM contracts', () => {23 contractHelpers,24 createEthAccountWithBalance,25 transferBalanceToEth,26 deployFlipper,25 let donor: IKeyringPair;27 itWeb3,28 SponsoringMode,29 createEthAccount,30 ethBalanceViaSub,31 normalizeEvents,32 CompiledContract,33 GAS_ARGS,34 subToEth,35} from './util/helpers';36import {submitTransactionAsync} from '../substrate/substrate-api';372638describe('Sponsoring EVM contracts', () => {27 before(async () => {28 await usingPlaygrounds(async (_helper, privateKey) => {39 itWeb3('Self sponsored can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {29 donor = privateKey('//Alice');30 });31 });3233 itEth('Self sponsored can be set by the address that deployed the contract', async ({helper, privateKey}) => {40 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);34 const owner = await helper.eth.createAccountWithBalance(donor);41 const flipper = await deployFlipper(web3, owner);35 const flipper = await helper.eth.deployFlipper(owner);42 const helpers = contractHelpers(web3, owner);36 const helpers = helper.ethNativeContract.contractHelpers(owner);3743 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;38 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;44 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;39 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;45 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;40 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;46 });41 });474248 itWeb3('Set self sponsored events', async ({api, web3, privateKeyWrapper}) => {43 itEth('Set self sponsored events', async ({helper}) => {49 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);44 const owner = await helper.eth.createAccountWithBalance(donor);50 const flipper = await deployFlipper(web3, owner);45 const flipper = await helper.eth.deployFlipper(owner);51 const helpers = contractHelpers(web3, owner);46 const helpers = helper.ethNativeContract.contractHelpers(owner);52 47 53 const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send();48 const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send();54 // console.log(result);49 const ethEvents = helper.eth.helper.eth.normalizeEvents(result.events);55 const ethEvents = normalizeEvents(result.events);56 expect(ethEvents).to.be.deep.equal([50 expect(ethEvents).to.be.deep.equal([57 {51 {58 address: flipper.options.address,52 address: flipper.options.address,71 },65 },72 },66 },73 ]);67 ]);7475 await expectSubstrateEventsAtBlock(76 api, 77 result.blockNumber,78 'evmContractHelpers',79 ['ContractSponsorSet','ContractSponsorshipConfirmed'],80 );81 });68 });826983 itWeb3('Self sponsored can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {70 itEth('Self sponsored can not be set by the address that did not deployed the contract', async ({helper}) => {84 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);71 const owner = await helper.eth.createAccountWithBalance(donor);85 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);72 const notOwner = await helper.eth.createAccountWithBalance(donor);86 const flipper = await deployFlipper(web3, owner);73 const helpers = helper.ethNativeContract.contractHelpers(owner);87 const helpers = contractHelpers(web3, owner);74 const flipper = await helper.eth.deployFlipper(owner);7588 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;76 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;89 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');77 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');90 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;78 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;91 });79 });928093 itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {81 itEth('Sponsoring can be set by the address that has deployed the contract', async ({helper}) => {94 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);82 const owner = await helper.eth.createAccountWithBalance(donor);95 const flipper = await deployFlipper(web3, owner);83 const helpers = helper.ethNativeContract.contractHelpers(owner);96 const helpers = contractHelpers(web3, owner);84 const flipper = await helper.eth.deployFlipper(owner);8597 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;86 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;98 await expect(helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner})).to.be.not.rejected;87 await expect(helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner})).to.be.not.rejected;99 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;88 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;100 });89 });10190102 itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {91 itEth('Sponsoring cannot be set by the address that did not deployed the contract', async ({helper}) => {103 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);92 const owner = await helper.eth.createAccountWithBalance(donor);104 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);93 const notOwner = await helper.eth.createAccountWithBalance(donor);105 const flipper = await deployFlipper(web3, owner);94 const helpers = helper.ethNativeContract.contractHelpers(owner);106 const helpers = contractHelpers(web3, owner);95 const flipper = await helper.eth.deployFlipper(owner);96107 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;97 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;108 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');98 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');109 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;99 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;110 });100 });111 101 112 itWeb3('Sponsor can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {102 itEth('Sponsor can be set by the address that deployed the contract', async ({helper}) => {113 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);103 const owner = await helper.eth.createAccountWithBalance(donor);114 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const sponsor = await helper.eth.createAccountWithBalance(donor);115 const flipper = await deployFlipper(web3, owner);105 const helpers = helper.ethNativeContract.contractHelpers(owner);116 const helpers = contractHelpers(web3, owner);106 const flipper = await helper.eth.deployFlipper(owner);107117 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;108 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;118 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;109 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;119 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;110 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;120 });111 });121 112 122 itWeb3('Set sponsor event', async ({api, web3, privateKeyWrapper}) => {113 itEth('Set sponsor event', async ({helper}) => {123 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);114 const owner = await helper.eth.createAccountWithBalance(donor);124 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);115 const sponsor = await helper.eth.createAccountWithBalance(donor);125 const flipper = await deployFlipper(web3, owner);116 const helpers = helper.ethNativeContract.contractHelpers(owner);126 const helpers = contractHelpers(web3, owner);117 const flipper = await helper.eth.deployFlipper(owner);127 118 128 const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();119 const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();129 const events = normalizeEvents(result.events);120 const events = helper.eth.normalizeEvents(result.events);130 expect(events).to.be.deep.equal([121 expect(events).to.be.deep.equal([131 {122 {132 address: flipper.options.address,123 address: flipper.options.address,137 },128 },138 },129 },139 ]);130 ]);140141 await expectSubstrateEventsAtBlock(142 api, 143 result.blockNumber,144 'evmContractHelpers',145 ['ContractSponsorSet'],146 );147 });131 });148 132 149 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {133 itEth('Sponsor can not be set by the address that did not deployed the contract', async ({helper}) => {150 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);134 const owner = await helper.eth.createAccountWithBalance(donor);151 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);135 const sponsor = await helper.eth.createAccountWithBalance(donor);152 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);136 const notOwner = await helper.eth.createAccountWithBalance(donor);153 const flipper = await deployFlipper(web3, owner);137 const helpers = helper.ethNativeContract.contractHelpers(owner);154 const helpers = contractHelpers(web3, owner);138 const flipper = await helper.eth.deployFlipper(owner);139155 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;140 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;156 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');141 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');157 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;142 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;158 });143 });159144160 itWeb3('Sponsorship can be confirmed by the address that pending as sponsor', async ({api, web3, privateKeyWrapper}) => {145 itEth('Sponsorship can be confirmed by the address that pending as sponsor', async ({helper}) => {161 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);146 const owner = await helper.eth.createAccountWithBalance(donor);162 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);147 const sponsor = await helper.eth.createAccountWithBalance(donor);163 const flipper = await deployFlipper(web3, owner);148 const helpers = helper.ethNativeContract.contractHelpers(owner);164 const helpers = contractHelpers(web3, owner);149 const flipper = await helper.eth.deployFlipper(owner);150165 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;151 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;166 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;152 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;167 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;153 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;168 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;154 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;169 });155 });170156171 itWeb3('Confirm sponsorship event', async ({api, web3, privateKeyWrapper}) => {157 itEth('Confirm sponsorship event', async ({helper}) => {172 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);158 const owner = await helper.eth.createAccountWithBalance(donor);173 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);159 const sponsor = await helper.eth.createAccountWithBalance(donor);174 const flipper = await deployFlipper(web3, owner);160 const helpers = helper.ethNativeContract.contractHelpers(owner);175 const helpers = contractHelpers(web3, owner);161 const flipper = await helper.eth.deployFlipper(owner);162176 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;163 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;177 const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});164 const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});178 const events = normalizeEvents(result.events);165 const events = helper.eth.normalizeEvents(result.events);179 expect(events).to.be.deep.equal([166 expect(events).to.be.deep.equal([180 {167 {181 address: flipper.options.address,168 address: flipper.options.address,186 },173 },187 },174 },188 ]);175 ]);189190 await expectSubstrateEventsAtBlock(191 api, 192 result.blockNumber,193 'evmContractHelpers',194 ['ContractSponsorshipConfirmed'],195 );196 });176 });197177198 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {178 itEth('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({helper}) => {199 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);179 const owner = await helper.eth.createAccountWithBalance(donor);200 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);180 const sponsor = await helper.eth.createAccountWithBalance(donor);201 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);181 const notSponsor = await helper.eth.createAccountWithBalance(donor);202 const flipper = await deployFlipper(web3, owner);182 const helpers = helper.ethNativeContract.contractHelpers(owner);203 const helpers = contractHelpers(web3, owner);183 const flipper = await helper.eth.deployFlipper(owner);184204 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;185 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;205 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;186 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;206 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');187 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');207 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;188 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;208 });189 });209190210 itWeb3('Sponsorship can not be confirmed by the address that not set as sponsor', async ({api, web3, privateKeyWrapper}) => {191 itEth('Sponsorship can not be confirmed by the address that not set as sponsor', async ({helper}) => {211 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);192 const owner = await helper.eth.createAccountWithBalance(donor);212 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);193 const notSponsor = await helper.eth.createAccountWithBalance(donor);213 const flipper = await deployFlipper(web3, owner);194 const helpers = helper.ethNativeContract.contractHelpers(owner);214 const helpers = contractHelpers(web3, owner);195 const flipper = await helper.eth.deployFlipper(owner);196215 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;197 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;216 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');198 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');217 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;199 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;218 });200 });219201220 itWeb3('Get self sponsored sponsor', async ({api, web3, privateKeyWrapper}) => {202 itEth('Get self sponsored sponsor', async ({helper}) => {221 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);203 const owner = await helper.eth.createAccountWithBalance(donor);222 const flipper = await deployFlipper(web3, owner);204 const helpers = helper.ethNativeContract.contractHelpers(owner);223 const helpers = contractHelpers(web3, owner);205 const flipper = await helper.eth.deployFlipper(owner);206224 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();207 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();225 208 229 expect(result[1]).to.be.eq('0');212 expect(result[1]).to.be.eq('0');230 });213 });231214232 itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {215 itEth('Get confirmed sponsor', async ({helper}) => {233 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);216 const owner = await helper.eth.createAccountWithBalance(donor);234 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);217 const sponsor = await helper.eth.createAccountWithBalance(donor);235 const flipper = await deployFlipper(web3, owner);218 const helpers = helper.ethNativeContract.contractHelpers(owner);236 const helpers = contractHelpers(web3, owner);219 const flipper = await helper.eth.deployFlipper(owner);220237 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();221 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();238 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});222 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});243 expect(result[1]).to.be.eq('0');227 expect(result[1]).to.be.eq('0');244 });228 });245229246 itWeb3('Sponsor can be removed by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {230 itEth('Sponsor can be removed by the address that deployed the contract', async ({helper}) => {247 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);231 const owner = await helper.eth.createAccountWithBalance(donor);248 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);232 const sponsor = await helper.eth.createAccountWithBalance(donor);249 const flipper = await deployFlipper(web3, owner);233 const helpers = helper.ethNativeContract.contractHelpers(owner);250 const helpers = contractHelpers(web3, owner);234 const flipper = await helper.eth.deployFlipper(owner);251235252 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;236 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;253 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();237 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();258 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;242 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;259 });243 });260244261 itWeb3('Remove sponsor event', async ({api, web3, privateKeyWrapper}) => {245 itEth('Remove sponsor event', async ({helper}) => {262 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);246 const owner = await helper.eth.createAccountWithBalance(donor);263 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);247 const sponsor = await helper.eth.createAccountWithBalance(donor);264 const flipper = await deployFlipper(web3, owner);248 const helpers = helper.ethNativeContract.contractHelpers(owner);265 const helpers = contractHelpers(web3, owner);249 const flipper = await helper.eth.deployFlipper(owner);266250267 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();251 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();268 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});252 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});269 253 270 const result = await helpers.methods.removeSponsor(flipper.options.address).send();254 const result = await helpers.methods.removeSponsor(flipper.options.address).send();271 const events = normalizeEvents(result.events);255 const events = helper.eth.normalizeEvents(result.events);272 expect(events).to.be.deep.equal([256 expect(events).to.be.deep.equal([273 {257 {274 address: flipper.options.address,258 address: flipper.options.address,278 },262 },279 },263 },280 ]);264 ]);281282 await expectSubstrateEventsAtBlock(283 api, 284 result.blockNumber,285 'evmContractHelpers',286 ['ContractSponsorRemoved'],287 );288 });265 });289266290 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {267 itEth('Sponsor can not be removed by the address that did not deployed the contract', async ({helper}) => {291 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);268 const owner = await helper.eth.createAccountWithBalance(donor);292 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);269 const notOwner = await helper.eth.createAccountWithBalance(donor);293 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);270 const sponsor = await helper.eth.createAccountWithBalance(donor);294 const flipper = await deployFlipper(web3, owner);271 const helpers = helper.ethNativeContract.contractHelpers(owner);295 const helpers = contractHelpers(web3, owner);272 const flipper = await helper.eth.deployFlipper(owner);296273297 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;274 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;298 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();275 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();303 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;280 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;304 });281 });305282306 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {283 itEth('In generous mode, non-allowlisted user transaction will be sponsored', async ({helper}) => {307 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);284 const owner = await helper.eth.createAccountWithBalance(donor);285 const sponsor = await helper.eth.createAccountWithBalance(donor);308 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);286 const caller = await helper.eth.createAccountWithBalance(donor);287 const helpers = helper.ethNativeContract.contractHelpers(owner);309 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);288 const flipper = await helper.eth.deployFlipper(owner);310289311 const flipper = await deployFlipper(web3, owner);312313 const helpers = contractHelpers(web3, owner);314315 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();290 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();316 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});291 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});317292318 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});293 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});319 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});294 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});320295321 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);296 const sponsorBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));322 const callerBalanceBefore = await ethBalanceViaSub(api, caller);297 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));323298324 await flipper.methods.flip().send({from: caller});299 await flipper.methods.flip().send({from: caller});325 expect(await flipper.methods.getValue().call()).to.be.true;300 expect(await flipper.methods.getValue().call()).to.be.true;326301327 // Balance should be taken from sponsor instead of caller302 // Balance should be taken from sponsor instead of caller328 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);303 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));329 const callerBalanceAfter = await ethBalanceViaSub(api, caller);304 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));330 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;305 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;331 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);306 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);332 });307 });333308334 itWeb3('In generous mode, non-allowlisted user transaction will be self sponsored', async ({api, web3, privateKeyWrapper}) => {309 itEth('In generous mode, non-allowlisted user transaction will be self sponsored', async ({helper}) => {335 const alice = privateKeyWrapper('//Alice');310 const owner = await helper.eth.createAccountWithBalance(donor);311 const caller = await helper.eth.createAccountWithBalance(donor);312 const helpers = helper.ethNativeContract.contractHelpers(owner);313 const flipper = await helper.eth.deployFlipper(owner);336314337 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);338 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);339340 const flipper = await deployFlipper(web3, owner);341342 const helpers = contractHelpers(web3, owner);343344 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();315 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();345316346 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});317 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});347 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});318 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});348319349 await transferBalanceToEth(api, alice, flipper.options.address);320 await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address);350321351 const contractBalanceBefore = await ethBalanceViaSub(api, flipper.options.address);322 const contractBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(flipper.options.address));352 const callerBalanceBefore = await ethBalanceViaSub(api, caller);323 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));353324354 await flipper.methods.flip().send({from: caller});325 await flipper.methods.flip().send({from: caller});355 expect(await flipper.methods.getValue().call()).to.be.true;326 expect(await flipper.methods.getValue().call()).to.be.true;356327357 // Balance should be taken from sponsor instead of caller328 // Balance should be taken from sponsor instead of caller358 const contractBalanceAfter = await ethBalanceViaSub(api, flipper.options.address);329 const contractBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(flipper.options.address));359 const callerBalanceAfter = await ethBalanceViaSub(api, caller);330 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));360 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;331 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;361 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);332 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);362 });333 });363334364 itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3, privateKeyWrapper}) => {335 itEth('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({helper}) => {365 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);336 const owner = await helper.eth.createAccountWithBalance(donor);366 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);337 const sponsor = await helper.eth.createAccountWithBalance(donor);338 const caller = helper.eth.createAccount();367 const caller = createEthAccount(web3);339 const helpers = helper.ethNativeContract.contractHelpers(owner);340 const flipper = await helper.eth.deployFlipper(owner);368341369 const flipper = await deployFlipper(web3, owner);370371 const helpers = contractHelpers(web3, owner);372 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});342 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});373 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});343 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});374344378 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();348 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();379 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});349 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});380350381 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);351 const sponsorBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));382 expect(sponsorBalanceBefore).to.be.not.equal('0');352 expect(sponsorBalanceBefore).to.be.not.equal('0');383353384 await flipper.methods.flip().send({from: caller});354 await flipper.methods.flip().send({from: caller});385 expect(await flipper.methods.getValue().call()).to.be.true;355 expect(await flipper.methods.getValue().call()).to.be.true;386356387 // Balance should be taken from flipper instead of caller357 // Balance should be taken from flipper instead of caller388 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);358 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));389 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;359 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;390 });360 });391361392 itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({api, web3, privateKeyWrapper}) => {362 itEth('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({helper}) => {393 const alice = privateKeyWrapper('//Alice');363 const owner = await helper.eth.createAccountWithBalance(donor);364 const caller = await helper.eth.createAccount();365 const helpers = helper.ethNativeContract.contractHelpers(owner);366 const flipper = await helper.eth.deployFlipper(owner);394367395 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);396 const caller = createEthAccount(web3);397398 const flipper = await deployFlipper(web3, owner);399400 const helpers = contractHelpers(web3, owner);401402 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});368 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});403 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});369 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});404370405 await transferBalanceToEth(api, alice, flipper.options.address);371 await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address);406372407 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);373 const originalFlipperBalance = await helper.balance.getEthereum(flipper.options.address);408 expect(originalFlipperBalance).to.be.not.equal('0');374 expect(originalFlipperBalance).to.be.not.equal('0');409375410 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);376 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);411 expect(await flipper.methods.getValue().call()).to.be.false;377 expect(await flipper.methods.getValue().call()).to.be.false;412378413 // Balance should be taken from flipper instead of caller379 // Balance should be taken from flipper instead of caller414 const balanceAfter = await web3.eth.getBalance(flipper.options.address);380 // FIXME the comment is wrong! What check should be here?381 const balanceAfter = await helper.balance.getEthereum(flipper.options.address);415 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);382 expect(balanceAfter).to.be.equals(originalFlipperBalance);416 });383 });417384418 itWeb3('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({api, web3, privateKeyWrapper}) => {385 itEth('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({helper}) => {419 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);386 const owner = await helper.eth.createAccountWithBalance(donor);387 const sponsor = await helper.eth.createAccountWithBalance(donor);420 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);388 const caller = await helper.eth.createAccountWithBalance(donor);389 const helpers = helper.ethNativeContract.contractHelpers(owner);421 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);390 const flipper = await helper.eth.deployFlipper(owner);422391423 const flipper = await deployFlipper(web3, owner);424425 const helpers = contractHelpers(web3, owner);426 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});392 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});427 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});393 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});428394432 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();398 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();433 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});399 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});434400435 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);401 const sponsorBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));436 const callerBalanceBefore = await ethBalanceViaSub(api, caller);402 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));437403438 await flipper.methods.flip().send({from: caller});404 await flipper.methods.flip().send({from: caller});439 expect(await flipper.methods.getValue().call()).to.be.true;405 expect(await flipper.methods.getValue().call()).to.be.true;440406441 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);407 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));442 const callerBalanceAfter = await ethBalanceViaSub(api, caller);408 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));443 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;409 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;444 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);410 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);445 });411 });446412447 itWeb3('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({api, web3, privateKeyWrapper}) => {413 itEth('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({helper}) => {448 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);414 const owner = await helper.eth.createAccountWithBalance(donor);449 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);415 const sponsor = await helper.eth.createAccountWithBalance(donor);450 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);416 const caller = await helper.eth.createAccountWithBalance(donor);451 const originalCallerBalance = await web3.eth.getBalance(caller);417 const helpers = helper.ethNativeContract.contractHelpers(owner);452453 const flipper = await deployFlipper(web3, owner);418 const flipper = await helper.eth.deployFlipper(owner);454419 455 const helpers = contractHelpers(web3, owner);420 const originalCallerBalance = await helper.balance.getEthereum(caller);456 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});421 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});457 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});422 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});458423462 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();427 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();463 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});428 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});464429465 const originalFlipperBalance = await web3.eth.getBalance(sponsor);430 const originalFlipperBalance = await helper.balance.getEthereum(sponsor);466 expect(originalFlipperBalance).to.be.not.equal('0');431 expect(originalFlipperBalance).to.be.not.equal('0');467432468 await flipper.methods.flip().send({from: caller});433 await flipper.methods.flip().send({from: caller});469 expect(await flipper.methods.getValue().call()).to.be.true;434 expect(await flipper.methods.getValue().call()).to.be.true;470 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);435 expect(await helper.balance.getEthereum(caller)).to.be.equals(originalCallerBalance);471436472 const newFlipperBalance = await web3.eth.getBalance(sponsor);437 const newFlipperBalance = await helper.balance.getEthereum(sponsor);473 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);438 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);474439475 await flipper.methods.flip().send({from: caller});440 await flipper.methods.flip().send({from: caller});476 expect(await web3.eth.getBalance(sponsor)).to.be.equal(newFlipperBalance);441 expect(await helper.balance.getEthereum(sponsor)).to.be.equal(newFlipperBalance);477 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);442 expect(await helper.balance.getEthereum(caller)).to.be.not.equals(originalCallerBalance);478 });443 });479444480 // TODO: Find a way to calculate default rate limit445 // TODO: Find a way to calculate default rate limit481 itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {446 itEth('Default rate limit equals 7200', async ({helper}) => {482 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);447 const owner = await helper.eth.createAccountWithBalance(donor);483 const flipper = await deployFlipper(web3, owner);448 const helpers = helper.ethNativeContract.contractHelpers(owner);484 const helpers = contractHelpers(web3, owner);449 const flipper = await helper.eth.deployFlipper(owner);450485 expect(await helpers.methods.sponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');451 expect(await helpers.methods.sponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');486 });452 });487});453});488454489describe('Sponsoring Fee Limit', () => {455describe('Sponsoring Fee Limit', () => {456 let donor: IKeyringPair;457 let alice: IKeyringPair;458 let DEFAULT_GAS: number;490459491 let testContract: CompiledContract;492 493 function compileTestContract() {460 function compileTestContract() {494 if (!testContract) {461 if (!testContract) {495 const input = {462 const input = {537 return testContract;504 return testContract;538 }505 }539 506 540 async function deployTestContract(web3: Web3, owner: string) {507 async function deployTestContract(helper: EthUniqueHelper, owner: string) {508 const web3 = helper.getWeb3();541 const compiled = compileTestContract();509 const compiled = compileTestContract();542 const testContract = new web3.eth.Contract(compiled.abi, undefined, {510 const testContract = new web3.eth.Contract(compiled.abi, undefined, {543 data: compiled.object,511 data: compiled.object,544 from: owner,512 from: owner,545 ...GAS_ARGS,513 gas: DEFAULT_GAS,546 });514 });547 return await testContract.deploy({data: compiled.object}).send({from: owner});515 return await testContract.deploy({data: compiled.object}).send({from: owner});548 }516 }549517550 itWeb3('Default fee limit', async ({api, web3, privateKeyWrapper}) => {518 before(async () => {519 await usingEthPlaygrounds(async (helper, privateKey) => {520 donor = privateKey('//Alice');521 DEFAULT_GAS = helper.eth.DEFAULT_GAS;522 });523 });524525 beforeEach(async () => {551 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);526 await usingPlaygrounds(async (helper) => {527 [alice] = await helper.arrange.createAccounts([1000n], donor);528 });552 const flipper = await deployFlipper(web3, owner);529 });530531 let testContract: CompiledContract;532 533534535 itEth('Default fee limit', async ({helper}) => {536 const owner = await helper.eth.createAccountWithBalance(donor);553 const helpers = contractHelpers(web3, owner);537 const helpers = helper.ethNativeContract.contractHelpers(owner);538 const flipper = await helper.eth.deployFlipper(owner);539554 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('115792089237316195423570985008687907853269984665640564039457584007913129639935');540 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('115792089237316195423570985008687907853269984665640564039457584007913129639935');555 });541 });556542557 itWeb3('Set fee limit', async ({api, web3, privateKeyWrapper}) => {543 itEth('Set fee limit', async ({helper}) => {558 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);544 const owner = await helper.eth.createAccountWithBalance(donor);559 const flipper = await deployFlipper(web3, owner);545 const helpers = helper.ethNativeContract.contractHelpers(owner);560 const helpers = contractHelpers(web3, owner);546 const flipper = await helper.eth.deployFlipper(owner);547561 await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();548 await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();562 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('100');549 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('100');563 });550 });564551565 itWeb3('Negative test - set fee limit by non-owner', async ({api, web3, privateKeyWrapper}) => {552 itEth('Negative test - set fee limit by non-owner', async ({helper}) => {566 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);553 const owner = await helper.eth.createAccountWithBalance(donor);567 const stranger = await createEthAccountWithBalance(api, web3, privateKeyWrapper);554 const stranger = await helper.eth.createAccountWithBalance(donor);568 const flipper = await deployFlipper(web3, owner);555 const helpers = helper.ethNativeContract.contractHelpers(owner);569 const helpers = contractHelpers(web3, owner);556 const flipper = await helper.eth.deployFlipper(owner);557570 await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;558 await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;571 });559 });572560573 itWeb3('Negative test - check that eth transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {561 itEth('Negative test - check that eth transactions exceeding fee limit are not executed', async ({helper}) => {574 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);562 const owner = await helper.eth.createAccountWithBalance(donor);575 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);563 const sponsor = await helper.eth.createAccountWithBalance(donor);576 const user = await createEthAccountWithBalance(api, web3, privateKeyWrapper);564 const user = await helper.eth.createAccountWithBalance(donor);565 const helpers = helper.ethNativeContract.contractHelpers(owner);577566578 const testContract = await deployTestContract(web3, owner);567 const testContract = await deployTestContract(helper, owner);579 const helpers = contractHelpers(web3, owner);580 568 581 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});569 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});582 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});570 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});583 571 584 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();572 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();585 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});573 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});586574587 const gasPrice = BigInt(await web3.eth.getGasPrice());575 const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());588576589 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();577 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();590578591 const originalUserBalance = await web3.eth.getBalance(user);579 const originalUserBalance = await helper.balance.getEthereum(user);592 await testContract.methods.test(100).send({from: user, gas: 2_000_000});580 await testContract.methods.test(100).send({from: user, gas: 2_000_000});593 expect(await web3.eth.getBalance(user)).to.be.equal(originalUserBalance);581 expect(await helper.balance.getEthereum(user)).to.be.equal(originalUserBalance);594582595 await testContract.methods.test(100).send({from: user, gas: 2_100_000});583 await testContract.methods.test(100).send({from: user, gas: 2_100_000});596 expect(await web3.eth.getBalance(user)).to.not.be.equal(originalUserBalance);584 expect(await helper.balance.getEthereum(user)).to.not.be.equal(originalUserBalance);597 });585 });598586599 itWeb3('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {587 itEth('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({helper, privateKey}) => {600 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);588 const owner = await helper.eth.createAccountWithBalance(donor);601 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);589 const sponsor = await helper.eth.createAccountWithBalance(donor);590 const helpers = helper.ethNativeContract.contractHelpers(owner);602591603 const testContract = await deployTestContract(web3, owner);592 const testContract = await deployTestContract(helper, owner);604 const helpers = contractHelpers(web3, owner);605 593 606 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});594 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});607 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});595 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});608 596 609 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();597 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();610 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});598 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});611599612 const gasPrice = BigInt(await web3.eth.getGasPrice());600 const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());613601614 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();602 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();615603616 const alice = privateKeyWrapper('//Alice');604 const originalAliceBalance = await helper.balance.getSubstrate(alice.address);617 const originalAliceBalance = (await api.query.system.account(alice.address)).data.free.toBigInt();605618 619 await submitTransactionAsync(606 await helper.eth.sendEVM(620 alice,607 alice,621 api.tx.evm.call(608 testContract.options.address,622 subToEth(alice.address),623 testContract.options.address,624 testContract.methods.test(100).encodeABI(),609 testContract.methods.test(100).encodeABI(),625 Uint8Array.from([]),610 '0',626 2_000_000n,611 2_000_000,627 gasPrice,628 null,629 null,630 [],631 ),632 );612 );633 expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);613 // expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);614 expect(await helper.balance.getSubstrate(alice.address)).to.be.equal(originalAliceBalance);634 615 635 await submitTransactionAsync(616 await helper.eth.sendEVM(636 alice,617 alice,637 api.tx.evm.call(618 testContract.options.address,638 subToEth(alice.address),639 testContract.options.address,640 testContract.methods.test(100).encodeABI(),619 testContract.methods.test(100).encodeABI(),641 Uint8Array.from([]),620 '0',642 2_100_000n,621 2_100_000,643 gasPrice,644 null,645 null,646 [],647 ),648 );622 );649 expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.not.be.equal(originalAliceBalance);623 expect(await helper.balance.getSubstrate(alice.address)).to.not.be.equal(originalAliceBalance);650 });624 });651});625});652626tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth17import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';19import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';20import {UNIQUE} from '../util/helpers';20212122describe('Create NFT collection from EVM', () => {22describe('Create NFT collection from EVM', () => {23 let donor: IKeyringPair;23 let donor: IKeyringPair;656566 await collectionHelpers.methods66 await collectionHelpers.methods67 .createNonfungibleCollection('A', 'A', 'A')67 .createNonfungibleCollection('A', 'A', 'A')68 .send({value: Number(2n * UNIQUE)});68 .send({value: Number(2n * helper.balance.getOneTokenNominal())});69 69 70 expect(await collectionHelpers.methods70 expect(await collectionHelpers.methods71 .isCollectionExist(expectedCollectionAddress)71 .isCollectionExist(expectedCollectionAddress)147147148describe('(!negative tests!) Create NFT collection from EVM', () => {148describe('(!negative tests!) Create NFT collection from EVM', () => {149 let donor: IKeyringPair;149 let donor: IKeyringPair;150 let nominal: bigint;150151151 before(async function() {152 before(async function() {152 await usingEthPlaygrounds(async (_helper, privateKey) => {153 await usingEthPlaygrounds(async (helper, privateKey) => {153 donor = await privateKey({filename: __filename});154 donor = await privateKey({filename: __filename});155 nominal = helper.balance.getOneTokenNominal();154 });156 });155 });157 });156158165167166 await expect(collectionHelper.methods168 await expect(collectionHelper.methods167 .createNonfungibleCollection(collectionName, description, tokenPrefix)169 .createNonfungibleCollection(collectionName, description, tokenPrefix)168 .call({value: Number(2n * UNIQUE)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);170 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);169 171 170 }172 }171 {173 {175 const tokenPrefix = 'A';177 const tokenPrefix = 'A';176 await expect(collectionHelper.methods178 await expect(collectionHelper.methods177 .createNonfungibleCollection(collectionName, description, tokenPrefix)179 .createNonfungibleCollection(collectionName, description, tokenPrefix)178 .call({value: Number(2n * UNIQUE)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);180 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);179 }181 }180 {182 {181 const MAX_TOKEN_PREFIX_LENGTH = 16;183 const MAX_TOKEN_PREFIX_LENGTH = 16;184 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);186 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);185 await expect(collectionHelper.methods187 await expect(collectionHelper.methods186 .createNonfungibleCollection(collectionName, description, tokenPrefix)188 .createNonfungibleCollection(collectionName, description, tokenPrefix)187 .call({value: Number(2n * UNIQUE)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);189 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);188 }190 }189 });191 });190 192 193 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);195 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);194 await expect(collectionHelper.methods196 await expect(collectionHelper.methods195 .createNonfungibleCollection('Peasantry', 'absolutely anything', 'CVE')197 .createNonfungibleCollection('Peasantry', 'absolutely anything', 'CVE')196 .call({value: Number(1n * UNIQUE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');198 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');197 });199 });198200199 itEth('(!negative test!) Check owner', async ({helper}) => {201 itEth('(!negative test!) Check owner', async ({helper}) => {tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util/playgrounds';19import {Pallets, requirePalletsOrSkip} from '../util/playgrounds';20import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';20import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';21import {UNIQUE} from '../util/helpers';21222223describe('Create RFT collection from EVM', () => {23describe('Create RFT collection from EVM', () => {24 let donor: IKeyringPair;24 let donor: IKeyringPair;666667 await collectionHelpers.methods67 await collectionHelpers.methods68 .createRFTCollection('A', 'A', 'A')68 .createRFTCollection('A', 'A', 'A')69 .send({value: Number(2n * UNIQUE)});69 .send({value: Number(2n * helper.balance.getOneTokenNominal())});70 70 71 expect(await collectionHelpers.methods71 expect(await collectionHelpers.methods72 .isCollectionExist(expectedCollectionAddress)72 .isCollectionExist(expectedCollectionAddress)148148149describe('(!negative tests!) Create RFT collection from EVM', () => {149describe('(!negative tests!) Create RFT collection from EVM', () => {150 let donor: IKeyringPair;150 let donor: IKeyringPair;151 let nominal: bigint;151152152 before(async function() {153 before(async function() {153 await usingEthPlaygrounds(async (helper, privateKey) => {154 await usingEthPlaygrounds(async (helper, privateKey) => {154 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);155 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);155 donor = await privateKey({filename: __filename});156 donor = await privateKey({filename: __filename});157 nominal = helper.balance.getOneTokenNominal();156 });158 });157 });159 });158160167169168 await expect(collectionHelper.methods170 await expect(collectionHelper.methods169 .createRFTCollection(collectionName, description, tokenPrefix)171 .createRFTCollection(collectionName, description, tokenPrefix)170 .call({value: Number(2n * UNIQUE)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);172 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);171 }173 }172 {174 {173 const MAX_DESCRIPTION_LENGTH = 256;175 const MAX_DESCRIPTION_LENGTH = 256;176 const tokenPrefix = 'A';178 const tokenPrefix = 'A';177 await expect(collectionHelper.methods179 await expect(collectionHelper.methods178 .createRFTCollection(collectionName, description, tokenPrefix)180 .createRFTCollection(collectionName, description, tokenPrefix)179 .call({value: Number(2n * UNIQUE)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);181 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);180 }182 }181 {183 {182 const MAX_TOKEN_PREFIX_LENGTH = 16;184 const MAX_TOKEN_PREFIX_LENGTH = 16;185 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);187 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);186 await expect(collectionHelper.methods188 await expect(collectionHelper.methods187 .createRFTCollection(collectionName, description, tokenPrefix)189 .createRFTCollection(collectionName, description, tokenPrefix)188 .call({value: Number(2n * UNIQUE)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);190 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);189 }191 }190 });192 });191 193 194 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);196 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);195 await expect(collectionHelper.methods197 await expect(collectionHelper.methods196 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')198 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')197 .call({value: Number(1n * UNIQUE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');199 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');198 });200 });199201200 itEth('(!negative test!) Check owner', async ({helper}) => {202 itEth('(!negative test!) Check owner', async ({helper}) => {tests/src/eth/marketplace/marketplace.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/>.161617import {usingPlaygrounds} from './../../util/playgrounds/index';18import {IKeyringPair} from '@polkadot/types/types';17import {readFile} from 'fs/promises';19import {readFile} from 'fs/promises';18import {getBalanceSingle} from '../../substrate/get-balance';20import {itEth, expect, SponsoringMode} from '../util/playgrounds';19import {20 addToAllowListExpectSuccess, 21 confirmSponsorshipExpectSuccess, 22 createCollectionExpectSuccess, 23 createItemExpectSuccess, 24 getTokenOwner,25 setCollectionLimitsExpectSuccess, 26 setCollectionSponsorExpectSuccess, 27 transferExpectSuccess, 28 transferFromExpectSuccess,29 transferBalanceTo,30} from '../../util/helpers';31import {collectionIdToAddress, contractHelpers, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, SponsoringMode, subToEth, subToEthLowercase, transferBalanceToEth} from '../util/helpers';32import {evmToAddress} from '@polkadot/util-crypto';33import nonFungibleAbi from '../nonFungibleAbi.json';342135import {expect} from 'chai';22describe('Matcher contract usage', () => {23 const PRICE = 2000n;24 let donor: IKeyringPair;25 let alice: IKeyringPair;26 let aliceMirror: string;27 let aliceDoubleMirror: string;28 let seller: IKeyringPair;29 let sellerMirror: string;363037const PRICE = 2000n;31 before(async () => {32 await usingPlaygrounds(async (_helper, privateKey) => {33 donor = privateKey('//Alice');34 }); 35 });383639describe('Matcher contract usage', () => {37 beforeEach(async () => {40 itWeb3('With UNQ', async ({api, web3, privateKeyWrapper}) => {38 await usingPlaygrounds(async (helper, privateKey) => {41 const alice = privateKeyWrapper('//Alice');39 [alice] = await helper.arrange.createAccounts([10000n], donor);40 aliceMirror = helper.address.substrateToEth(alice.address).toLowerCase();41 aliceDoubleMirror = helper.address.ethToSubstrate(aliceMirror);42 seller = privateKey(`//Seller/${Date.now()}`);42 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);43 sellerMirror = helper.address.substrateToEth(seller.address).toLowerCase();4445 await helper.balance.transferToSubstrate(donor, aliceDoubleMirror, 10_000_000_000_000_000_000n);43 const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);46 });47 });4849 itEth('With UNQ', async ({helper}) => {50 const web3 = helper.getWeb3();51 const matcherOwner = await helper.eth.createAccountWithBalance(donor);44 const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {52 const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {45 from: matcherOwner,53 from: matcherOwner,46 ...GAS_ARGS,54 gas: helper.eth.DEFAULT_GAS,47 });55 });48 const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});56 const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});5749 const helpers = contractHelpers(web3, matcherOwner);58 const sponsor = await helper.eth.createAccountWithBalance(donor);59 const helpers = helper.ethNativeContract.contractHelpers(matcherOwner);50 await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});60 await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});51 await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});61 await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});52 62 53 await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner});63 await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner});54 await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor});64 await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor});556556 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});66 const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}, pendingSponsor: alice.address});57 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorApproveTimeout: 1});67 await collection.confirmSponsorship(alice);68 await collection.addToAllowList(alice, {Substrate: aliceDoubleMirror});58 const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});69 const evmCollection = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');59 await setCollectionSponsorExpectSuccess(collectionId, alice.address);70 await helper.eth.transferBalanceFromSubstrate(donor, aliceMirror);60 await transferBalanceToEth(api, alice, subToEth(alice.address));61 await confirmSponsorshipExpectSuccess(collectionId);627163 await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});72 await helpers.methods.toggleAllowed(matcher.options.address, aliceMirror, true).send({from: matcherOwner});64 await addToAllowListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));73 await helpers.methods.toggleAllowed(matcher.options.address, sellerMirror, true).send({from: matcherOwner});657466 const seller = privateKeyWrapper(`//Seller/${Date.now()}`);75 const token = await collection.mintToken(alice, {Ethereum: sellerMirror});67 await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});687669 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);7071 // To transfer item to matcher it first needs to be transfered to EVM account of bob72 await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});7374 // Token is owned by seller initially77 // Token is owned by seller initially75 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});78 expect(await token.getOwner()).to.be.deep.equal({Ethereum: sellerMirror});767977 // Ask80 // Ask78 {81 {79 await executeEthTxOnSub(web3, api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));82 await helper.eth.sendEVM(seller, evmCollection.options.address, evmCollection.methods.approve(matcher.options.address, token.tokenId).encodeABI(), '0');80 await executeEthTxOnSub(web3, api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));83 await helper.eth.sendEVM(seller, matcher.options.address, matcher.methods.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, token.tokenId).encodeABI(), '0');81 }84 }828583 // Token is transferred to matcher86 // Token is transferred to matcher84 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});87 expect(await token.getOwner()).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});858886 // Buy89 // Buy87 {90 {88 const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);91 const sellerBalanceBeforePurchase = await helper.balance.getSubstrate(seller.address);89 await executeEthTxOnSub(web3, api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId), {value: PRICE});92 await helper.eth.sendEVM(alice, matcher.options.address, matcher.methods.buy(evmCollection.options.address, token.tokenId).encodeABI(), PRICE.toString());90 expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);93 expect(await helper.balance.getSubstrate(seller.address) - sellerBalanceBeforePurchase === PRICE);91 }94 }929593 // Token is transferred to evm account of alice96 // Token is transferred to evm account of alice94 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});97 expect(await token.getOwner()).to.be.deep.equal({Ethereum: aliceMirror});959896 // Transfer token to substrate side of alice99 // Transfer token to substrate side of alice97 await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});100 await token.transferFrom(alice, {Ethereum: aliceMirror}, {Substrate: alice.address});9810199 // Token is transferred to substrate account of alice, seller received funds102 // Token is transferred to substrate account of alice, seller received funds100 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});103 expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});101 });104 });102105103104 itWeb3('With escrow', async ({api, web3, privateKeyWrapper}) => {106 itEth('With escrow', async ({helper}) => {105 const alice = privateKeyWrapper('//Alice');107 const web3 = helper.getWeb3();106 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);108 const matcherOwner = await helper.eth.createAccountWithBalance(donor);107 const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);108 const escrow = await createEthAccountWithBalance(api, web3, privateKeyWrapper);109 const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {109 const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {110 from: matcherOwner,110 from: matcherOwner,111 ...GAS_ARGS,111 gas: helper.eth.DEFAULT_GAS,112 });112 });113 const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner, gas: 10000000});113 const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner, gas: 10000000});114115 const sponsor = await helper.eth.createAccountWithBalance(donor);116 const escrow = await helper.eth.createAccountWithBalance(donor);114 await matcher.methods.setEscrow(escrow).send({from: matcherOwner});117 await matcher.methods.setEscrow(escrow).send({from: matcherOwner});115 const helpers = contractHelpers(web3, matcherOwner);118 const helpers = helper.ethNativeContract.contractHelpers(matcherOwner);116 await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});119 await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});117 await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});120 await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});118 121 119 await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner});122 await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner});120 await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor});123 await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor});121124122 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});125 const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}, pendingSponsor: alice.address});123 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorApproveTimeout: 1});126 await collection.confirmSponsorship(alice);127 await collection.addToAllowList(alice, {Substrate: aliceDoubleMirror});124 const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});128 const evmCollection = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');125 await setCollectionSponsorExpectSuccess(collectionId, alice.address);129 await helper.eth.transferBalanceFromSubstrate(donor, aliceMirror);126 await transferBalanceToEth(api, alice, subToEth(alice.address));127 await confirmSponsorshipExpectSuccess(collectionId);128130129 await helpers.methods.toggleAllowed(matcher.options.address, subToEth(alice.address), true).send({from: matcherOwner});130 await addToAllowListExpectSuccess(alice, collectionId, evmToAddress(subToEth(alice.address)));131131132 const seller = privateKeyWrapper(`//Seller/${Date.now()}`);132 await helpers.methods.toggleAllowed(matcher.options.address, aliceMirror, true).send({from: matcherOwner});133 await helpers.methods.toggleAllowed(matcher.options.address, subToEth(seller.address), true).send({from: matcherOwner});134133135 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);134 await helpers.methods.toggleAllowed(matcher.options.address, sellerMirror, true).send({from: matcherOwner});136135137 // To transfer item to matcher it first needs to be transfered to EVM account of bob136 const token = await collection.mintToken(alice, {Ethereum: sellerMirror});138 await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});139137140 // Token is owned by seller initially138 // Token is owned by seller initially141 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});139 expect(await token.getOwner()).to.be.deep.equal({Ethereum: sellerMirror});142140143 // Ask141 // Ask144 {142 {145 await executeEthTxOnSub(web3, api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));143 await helper.eth.sendEVM(seller, evmCollection.options.address, evmCollection.methods.approve(matcher.options.address, token.tokenId).encodeABI(), '0');146 await executeEthTxOnSub(web3, api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));144 await helper.eth.sendEVM(seller, matcher.options.address, matcher.methods.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, token.tokenId).encodeABI(), '0');147 }145 }148146149 // Token is transferred to matcher147 // Token is transferred to matcher150 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});148 expect(await token.getOwner()).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});151149152 // Give buyer KSM150 // Give buyer KSM153 await matcher.methods.depositKSM(PRICE, subToEth(alice.address)).send({from: escrow});151 await matcher.methods.depositKSM(PRICE, aliceMirror).send({from: escrow});154152155 // Buy153 // Buy156 {154 {157 expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal('0');155 expect(await matcher.methods.balanceKSM(sellerMirror).call()).to.be.equal('0');158 expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal(PRICE.toString());156 expect(await matcher.methods.balanceKSM(aliceMirror).call()).to.be.equal(PRICE.toString());159157160 await executeEthTxOnSub(web3, api, alice, matcher, m => m.buyKSM(evmCollection.options.address, tokenId, subToEth(alice.address), subToEth(alice.address)));158 await helper.eth.sendEVM(alice, matcher.options.address, matcher.methods.buyKSM(evmCollection.options.address, token.tokenId, aliceMirror, aliceMirror).encodeABI(), '0');161159162 // Price is removed from buyer balance, and added to seller160 // Price is removed from buyer balance, and added to seller163 expect(await matcher.methods.balanceKSM(subToEth(alice.address)).call()).to.be.equal('0');161 expect(await matcher.methods.balanceKSM(aliceMirror).call()).to.be.equal('0');164 expect(await matcher.methods.balanceKSM(subToEth(seller.address)).call()).to.be.equal(PRICE.toString());162 expect(await matcher.methods.balanceKSM(sellerMirror).call()).to.be.equal(PRICE.toString());165 }163 }166164167 // Token is transferred to evm account of alice165 // Token is transferred to evm account of alice168 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});166 expect(await token.getOwner()).to.be.deep.equal({Ethereum: aliceMirror});169167170 // Transfer token to substrate side of alice168 // Transfer token to substrate side of alice171 await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});169 await token.transferFrom(alice, {Ethereum: aliceMirror}, {Substrate: alice.address});172170173 // Token is transferred to substrate account of alice, seller received funds171 // Token is transferred to substrate account of alice, seller received funds174 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});172 expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});175 });173 });176174177178 itWeb3('Sell tokens from substrate user via EVM contract', async ({api, web3, privateKeyWrapper}) => {175 itEth('Sell tokens from substrate user via EVM contract', async ({helper}) => {179 const alice = privateKeyWrapper('//Alice');176 const web3 = helper.getWeb3();180 const matcherOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);177 const matcherOwner = await helper.eth.createAccountWithBalance(donor);181 const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {178 const matcherContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/MarketPlace.abi`)).toString()), undefined, {182 from: matcherOwner,179 from: matcherOwner,183 ...GAS_ARGS,180 gas: helper.eth.DEFAULT_GAS,184 });181 });185 const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});182 const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});186 await transferBalanceToEth(api, alice, matcher.options.address);187183188 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});184 await helper.eth.transferBalanceFromSubstrate(donor, matcher.options.address);189 await setCollectionLimitsExpectSuccess(alice, collectionId, {sponsorApproveTimeout: 1});190 const evmCollection = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collectionId), {from: matcherOwner});191185192 const seller = privateKeyWrapper(`//Seller/${Date.now()}`);186 const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}});187 const evmCollection = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');188193 await transferBalanceTo(api, alice, seller.address);189 await helper.balance.transferToSubstrate(donor, seller.address, 100_000_000_000_000_000_000n);194 190 195 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', seller.address);191 const token = await collection.mintToken(alice, {Ethereum: sellerMirror});196197 // To transfer item to matcher it first needs to be transfered to EVM account of bob198 await transferExpectSuccess(collectionId, tokenId, seller, {Ethereum: subToEth(seller.address)});199192200 // Token is owned by seller initially193 // Token is owned by seller initially201 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(seller.address)});194 expect(await token.getOwner()).to.be.deep.equal({Ethereum: sellerMirror});202195203 // Ask196 // Ask204 {197 {205 await executeEthTxOnSub(web3, api, seller, evmCollection, m => m.approve(matcher.options.address, tokenId));198 await helper.eth.sendEVM(seller, evmCollection.options.address, evmCollection.methods.approve(matcher.options.address, token.tokenId).encodeABI(), '0');206 await executeEthTxOnSub(web3, api, seller, matcher, m => m.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, tokenId));199 await helper.eth.sendEVM(seller, matcher.options.address, matcher.methods.addAsk(PRICE, '0x0000000000000000000000000000000000000001', evmCollection.options.address, token.tokenId).encodeABI(), '0');207 }200 }208201209 // Token is transferred to matcher202 // Token is transferred to matcher210 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});203 expect(await token.getOwner()).to.be.deep.equal({Ethereum: matcher.options.address.toLowerCase()});211204212 // Buy205 // Buy213 {206 {214 const sellerBalanceBeforePurchase = await getBalanceSingle(api, seller.address);207 const sellerBalanceBeforePurchase = await helper.balance.getSubstrate(seller.address);215 await executeEthTxOnSub(web3, api, alice, matcher, m => m.buy(evmCollection.options.address, tokenId), {value: PRICE});208 await helper.eth.sendEVM(alice, matcher.options.address, matcher.methods.buy(evmCollection.options.address, token.tokenId).encodeABI(), PRICE.toString());216 expect(await getBalanceSingle(api, seller.address) - sellerBalanceBeforePurchase === PRICE);209 expect(await helper.balance.getSubstrate(seller.address) - sellerBalanceBeforePurchase === PRICE);217 }210 }218211219 // Token is transferred to evm account of alice212 // Token is transferred to evm account of alice220 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Ethereum: subToEthLowercase(alice.address)});213 expect(await token.getOwner()).to.be.deep.equal({Ethereum: aliceMirror});221214222 // Transfer token to substrate side of alice215 // Transfer token to substrate side of alice223 await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: subToEth(alice.address)}, {Substrate: alice.address});216 await token.transferFrom(alice, {Ethereum: aliceMirror}, {Substrate: alice.address});224217225 // Token is transferred to substrate account of alice, seller received funds218 // Token is transferred to substrate account of alice, seller received funds226 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal({Substrate: alice.address});219 expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});227 });220 });228});221});229222tests/src/eth/nonFungible.test.tsdiffbeforeafterboth17import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util/playgrounds';17import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util/playgrounds';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {Contract} from 'web3-eth-contract';19import {Contract} from 'web3-eth-contract';20import {UNIQUE} from '../util/helpers';20212122describe('NFT: Information getting', () => {22describe('NFT: Information getting', () => {23 let donor: IKeyringPair;23 let donor: IKeyringPair;84 const receiver = helper.eth.createAccount();84 const receiver = helper.eth.createAccount();858586 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);86 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);87 let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * UNIQUE)});87 let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});88 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);88 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);89 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);89 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);90 90 tests/src/eth/proxy/fungibleProxy.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/>.161617import {GAS_ARGS, normalizeEvents} from '../util/helpers';18import {expect} from 'chai';17import {expect} from 'chai';19import {readFile} from 'fs/promises';18import {readFile} from 'fs/promises';20import {IKeyringPair} from '@polkadot/types/types';19import {IKeyringPair} from '@polkadot/types/types';26 const web3 = helper.getWeb3();25 const web3 = helper.getWeb3();27 const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {26 const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueFungibleProxy.abi`)).toString()), undefined, {28 from: owner,27 from: owner,29 ...GAS_ARGS,28 gas: helper.eth.DEFAULT_GAS,30 });29 });31 const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueFungibleProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});30 const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueFungibleProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});32 return proxy;31 return proxy;949395 {94 {96 const result = await contract.methods.approve(spender, 100).send({from: caller});95 const result = await contract.methods.approve(spender, 100).send({from: caller});97 const events = normalizeEvents(result.events);96 const events = helper.eth.normalizeEvents(result.events);989799 expect(events).to.be.deep.equal([98 expect(events).to.be.deep.equal([100 {99 {131130132 {131 {133 const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: caller});132 const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: caller});134 const events = normalizeEvents(result.events);133 const events = helper.eth.normalizeEvents(result.events);135 expect(events).to.be.deep.equal([134 expect(events).to.be.deep.equal([136 {135 {137 address,136 address,177176178 {177 {179 const result = await contract.methods.transfer(receiver, 50).send({from: caller});178 const result = await contract.methods.transfer(receiver, 50).send({from: caller});180 const events = normalizeEvents(result.events);179 const events = helper.eth.normalizeEvents(result.events);181 expect(events).to.be.deep.equal([180 expect(events).to.be.deep.equal([182 {181 {183 address,182 address,tests/src/eth/proxy/nonFungibleProxy.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/>.161617import {GAS_ARGS, itWeb3, normalizeEvents} from '../util/helpers';18import {expect} from 'chai';19import {readFile} from 'fs/promises';17import {readFile} from 'fs/promises';20import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';21import {EthUniqueHelper, itEth, usingEthPlaygrounds} from '../util/playgrounds';19import {EthUniqueHelper, itEth, usingEthPlaygrounds, expect} from '../util/playgrounds';20222123async function proxyWrap(helper: EthUniqueHelper, wrapped: any, donor: IKeyringPair) {22async function proxyWrap(helper: EthUniqueHelper, wrapped: any, donor: IKeyringPair) {24 // Proxy owner has no special privilegies, we don't need to reuse them23 // Proxy owner has no special privilegies, we don't need to reuse them25 const owner = await helper.eth.createAccountWithBalance(donor);24 const owner = await helper.eth.createAccountWithBalance(donor);26 const web3 = helper.getWeb3();25 const web3 = helper.getWeb3();27 const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {26 const proxyContract = new web3.eth.Contract(JSON.parse((await readFile(`${__dirname}/UniqueNFTProxy.abi`)).toString()), undefined, {28 from: owner,27 from: owner,29 ...GAS_ARGS,28 gas: helper.eth.DEFAULT_GAS,30 });29 });31 const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});30 const proxy = await proxyContract.deploy({data: (await readFile(`${__dirname}/UniqueNFTProxy.bin`)).toString(), arguments: [wrapped.options.address]}).send({from: owner});32 return proxy;31 return proxy;119 nextTokenId,118 nextTokenId,120 'Test URI',119 'Test URI',121 ).send({from: caller});120 ).send({from: caller});122 const events = normalizeEvents(result.events);121 const events = helper.eth.normalizeEvents(result.events);123 events[0].address = events[0].address.toLocaleLowerCase();122 events[0].address = events[0].address.toLocaleLowerCase();124123125 expect(events).to.be.deep.equal([124 expect(events).to.be.deep.equal([139 });138 });140139141 //TODO: CORE-302 add eth methods140 //TODO: CORE-302 add eth methods142 itWeb3.skip('Can perform mintBulk()', async () => {141 itEth.skip('Can perform mintBulk()', async ({helper}) => {143 /*142 const collection = await helper.nft.mintCollection(donor, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});144 const collection = await createCollectionExpectSuccess({143145 mode: {type: 'NFT'},144 const caller = await helper.eth.createAccountWithBalance(donor, 30n);146 });145 const receiver = helper.eth.createAccount();147 const alice = privateKeyWrapper('//Alice');146148147 const address = helper.ethAddress.fromCollectionId(collection.collectionId);149 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);148 const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller);150 const receiver = createEthAccount(web3);149 const contract = await proxyWrap(helper, evmCollection, donor);151150 await collection.addAdmin(donor, {Ethereum: contract.options.address});152 const address = collectionIdToAddress(collection);151153 const contract = await proxyWrap(api, web3, new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS}), privateKeyWrapper);152 {154 const changeAdminTx = api.tx.unique.addCollectionAdmin(collection, {Ethereum: contract.options.address});153 const nextTokenId = await contract.methods.nextTokenId().call();155 await submitTransactionAsync(alice, changeAdminTx);154 expect(nextTokenId).to.be.equal('1');156155 const result = await contract.methods.mintBulkWithTokenURI(157 {156 receiver,158 const nextTokenId = await contract.methods.nextTokenId().call();157 [159 expect(nextTokenId).to.be.equal('1');158 [nextTokenId, 'Test URI 0'],160 const result = await contract.methods.mintBulkWithTokenURI(159 [+nextTokenId + 1, 'Test URI 1'],161 receiver,160 [+nextTokenId + 2, 'Test URI 2'],162 [161 ],163 [nextTokenId, 'Test URI 0'],162 ).send({from: caller});164 [+nextTokenId + 1, 'Test URI 1'],163 const events = helper.eth.normalizeEvents(result.events);165 [+nextTokenId + 2, 'Test URI 2'],164166 ],165 expect(events).to.be.deep.equal([167 ).send({from: caller});166 {168 const events = normalizeEvents(result.events);167 address,169168 event: 'Transfer',170 expect(events).to.be.deep.equal([169 args: {171 {170 from: '0x0000000000000000000000000000000000000000',172 address,171 to: receiver,173 event: 'Transfer',172 tokenId: nextTokenId,174 args: {173 },175 from: '0x0000000000000000000000000000000000000000',174 },176 to: receiver,175 {177 tokenId: nextTokenId,176 address,178 },177 event: 'Transfer',179 },178 args: {180 {179 from: '0x0000000000000000000000000000000000000000',181 address,180 to: receiver,182 event: 'Transfer',181 tokenId: String(+nextTokenId + 1),183 args: {182 },184 from: '0x0000000000000000000000000000000000000000',183 },185 to: receiver,184 {186 tokenId: String(+nextTokenId + 1),185 address,187 },186 event: 'Transfer',188 },187 args: {189 {188 from: '0x0000000000000000000000000000000000000000',190 address,189 to: receiver,191 event: 'Transfer',190 tokenId: String(+nextTokenId + 2),192 args: {191 },193 from: '0x0000000000000000000000000000000000000000',192 },194 to: receiver,193 ]);195 tokenId: String(+nextTokenId + 2),194196 },195 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');197 },196 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');198 ]);197 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');199198 }200 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI 0');201 expect(await contract.methods.tokenURI(+nextTokenId + 1).call()).to.be.equal('Test URI 1');202 expect(await contract.methods.tokenURI(+nextTokenId + 2).call()).to.be.equal('Test URI 2');203 }204 */205 });199 });206200207 itEth('Can perform burn()', async ({helper}) => {201 itEth('Can perform burn()', async ({helper}) => {216210217 {211 {218 const result = await contract.methods.burn(tokenId).send({from: caller});212 const result = await contract.methods.burn(tokenId).send({from: caller});219 const events = normalizeEvents(result.events);213 const events = helper.eth.normalizeEvents(result.events);220214221 expect(events).to.be.deep.equal([215 expect(events).to.be.deep.equal([222 {216 {243 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});237 const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address});244238245 {239 {246 const result = await contract.methods.approve(spender, tokenId).send({from: caller, ...GAS_ARGS});240 const result = await contract.methods.approve(spender, tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS});247 const events = normalizeEvents(result.events);241 const events = helper.eth.normalizeEvents(result.events);248242249 expect(events).to.be.deep.equal([243 expect(events).to.be.deep.equal([250 {244 {276270277 {271 {278 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: caller});272 const result = await contract.methods.transferFrom(owner, receiver, tokenId).send({from: caller});279 const events = normalizeEvents(result.events);273 const events = helper.eth.normalizeEvents(result.events);280 expect(events).to.be.deep.equal([274 expect(events).to.be.deep.equal([281 {275 {282 address,276 address,313307314 {308 {315 const result = await contract.methods.transfer(receiver, tokenId).send({from: caller});309 const result = await contract.methods.transfer(receiver, tokenId).send({from: caller});316 const events = normalizeEvents(result.events);310 const events = helper.eth.normalizeEvents(result.events);317 expect(events).to.be.deep.equal([311 expect(events).to.be.deep.equal([318 {312 {319 address,313 address,tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth18import {EthUniqueHelper, expect, itEth, usingEthPlaygrounds} from './util/playgrounds';18import {EthUniqueHelper, expect, itEth, usingEthPlaygrounds} from './util/playgrounds';19import {IKeyringPair} from '@polkadot/types/types';19import {IKeyringPair} from '@polkadot/types/types';20import {Contract} from 'web3-eth-contract';20import {Contract} from 'web3-eth-contract';21import {UNIQUE} from '../util/helpers';21222223describe('Refungible token: Information getting', () => {23describe('Refungible token: Information getting', () => {24 let donor: IKeyringPair;24 let donor: IKeyringPair;81 const receiver = helper.eth.createAccount();81 const receiver = helper.eth.createAccount();828283 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);83 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);84 let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * UNIQUE)});84 let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});85 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);85 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);86 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);86 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);87 87 tests/src/eth/scheduling.test.tsdiffbeforeafterbothno changes
tests/src/eth/sponsoring.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/>.161617import {expect} from 'chai';17import {IKeyringPair} from '@polkadot/types/types';18import {contractHelpers, createEthAccount, createEthAccountWithBalance, deployCollector, deployFlipper, itWeb3, SponsoringMode} from './util/helpers';18import {itEth, expect, SponsoringMode} from '../eth/util/playgrounds';19import {usingPlaygrounds} from './../util/playgrounds/index';192020describe('EVM sponsoring', () => {21describe('EVM sponsoring', () => {22 let donor: IKeyringPair;2324 before(async () => {25 await usingPlaygrounds(async (helper, privateKey) => {26 donor = privateKey('//Alice');27 });28 });2921 itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3, privateKeyWrapper}) => {30 itEth('Fee is deducted from contract if sponsoring is enabled', async ({helper}) => {22 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);31 const owner = await helper.eth.createAccountWithBalance(donor);23 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);32 const sponsor = await helper.eth.createAccountWithBalance(donor);24 const caller = createEthAccount(web3);33 const caller = helper.eth.createAccount();25 const originalCallerBalance = await web3.eth.getBalance(caller);34 const originalCallerBalance = await helper.balance.getEthereum(caller);3526 expect(originalCallerBalance).to.be.equal('0');36 expect(originalCallerBalance).to.be.equal(0n);273728 const flipper = await deployFlipper(web3, owner);38 const flipper = await helper.eth.deployFlipper(owner);293930 const helpers = contractHelpers(web3, owner);40 const helpers = helper.ethNativeContract.contractHelpers(owner);4131 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});42 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});32 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});43 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});39 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});50 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});40 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;51 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;415242 const originalSponsorBalance = await web3.eth.getBalance(sponsor);53 const originalSponsorBalance = await helper.balance.getEthereum(sponsor);43 expect(originalSponsorBalance).to.be.not.equal('0');54 expect(originalSponsorBalance).to.be.not.equal(0n);445545 await flipper.methods.flip().send({from: caller});56 await flipper.methods.flip().send({from: caller});46 expect(await flipper.methods.getValue().call()).to.be.true;57 expect(await flipper.methods.getValue().call()).to.be.true;475848 // Balance should be taken from flipper instead of caller59 // Balance should be taken from flipper instead of caller49 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);60 expect(await helper.balance.getEthereum(caller)).to.be.equal(originalCallerBalance);50 expect(await web3.eth.getBalance(sponsor)).to.be.not.equals(originalSponsorBalance);61 expect(await helper.balance.getEthereum(sponsor)).to.be.not.equal(originalSponsorBalance);51 });62 });526353 itWeb3('...but this doesn\'t applies to payable value', async ({api, web3, privateKeyWrapper}) => {64 itEth('...but this doesn\'t applies to payable value', async ({helper}) => {54 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);65 const owner = await helper.eth.createAccountWithBalance(donor);55 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);66 const sponsor = await helper.eth.createAccountWithBalance(donor);56 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);67 const caller = await helper.eth.createAccountWithBalance(donor);57 const originalCallerBalance = await web3.eth.getBalance(caller);68 const originalCallerBalance = await helper.balance.getEthereum(caller);6958 expect(originalCallerBalance).to.be.not.equal('0');70 expect(originalCallerBalance).to.be.not.equal(0n);597160 const collector = await deployCollector(web3, owner);72 const collector = await helper.eth.deployCollectorContract(owner);617362 const helpers = contractHelpers(web3, owner);74 const helpers = helper.ethNativeContract.contractHelpers(owner);7563 await helpers.methods.toggleAllowlist(collector.options.address, true).send({from: owner});76 await helpers.methods.toggleAllowlist(collector.options.address, true).send({from: owner});64 await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner});77 await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner});71 await helpers.methods.setSponsor(collector.options.address, sponsor).send({from: owner});84 await helpers.methods.setSponsor(collector.options.address, sponsor).send({from: owner});72 await helpers.methods.confirmSponsorship(collector.options.address).send({from: sponsor});85 await helpers.methods.confirmSponsorship(collector.options.address).send({from: sponsor});738674 const originalSponsorBalance = await web3.eth.getBalance(sponsor);87 const originalSponsorBalance = await helper.balance.getEthereum(sponsor);75 expect(originalSponsorBalance).to.be.not.equal('0');88 expect(originalSponsorBalance).to.be.not.equal(0n);768977 await collector.methods.giveMoney().send({from: caller, value: '10000'});90 await collector.methods.giveMoney().send({from: caller, value: '10000'});789179 // Balance will be taken from both caller (value) and from collector (fee)92 // Balance will be taken from both caller (value) and from collector (fee)80 expect(await web3.eth.getBalance(caller)).to.be.equals((BigInt(originalCallerBalance) - 10000n).toString());93 expect(await helper.balance.getEthereum(caller)).to.be.equals((originalCallerBalance - 10000n));81 expect(await web3.eth.getBalance(sponsor)).to.be.not.equals(originalSponsorBalance);94 expect(await helper.balance.getEthereum(sponsor)).to.be.not.equals(originalSponsorBalance);82 expect(await collector.methods.getCollected().call()).to.be.equal('10000');95 expect(await collector.methods.getCollected().call()).to.be.equal('10000');83 });96 });84});97});tests/src/eth/tokenProperties.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/>.161617import {itEth, usingEthPlaygrounds, expect, cartesian} from './util/playgrounds';17import {itEth, usingEthPlaygrounds, expect} from './util/playgrounds';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';191920describe('EVM token properties', () => {20describe('EVM token properties', () => {484849 itEth('Can be set', async({helper}) => {49 itEth('Can be set', async({helper}) => {50 const caller = await helper.eth.createAccountWithBalance(donor);50 const caller = await helper.eth.createAccountWithBalance(donor);51 const collection = await helper.nft.mintCollection(alice);51 const collection = await helper.nft.mintCollection(alice, {52 tokenPropertyPermissions: [{53 key: 'testKey',54 permission: {55 collectionAdmin: true,56 },57 }],58 });52 const token = await collection.mintToken(alice);59 const token = await collection.mintToken(alice);5354 await collection.setTokenPropertyPermissions(alice, [{55 key: 'testKey',56 permission: {57 collectionAdmin: true,58 },59 }]);606061 await collection.addAdmin(alice, {Ethereum: caller});61 await collection.addAdmin(alice, {Ethereum: caller});6262717172 itEth('Can be deleted', async({helper}) => {72 itEth('Can be deleted', async({helper}) => {73 const caller = await helper.eth.createAccountWithBalance(donor);73 const caller = await helper.eth.createAccountWithBalance(donor);74 const collection = await helper.nft.mintCollection(alice);74 const collection = await helper.nft.mintCollection(alice, {75 tokenPropertyPermissions: [{76 key: 'testKey',77 permission: {78 mutable: true,79 collectionAdmin: true,80 },81 }],82 });83 75 const token = await collection.mintToken(alice);84 const token = await collection.mintToken(alice);7677 await collection.setTokenPropertyPermissions(alice, [{78 key: 'testKey',79 permission: {80 mutable: true,81 collectionAdmin: true,82 },83 }]);84 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);85 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);858686 await collection.addAdmin(alice, {Ethereum: caller});87 await collection.addAdmin(alice, {Ethereum: caller});969797 itEth('Can be read', async({helper}) => {98 itEth('Can be read', async({helper}) => {98 const caller = helper.eth.createAccount();99 const caller = helper.eth.createAccount();99 const collection = await helper.nft.mintCollection(alice);100 const collection = await helper.nft.mintCollection(alice, {101 tokenPropertyPermissions: [{102 key: 'testKey',103 permission: {104 collectionAdmin: true,105 },106 }],107 });108 100 const token = await collection.mintToken(alice);109 const token = await collection.mintToken(alice);101102 await collection.setTokenPropertyPermissions(alice, [{103 key: 'testKey',104 permission: {105 collectionAdmin: true,106 },107 }]);108 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);110 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);109111110 const address = helper.ethAddress.fromCollectionId(collection.collectionId);112 const address = helper.ethAddress.fromCollectionId(collection.collectionId);116});118});119120121type ElementOf<A> = A extends readonly (infer T)[] ? T : never;122function* cartesian<T extends Array<Array<any>>, R extends Array<any>>(internalRest: [...R], ...args: [...T]): Generator<[...R, ...{[K in keyof T]: ElementOf<T[K]>}]> {123 if(args.length === 0) {124 yield internalRest as any;125 return;126 }127 for(const value of args[0]) {128 yield* cartesian([...internalRest, value], ...args.slice(1)) as any;129 }130}117131tests/src/eth/util/helpers.d.tsdiffbeforeafterbothno changes
tests/src/eth/util/helpers.tsdiffbeforeafterbothno changes
tests/src/eth/util/playgrounds/index.tsdiffbeforeafterboth20chai.use(chaiLike);20chai.use(chaiLike);21export const expect = chai.expect;21export const expect = chai.expect;2223export enum SponsoringMode {24 Disabled = 0,25 Allowlisted = 1,26 Generous = 2,27}222823export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair>) => Promise<void>) => {29export const usingEthPlaygrounds = async (code: (helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair>) => Promise<void>) => {24 const silentConsole = new SilentConsole();30 const silentConsole = new SilentConsole();48 }54 }49 finally {55 finally {50 await helper.disconnect();56 await helper.disconnect();51 await helper.disconnectWeb3();52 silentConsole.disable();57 silentConsole.disable();53 }58 }54};59};77itEthIfWithPallet.skip = (name: string, required: string[], cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any) => itEthIfWithPallet(name, required, cb, {skip: true});82itEthIfWithPallet.skip = (name: string, required: string[], cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any) => itEthIfWithPallet(name, required, cb, {skip: true});78itEth.ifWithPallets = itEthIfWithPallet;83itEth.ifWithPallets = itEthIfWithPallet;7980type ElementOf<A> = A extends readonly (infer T)[] ? T : never;81// I want a fancier api, not a memory efficiency82export function* cartesian<T extends Array<Array<any>>, R extends Array<any>>(internalRest: [...R], ...args: [...T]): Generator<[...R, ...{[K in keyof T]: ElementOf<T[K]>}]> {83 if(args.length === 0) {84 yield internalRest as any;85 return;86 }87 for(const value of args[0]) {88 yield* cartesian([...internalRest, value], ...args.slice(1)) as any;89 }90}9184tests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth8 object: string;8 object: string;9}9}1011export type NormalizedEvent = {12 address: string,13 event: string,14 args: { [key: string]: string }15};16tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth181819import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';202021import {ContractImports, CompiledContract} from './types';21import {ContractImports, CompiledContract, NormalizedEvent} from './types';222223// Native contracts ABI23// Native contracts ABI24import collectionHelpersAbi from '../../collectionHelpersAbi.json';24import collectionHelpersAbi from '../../collectionHelpersAbi.json';27import refungibleAbi from '../../reFungibleAbi.json';27import refungibleAbi from '../../reFungibleAbi.json';28import refungibleTokenAbi from '../../reFungibleTokenAbi.json';28import refungibleTokenAbi from '../../reFungibleTokenAbi.json';29import contractHelpersAbi from './../contractHelpersAbi.json';29import contractHelpersAbi from './../contractHelpersAbi.json';30import {TEthereumAccount} from '../../../util/playgrounds/types';30import {ICrossAccountId, TEthereumAccount} from '../../../util/playgrounds/types';313132class EthGroupBase {32class EthGroupBase {33 helper: EthUniqueHelper;33 helper: EthUniqueHelper;253 return before - after;253 return before - after;254 }254 }255256 normalizeEvents(events: any): NormalizedEvent[] {257 const output = [];258 for (const key of Object.keys(events)) {259 if (key.match(/^[0-9]+$/)) {260 output.push(events[key]);261 } else if (Array.isArray(events[key])) {262 output.push(...events[key]);263 } else {264 output.push(events[key]);265 }266 }267 output.sort((a, b) => a.logIndex - b.logIndex);268 return output.map(({address, event, returnValues}) => {269 const args: { [key: string]: string } = {};270 for (const key of Object.keys(returnValues)) {271 if (!key.match(/^[0-9]+$/)) {272 args[key] = returnValues[key];273 }274 }275 return {276 address,277 event,278 args,279 };280 });281 }282283 async calculateFee(address: ICrossAccountId, code: () => Promise<any>): Promise<bigint> {284 const wrappedCode = async () => {285 await code();286 // In dev mode, the transaction might not finish processing in time287 await this.helper.wait.newBlocks(1);288 };289 return await this.helper.arrange.calculcateFee(address, wrappedCode);290 }255} 291} 256292257class EthAddressGroup extends EthGroupBase {293class EthAddressGroup extends EthGroupBase {285 }321 }286} 322} 287 323 324export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;288325289export class EthUniqueHelper extends DevUniqueHelper {326export class EthUniqueHelper extends DevUniqueHelper {290 web3: Web3 | null = null;327 web3: Web3 | null = null;295 ethNativeContract: NativeContractGroup;332 ethNativeContract: NativeContractGroup;296 ethContract: ContractGroup;333 ethContract: ContractGroup;297334298 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {335 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {336 options.helperBase = options.helperBase ?? EthUniqueHelper;337299 super(logger);338 super(logger, options);300 this.eth = new EthGroup(this);339 this.eth = new EthGroup(this);301 this.ethAddress = new EthAddressGroup(this);340 this.ethAddress = new EthAddressGroup(this);302 this.ethNativeContract = new NativeContractGroup(this);341 this.ethNativeContract = new NativeContractGroup(this);314 this.web3 = new Web3(this.web3Provider);353 this.web3 = new Web3(this.web3Provider);315 }354 }316355317 async disconnectWeb3() {356 async disconnect() {318 if(this.web3 === null) return;357 if(this.web3 === null) return;319 this.web3Provider?.connection.close();358 this.web3Provider?.connection.close();359320 this.web3 = null;360 await super.disconnect();321 }361 }362363 clearApi() {364 this.web3 = null;365 }366367 clone(helperCls: EthUniqueHelperConstructor, options?: { [key: string]: any; }): EthUniqueHelper {368 const newHelper = super.clone(helperCls, options) as EthUniqueHelper;369 newHelper.web3 = this.web3;370 newHelper.web3Provider = this.web3Provider;371372 return newHelper;373 }322}374}323 375 tests/src/flipper/flipper.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/flipper/metadata.jsondiffbeforeafterbothno changes
tests/src/inflation.test.tsdiffbeforeafterboth40 const tx = helper.constructApiCall('api.tx.inflation.startInflation', [1]);40 const tx = helper.constructApiCall('api.tx.inflation.startInflation', [1]);41 await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [tx])).to.not.be.rejected;41 await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [tx])).to.not.be.rejected;424243 const blockInterval = (helper.api!.consts.inflation.inflationBlockInterval as any).toBigInt();43 const blockInterval = (helper.getApi().consts.inflation.inflationBlockInterval as any).toBigInt();44 const totalIssuanceStart = ((await helper.api!.query.inflation.startingYearTotalIssuance()) as any).toBigInt();44 const totalIssuanceStart = ((await helper.callRpc('api.query.inflation.startingYearTotalIssuance', [])) as any).toBigInt();45 const blockInflation = (await helper.api!.query.inflation.blockInflation() as any).toBigInt();45 const blockInflation = (await helper.callRpc('api.query.inflation.blockInflation', []) as any).toBigInt();464647 const YEAR = 5259600n; // 6-second block. Blocks in one year47 const YEAR = 5259600n; // 6-second block. Blocks in one year48 // const YEAR = 2629800n; // 12-second block. Blocks in one year48 // const YEAR = 2629800n; // 12-second block. Blocks in one yeartests/src/load_test_sc/loadtester.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/load_test_sc/metadata.jsondiffbeforeafterbothno changes
tests/src/nesting/migration-check.test.tsdiffbeforeafterbothno changes
tests/src/nesting/properties.test.tsdiffbeforeafterboth276 276 277 itSub('Reads access rights to properties of a collection', async ({helper}) => {277 itSub('Reads access rights to properties of a collection', async ({helper}) => {278 const collection = await helper.nft.mintCollection(alice);278 const collection = await helper.nft.mintCollection(alice);279 const propertyRights = (await helper.api!.query.common.collectionPropertyPermissions(collection.collectionId)).toJSON();279 const propertyRights = (await helper.callRpc('api.query.common.collectionPropertyPermissions', [collection.collectionId])).toJSON();280 expect(propertyRights).to.be.empty;280 expect(propertyRights).to.be.empty;281 });281 });282 282 817 ).to.be.fulfilled;817 ).to.be.fulfilled;818 }818 }819819820 const originalSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 820 const originalSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 821 return originalSpace;821 return originalSpace;822 }822 }823823840 ).to.be.rejectedWith(/common\.NoPermission/);840 ).to.be.rejectedWith(/common\.NoPermission/);841 }841 }842842843 const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 843 const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 844 expect(consumedSpace).to.be.equal(originalSpace);844 expect(consumedSpace).to.be.equal(originalSpace);845 }845 }846846875 ).to.be.rejectedWith(/common\.NoPermission/);875 ).to.be.rejectedWith(/common\.NoPermission/);876 }876 }877 877 878 const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 878 const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 879 expect(consumedSpace).to.be.equal(originalSpace);879 expect(consumedSpace).to.be.equal(originalSpace);880 }880 }881881911911912 expect(await token.getProperties(['non-existent', 'now-existent'])).to.be.empty;912 expect(await token.getProperties(['non-existent', 'now-existent'])).to.be.empty;913 913 914 const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 914 const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 915 expect(consumedSpace).to.be.equal(originalSpace);915 expect(consumedSpace).to.be.equal(originalSpace);916 }916 }917917951 ])).to.be.rejectedWith(/common\.NoSpaceForProperty/);951 ])).to.be.rejectedWith(/common\.NoSpaceForProperty/);952 952 953 expect(await token.getProperties(['a_holy_book', 'young_years'])).to.be.empty;953 expect(await token.getProperties(['a_holy_book', 'young_years'])).to.be.empty;954 const consumedSpace = await getConsumedSpace(token.collection.helper.api, token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 954 const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); 955 expect(consumedSpace).to.be.equal(originalSpace);955 expect(consumedSpace).to.be.equal(originalSpace);956 }956 }957957tests/src/overflow.test.tsdiffbeforeafterbothno changes
tests/src/pallet-presence.test.tsdiffbeforeafterboth59describe('Pallet presence', () => {59describe('Pallet presence', () => {60 before(async () => {60 before(async () => {61 await usingPlaygrounds(async helper => {61 await usingPlaygrounds(async helper => {62 const chain = await helper.api!.rpc.system.chain();62 const chain = await helper.callRpc('api.rpc.system.chain', []);636364 const refungible = 'refungible';64 const refungible = 'refungible';65 const scheduler = 'scheduler';65 const scheduler = 'scheduler';tests/src/removeFromContractAllowList.test.tsdiffbeforeafterbothno changes
tests/src/rmrk/acceptNft.test.tsdiffbeforeafterboth8} from './util/tx';8} from './util/tx';9import {NftIdTuple} from './util/fetch';9import {NftIdTuple} from './util/fetch';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';11import {requirePallets, Pallets} from '../util/helpers';11import {requirePallets, Pallets} from '../deprecated-helpers/helpers';121213describe('integration test: accept NFT', () => {13describe('integration test: accept NFT', () => {14 let api: any;14 let api: any;tests/src/rmrk/addResource.test.tsdiffbeforeafterboth12 addNftComposableResource,12 addNftComposableResource,13} from './util/tx';13} from './util/tx';14import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';14import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';15import {requirePallets, Pallets} from '../util/helpers';15import {requirePallets, Pallets} from '../deprecated-helpers/helpers';161617describe('integration test: add NFT resource', () => {17describe('integration test: add NFT resource', () => {18 const Alice = '//Alice';18 const Alice = '//Alice';tests/src/rmrk/addTheme.test.tsdiffbeforeafterboth3import {createBase, addTheme} from './util/tx';3import {createBase, addTheme} from './util/tx';4import {expectTxFailure} from './util/helpers';4import {expectTxFailure} from './util/helpers';5import {getThemeNames} from './util/fetch';5import {getThemeNames} from './util/fetch';6import {requirePallets, Pallets} from '../util/helpers';6import {requirePallets, Pallets} from '../deprecated-helpers/helpers';778describe('integration test: add Theme to Base', () => {8describe('integration test: add Theme to Base', () => {9 let api: any;9 let api: any;tests/src/rmrk/burnNft.test.tsdiffbeforeafterboth556import chai from 'chai';6import chai from 'chai';7import chaiAsPromised from 'chai-as-promised';7import chaiAsPromised from 'chai-as-promised';8import {requirePallets, Pallets} from '../util/helpers';8import {requirePallets, Pallets} from '../deprecated-helpers/helpers';9910chai.use(chaiAsPromised);10chai.use(chaiAsPromised);11const expect = chai.expect;11const expect = chai.expect;tests/src/rmrk/changeCollectionIssuer.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';4import {4import {5 changeIssuer,5 changeIssuer,tests/src/rmrk/createBase.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {createCollection, createBase} from './util/tx';3import {createCollection, createBase} from './util/tx';445describe('integration test: create new Base', () => {5describe('integration test: create new Base', () => {tests/src/rmrk/createCollection.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {createCollection} from './util/tx';3import {createCollection} from './util/tx';445describe('Integration test: create new collection', () => {5describe('Integration test: create new collection', () => {tests/src/rmrk/deleteCollection.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';4import {createCollection, deleteCollection} from './util/tx';4import {createCollection, deleteCollection} from './util/tx';55tests/src/rmrk/equipNft.test.tsdiffbeforeafterboth1import {ApiPromise} from '@polkadot/api';1import {ApiPromise} from '@polkadot/api';2import {expect} from 'chai';2import {expect} from 'chai';3import {getApiConnection} from '../substrate/substrate-api';3import {getApiConnection} from '../substrate/substrate-api';4import {requirePallets, Pallets} from '../util/helpers';4import {requirePallets, Pallets} from '../deprecated-helpers/helpers';5import {getNft, getParts, NftIdTuple} from './util/fetch';5import {getNft, getParts, NftIdTuple} from './util/fetch';6import {expectTxFailure} from './util/helpers';6import {expectTxFailure} from './util/helpers';7import {7import {tests/src/rmrk/getOwnedNfts.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import {getApiConnection} from '../substrate/substrate-api';2import {getApiConnection} from '../substrate/substrate-api';3import {requirePallets, Pallets} from '../util/helpers';3import {requirePallets, Pallets} from '../deprecated-helpers/helpers';4import {getOwnedNfts} from './util/fetch';4import {getOwnedNfts} from './util/fetch';5import {mintNft, createCollection} from './util/tx';5import {mintNft, createCollection} from './util/tx';66tests/src/rmrk/lockCollection.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';4import {createCollection, lockCollection, mintNft} from './util/tx';4import {createCollection, lockCollection, mintNft} from './util/tx';55tests/src/rmrk/mintNft.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import {getApiConnection} from '../substrate/substrate-api';2import {getApiConnection} from '../substrate/substrate-api';3import {requirePallets, Pallets} from '../util/helpers';3import {requirePallets, Pallets} from '../deprecated-helpers/helpers';4import {getNft} from './util/fetch';4import {getNft} from './util/fetch';5import {expectTxFailure} from './util/helpers';5import {expectTxFailure} from './util/helpers';6import {createCollection, mintNft} from './util/tx';6import {createCollection, mintNft} from './util/tx';tests/src/rmrk/rejectNft.test.tsdiffbeforeafterboth8} from './util/tx';8} from './util/tx';9import {getChildren, NftIdTuple} from './util/fetch';9import {getChildren, NftIdTuple} from './util/fetch';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';11import {requirePallets, Pallets} from '../util/helpers';11import {requirePallets, Pallets} from '../deprecated-helpers/helpers';121213describe('integration test: reject NFT', () => {13describe('integration test: reject NFT', () => {14 let api: any;14 let api: any;tests/src/rmrk/removeResource.test.tsdiffbeforeafterboth1import {expect} from 'chai';1import {expect} from 'chai';2import privateKey from '../substrate/privateKey';2import privateKey from '../substrate/privateKey';3import {executeTransaction, getApiConnection} from '../substrate/substrate-api';3import {executeTransaction, getApiConnection} from '../substrate/substrate-api';4import {requirePallets, Pallets} from '../util/helpers';4import {requirePallets, Pallets} from '../deprecated-helpers/helpers';5import {getNft, NftIdTuple} from './util/fetch';5import {getNft, NftIdTuple} from './util/fetch';6import {expectTxFailure} from './util/helpers';6import {expectTxFailure} from './util/helpers';7import {7import {tests/src/rmrk/rmrkIsolation.test.tsdiffbeforeafterboth9 requirePallets,9 requirePallets,10 normalizeAccountId,10 normalizeAccountId,11 Pallets,11 Pallets,12} from '../util/helpers';12} from '../deprecated-helpers/helpers';13import {IKeyringPair} from '@polkadot/types/types';13import {IKeyringPair} from '@polkadot/types/types';14import {ApiPromise} from '@polkadot/api';14import {ApiPromise} from '@polkadot/api';15import {it} from 'mocha';15import {it} from 'mocha';tests/src/rmrk/sendNft.test.tsdiffbeforeafterboth3import {createCollection, mintNft, sendNft} from './util/tx';3import {createCollection, mintNft, sendNft} from './util/tx';4import {NftIdTuple} from './util/fetch';4import {NftIdTuple} from './util/fetch';5import {isNftChildOfAnother, expectTxFailure} from './util/helpers';5import {isNftChildOfAnother, expectTxFailure} from './util/helpers';6import {requirePallets, Pallets} from '../util/helpers';6import {requirePallets, Pallets} from '../deprecated-helpers/helpers';778describe('integration test: send NFT', () => {8describe('integration test: send NFT', () => {9 let api: any;9 let api: any;tests/src/rmrk/setCollectionProperty.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';4import {createCollection, setPropertyCollection} from './util/tx';4import {createCollection, setPropertyCollection} from './util/tx';55tests/src/rmrk/setEquippableList.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';4import {createCollection, createBase, setEquippableList} from './util/tx';4import {createCollection, createBase, setEquippableList} from './util/tx';55tests/src/rmrk/setNftProperty.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {NftIdTuple} from './util/fetch';3import {NftIdTuple} from './util/fetch';4import {expectTxFailure} from './util/helpers';4import {expectTxFailure} from './util/helpers';5import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';5import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';tests/src/rmrk/setResourcePriorities.test.tsdiffbeforeafterboth1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';2import {requirePallets, Pallets} from '../util/helpers';2import {requirePallets, Pallets} from '../deprecated-helpers/helpers';3import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';4import {mintNft, createCollection, setResourcePriorities} from './util/tx';4import {mintNft, createCollection, setResourcePriorities} from './util/tx';55tests/src/rpc.load.tsdiffbeforeafterbothno changes
tests/src/scheduler.test.tsdiffbeforeafterbothno changes
tests/src/setChainLimits.test.tsdiffbeforeafterbothno changes
tests/src/setContractSponsoringRateLimit.test.tsdiffbeforeafterbothno changes
tests/src/substrate/get-balance.tsdiffbeforeafterboth19import promisifySubstrate from './promisify-substrate';19import promisifySubstrate from './promisify-substrate';20import {IKeyringPair} from '@polkadot/types/types';20import {IKeyringPair} from '@polkadot/types/types';21import {submitTransactionAsync} from './substrate-api';21import {submitTransactionAsync} from './substrate-api';22import {getGenericResult} from '../util/helpers';22import {getGenericResult} from '../deprecated-helpers/helpers';23import {expect} from 'chai';23import {expect} from 'chai';242425export default async function getBalance(api: ApiPromise, accounts: string[]): Promise<Array<bigint>> {25export default async function getBalance(api: ApiPromise, accounts: string[]): Promise<Array<bigint>> {tests/src/toggleContractAllowList.test.tsdiffbeforeafterbothno changes
tests/src/transfer.nload.tsdiffbeforeafterboth18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import usingApi, {submitTransactionAsync} from './substrate/substrate-api';19import usingApi, {submitTransactionAsync} from './substrate/substrate-api';20import waitNewBlocks from './substrate/wait-new-blocks';20import waitNewBlocks from './substrate/wait-new-blocks';21import {findUnusedAddresses} from './util/helpers';22import * as cluster from 'cluster';21import * as cluster from 'cluster';23import os from 'os';22import os from 'os';2324async function findUnusedAddress(api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair, seedAddition = ''): Promise<IKeyringPair> {25 let bal = 0n;26 let unused;27 do {28 const randomSeed = 'seed' + Math.floor(Math.random() * Math.floor(10000)) + seedAddition;29 unused = privateKeyWrapper(`//${randomSeed}`);30 bal = (await api.query.system.account(unused.address)).data.free.toBigInt();31 } while (bal !== 0n);32 return unused;33}3435function findUnusedAddresses(api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair, amount: number): Promise<IKeyringPair[]> {36 return Promise.all(new Array(amount).fill(null).map(() => findUnusedAddress(api, privateKeyWrapper, '_' + Date.now())));37}243825// Innacurate transfer fee39// Innacurate transfer fee26const FEE = 10n ** 8n;40const FEE = 10n ** 8n;tests/src/transfer_contract/metadata.jsondiffbeforeafterbothno changes
tests/src/transfer_contract/nft_transfer.wasmdiffbeforeafterbothbinary blob — no preview
tests/src/tx-version-presence.test.tsdiffbeforeafterboth22describe('TxVersion is present', () => {22describe('TxVersion is present', () => {23 before(async () => {23 before(async () => {24 await usingPlaygrounds(async helper => {24 await usingPlaygrounds(async helper => {25 metadata = await helper.api!.rpc.state.getMetadata();25 metadata = await helper.callRpc('api.rpc.state.getMetadata', []);26 });26 });27 });27 });2828tests/src/util/contracthelpers.tsdiffbeforeafterbothno changes
tests/src/util/helpers.tsdiffbeforeafterbothno changes
tests/src/util/playgrounds/index.tsdiffbeforeafterboth62 Fungible = 'fungible',62 Fungible = 'fungible',63 NFT = 'nonfungible',63 NFT = 'nonfungible',64 Scheduler = 'scheduler',64 Scheduler = 'scheduler',65 AppPromotion = 'apppromotion',65}66}666767export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {68export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {tests/src/util/playgrounds/types.tsdiffbeforeafterboth14export interface ITransactionResult {14export interface ITransactionResult {15 status: 'Fail' | 'Success';15 status: 'Fail' | 'Success';16 result: {16 result: {17 dispatchError: any,17 events: {18 events: {18 phase: any, // {ApplyExtrinsic: number} | 'Initialization',19 phase: any, // {ApplyExtrinsic: number} | 'Initialization',19 event: IEvent;20 event: IEvent;47 call: string;48 call: string;48 params: any[];49 params: any[];49 moduleError?: string;50 moduleError?: string;51 dispatchError?: any;50 events?: any;52 events?: any;51}53}5254162 amount: bigint,164 amount: bigint,163}165}166167export interface ISchedulerOptions {168 priority?: number,169 periodic?: {170 period: number,171 repetitions: number,172 },173}164174165export type TSubstrateAccount = string;175export type TSubstrateAccount = string;166export type TEthereumAccount = string;176export type TEthereumAccount = string;tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth63 wait: WaitGroup;62 wait: WaitGroup;64 admin: AdminGroup;63 admin: AdminGroup;656466 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {65 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {66 options.helperBase = options.helperBase ?? DevUniqueHelper;6767 super(logger);68 super(logger, options);68 this.arrange = new ArrangeGroup(this);69 this.arrange = new ArrangeGroup(this);69 this.wait = new WaitGroup(this);70 this.wait = new WaitGroup(this);70 this.admin = new AdminGroup(this);71 this.admin = new AdminGroup(this);108}109}109110110class ArrangeGroup {111class ArrangeGroup {111 helper: UniqueHelper;112 helper: DevUniqueHelper;112113113 constructor(helper: UniqueHelper) {114 constructor(helper: DevUniqueHelper) {114 this.helper = helper;115 this.helper = helper;115 }116 }116117215 };216 };216217217 isDevNode = async () => {218 isDevNode = async () => {218 const block1 = await this.helper.api?.rpc.chain.getBlock(await this.helper.api?.rpc.chain.getBlockHash(1));219 const block1 = await this.helper.callRpc('api.rpc.chain.getBlock', [await this.helper.callRpc('api.rpc.chain.getBlockHash', [1])]);219 const block2 = await this.helper.api?.rpc.chain.getBlock(await this.helper.api?.rpc.chain.getBlockHash(2));220 const block2 = await this.helper.callRpc('api.rpc.chain.getBlock', [await this.helper.callRpc('api.rpc.chain.getBlockHash', [2])]);220 const findCreationDate = async (block: any) => {221 const findCreationDate = async (block: any) => {221 const humanBlock = block.toHuman();222 const humanBlock = block.toHuman();222 let date;223 let date;245}246}246247247class WaitGroup {248class WaitGroup {248 helper: UniqueHelper;249 helper: DevUniqueHelper;249250250 constructor(helper: UniqueHelper) {251 constructor(helper: DevUniqueHelper) {251 this.helper = helper;252 this.helper = helper;252 }253 }253254254 /**255 /**255 * Wait for specified bnumber of blocks256 * Wait for specified number of blocks256 * @param blocksCount number of blocks to wait257 * @param blocksCount number of blocks to wait257 * @returns 258 * @returns 258 */259 */259 async newBlocks(blocksCount = 1): Promise<void> {260 async newBlocks(blocksCount = 1): Promise<void> {260 // eslint-disable-next-line no-async-promise-executor261 // eslint-disable-next-line no-async-promise-executor261 const promise = new Promise<void>(async (resolve) => {262 const promise = new Promise<void>(async (resolve) => {262 const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(() => {263 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(() => {263 if (blocksCount > 0) {264 if (blocksCount > 0) {264 blocksCount--;265 blocksCount--;265 } else {266 } else {274 async forParachainBlockNumber(blockNumber: bigint) {275 async forParachainBlockNumber(blockNumber: bigint) {275 // eslint-disable-next-line no-async-promise-executor276 // eslint-disable-next-line no-async-promise-executor276 return new Promise<void>(async (resolve) => {277 return new Promise<void>(async (resolve) => {277 const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(async (data: any) => {278 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(async (data: any) => {278 if (data.number.toNumber() >= blockNumber) {279 if (data.number.toNumber() >= blockNumber) {279 unsubscribe();280 unsubscribe();280 resolve();281 resolve();286 async forRelayBlockNumber(blockNumber: bigint) {287 async forRelayBlockNumber(blockNumber: bigint) {287 // eslint-disable-next-line no-async-promise-executor288 // eslint-disable-next-line no-async-promise-executor288 return new Promise<void>(async (resolve) => {289 return new Promise<void>(async (resolve) => {289 const unsubscribe = await this.helper.api!.query.parachainSystem.validationData(async (data: any) => {290 const unsubscribe = await this.helper.getApi().query.parachainSystem.validationData(async (data: any) => {290 if (data.value.relayParentNumber.toNumber() >= blockNumber) {291 if (data.value.relayParentNumber.toNumber() >= blockNumber) {291 // @ts-ignore292 // @ts-ignore292 unsubscribe();293 unsubscribe();tests/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, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';131314export class CrossAccountId implements ICrossAccountId {14export class CrossAccountId implements ICrossAccountId {15 Substrate?: TSubstrateAccount;15 Substrate?: TSubstrateAccount;275 }275 }276 276 277 private static extractData(data: any, type: any): any {277 private static extractData(data: any, type: any): any {278 if(!type) return data.toHuman();278 if (['u16', 'u32'].indexOf(type.type) > -1) return data.toNumber();279 if (['u16', 'u32'].indexOf(type.type) > -1) return data.toNumber();279 if (['u64', 'u128', 'u256'].indexOf(type.type) > -1) return data.toBigInt();280 if (['u64', 'u128', 'u256'].indexOf(type.type) > -1) return data.toBigInt();280 if(type.hasOwnProperty('sub')) return this.extractSub(data, type.sub);281 if(type.hasOwnProperty('sub')) return this.extractSub(data, type.sub);317 forcedNetwork: TUniqueNetworks | null;318 forcedNetwork: TUniqueNetworks | null;318 network: TUniqueNetworks | null;319 network: TUniqueNetworks | null;319 chainLog: IUniqueHelperLog[];320 chainLog: IUniqueHelperLog[];321 children: ChainHelperBase[];320322321 constructor(logger?: ILogger) {323 constructor(logger?: ILogger) {322 this.util = UniqueUtil;324 this.util = UniqueUtil;327 this.forcedNetwork = null;329 this.forcedNetwork = null;328 this.network = null;330 this.network = null;329 this.chainLog = [];331 this.chainLog = [];332 this.children = [];330 }333 }334335 getApi(): ApiPromise {336 if(this.api === null) throw Error('API not initialized');337 return this.api;338 }331339332 clearChainLog(): void {340 clearChainLog(): void {333 this.chainLog = [];341 this.chainLog = [];345 }353 }346354347 async disconnect() {355 async disconnect() {356 for (const child of this.children) {357 child.clearApi();358 }359348 if (this.api === null) return;360 if (this.api === null) return;349 await this.api.disconnect();361 await this.api.disconnect();350 this.api = null;362 this.clearApi();351 this.network = null;352 }363 }364365 clearApi() {366 this.api = null;367 this.network = null;368 }353369354 static async detectNetwork(api: ApiPromise): Promise<TUniqueNetworks> {370 static async detectNetwork(api: ApiPromise): Promise<TUniqueNetworks> {355 const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;371 const spec = (await api.query.system.lastRuntimeUpgrade()).toJSON() as any;473489474 constructApiCall(apiCall: string, params: any[]) {490 constructApiCall(apiCall: string, params: any[]) {475 if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);491 if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);476 let call = this.api as any;492 let call = this.getApi() as any;477 for(const part of apiCall.slice(4).split('.')) {493 for(const part of apiCall.slice(4).split('.')) {478 call = call[part];494 call = call[part];479 }495 }508 params,524 params,509 } as IUniqueHelperLog;525 } as IUniqueHelperLog;510526511 if(result.status !== this.transactionStatus.SUCCESS && result.moduleError) log.moduleError = result.moduleError;527 if(result.status !== this.transactionStatus.SUCCESS) {528 if (result.moduleError) log.moduleError = result.moduleError;529 else if (result.result.dispatchError) log.dispatchError = result.result.dispatchError;530 }512 if(events.length > 0) log.events = events;531 if(events.length > 0) log.events = events;513532514 this.chainLog.push(log);533 this.chainLog.push(log);515534516 if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) throw Error(`${result.moduleError}`);535 if(expectSuccess && result.status !== this.transactionStatus.SUCCESS) {536 if (result.moduleError) throw Error(`${result.moduleError}`);537 else if (result.result.dispatchError) throw Error(JSON.stringify(result.result.dispatchError));538 }517 return result;539 return result;518 }540 }5195411985 * @returns ss58Format, token decimals, and token symbol2007 * @returns ss58Format, token decimals, and token symbol1986 */2008 */1987 getChainProperties(): IChainProperties {2009 getChainProperties(): IChainProperties {1988 const properties = (this.helper.api as any).registry.getChainProperties().toJSON();2010 const properties = (this.helper.getApi() as any).registry.getChainProperties().toJSON();1989 return {2011 return {1990 ss58Format: properties.ss58Format.toJSON(),2012 ss58Format: properties.ss58Format.toJSON(),1991 tokenDecimals: properties.tokenDecimals.toJSON(),2013 tokenDecimals: properties.tokenDecimals.toJSON(),2028 * @returns number, account's nonce2050 * @returns number, account's nonce2029 */2051 */2030 async getNonce(address: TSubstrateAccount): Promise<number> {2052 async getNonce(address: TSubstrateAccount): Promise<number> {2031 return (await (this.helper.api as any).query.system.account(address)).nonce.toNumber();2053 return (await this.helper.callRpc('api.query.system.account', [address])).nonce.toNumber();2032 }2054 }2033}2055}203420562160 */2182 */2161 async stake(signer: TSigner, amountToStake: bigint, label?: string): Promise<boolean> {2183 async stake(signer: TSigner, amountToStake: bigint, label?: string): Promise<boolean> {2162 if(typeof label === 'undefined') label = `${signer.address} amount: ${amountToStake}`;2184 if(typeof label === 'undefined') label = `${signer.address} amount: ${amountToStake}`;2163 const stakeResult = await this.helper.executeExtrinsic(2185 const _stakeResult = await this.helper.executeExtrinsic(2164 signer, 'api.tx.appPromotion.stake',2186 signer, 'api.tx.appPromotion.stake',2165 [amountToStake], true,2187 [amountToStake], true,2166 );2188 );2177 */2199 */2178 async unstake(signer: TSigner, label?: string): Promise<number> {2200 async unstake(signer: TSigner, label?: string): Promise<number> {2179 if(typeof label === 'undefined') label = `${signer.address}`;2201 if(typeof label === 'undefined') label = `${signer.address}`;2180 const unstakeResult = await this.helper.executeExtrinsic(2202 const _unstakeResult = await this.helper.executeExtrinsic(2181 signer, 'api.tx.appPromotion.unstake',2203 signer, 'api.tx.appPromotion.unstake',2182 [], true,2204 [], true,2183 );2205 );2236 }2258 }2237}2259}22602261class SchedulerGroup extends HelperGroup {2262 constructor(helper: UniqueHelper) {2263 super(helper);2264 }22652266 async cancelScheduled(signer: TSigner, scheduledId: string) {2267 return this.helper.executeExtrinsic(2268 signer,2269 'api.tx.scheduler.cancelNamed',2270 [scheduledId],2271 true,2272 );2273 }22742275 async changePriority(signer: TSigner, scheduledId: string, priority: number) {2276 return this.helper.executeExtrinsic(2277 signer,2278 'api.tx.scheduler.changeNamedPriority',2279 [scheduledId, priority],2280 true,2281 );2282 }22832284 scheduleAt<T extends UniqueHelper>(2285 scheduledId: string,2286 executionBlockNumber: number,2287 options: ISchedulerOptions = {},2288 ) {2289 return this.schedule<T>('scheduleNamed', scheduledId, executionBlockNumber, options);2290 }22912292 scheduleAfter<T extends UniqueHelper>(2293 scheduledId: string,2294 blocksBeforeExecution: number,2295 options: ISchedulerOptions = {},2296 ) {2297 return this.schedule<T>('scheduleNamedAfter', scheduledId, blocksBeforeExecution, options);2298 }22992300 schedule<T extends UniqueHelper>(2301 scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter',2302 scheduledId: string,2303 blocksNum: number,2304 options: ISchedulerOptions = {},2305 ) {2306 // eslint-disable-next-line @typescript-eslint/naming-convention2307 const ScheduledHelperType = ScheduledUniqueHelper(this.helper.helperBase);2308 return this.helper.clone(ScheduledHelperType, {2309 scheduleFn,2310 scheduledId,2311 blocksNum,2312 options,2313 }) as T;2314 }2315}23162317export type UniqueHelperConstructor = new(...args: any[]) => UniqueHelper;223823182239export class UniqueHelper extends ChainHelperBase {2319export class UniqueHelper extends ChainHelperBase {2320 helperBase: any;23212240 chain: ChainGroup;2322 chain: ChainGroup;2241 balance: BalanceGroup;2323 balance: BalanceGroup;2245 rft: RFTGroup;2327 rft: RFTGroup;2246 ft: FTGroup;2328 ft: FTGroup;2247 staking: StakingGroup;2329 staking: StakingGroup;2330 scheduler: SchedulerGroup;224823312249 constructor(logger?: ILogger) {2332 constructor(logger?: ILogger, options: {[key: string]: any} = {}) {2250 super(logger);2333 super(logger);23342335 this.helperBase = options.helperBase ?? UniqueHelper;23362251 this.chain = new ChainGroup(this);2337 this.chain = new ChainGroup(this);2252 this.balance = new BalanceGroup(this);2338 this.balance = new BalanceGroup(this);2256 this.rft = new RFTGroup(this);2342 this.rft = new RFTGroup(this);2257 this.ft = new FTGroup(this);2343 this.ft = new FTGroup(this);2258 this.staking = new StakingGroup(this);2344 this.staking = new StakingGroup(this);2345 this.scheduler = new SchedulerGroup(this);2259 }2346 }23472348 clone(helperCls: UniqueHelperConstructor, options: {[key: string]: any} = {}) {2349 Object.setPrototypeOf(helperCls.prototype, this);2350 const newHelper = new helperCls(this.logger, options);23512352 newHelper.api = this.api;2353 newHelper.network = this.network;2354 newHelper.forceNetwork = this.forceNetwork;23552356 this.children.push(newHelper);23572358 return newHelper;2359 }23602361 getSudo<T extends UniqueHelper>() {2362 // eslint-disable-next-line @typescript-eslint/naming-convention2363 const SudoHelperType = SudoUniqueHelper(this.helperBase);2364 return this.clone(SudoHelperType) as T;2365 }2260}2366}226123672368// eslint-disable-next-line @typescript-eslint/naming-convention2369function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {2370 return class extends Base {2371 scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter';2372 scheduledId: string;2373 blocksNum: number;2374 options: ISchedulerOptions;23752376 constructor(...args: any[]) {2377 const logger = args[0] as ILogger;2378 const options = args[1] as {2379 scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter',2380 scheduledId: string,2381 blocksNum: number,2382 options: ISchedulerOptions2383 };23842385 super(logger);23862387 this.scheduleFn = options.scheduleFn;2388 this.scheduledId = options.scheduledId;2389 this.blocksNum = options.blocksNum;2390 this.options = options.options;2391 }23922393 executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise<ITransactionResult> {2394 const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams);2395 const extrinsic = 'api.tx.scheduler.' + this.scheduleFn;23962397 return super.executeExtrinsic(2398 sender,2399 extrinsic,2400 [2401 this.scheduledId,2402 this.blocksNum,2403 this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,2404 this.options.priority ?? null,2405 {Value: scheduledTx},2406 ],2407 expectSuccess,2408 );2409 }2410 };2411}24122413// eslint-disable-next-line @typescript-eslint/naming-convention2414function SudoUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {2415 return class extends Base {2416 constructor(...args: any[]) {2417 super(...args);2418 }24192420 executeExtrinsic (2421 sender: IKeyringPair,2422 extrinsic: string,2423 params: any[],2424 expectSuccess?: boolean,2425 ): Promise<ITransactionResult> {2426 const call = this.constructApiCall(extrinsic, params);24272428 return super.executeExtrinsic(2429 sender,2430 'api.tx.sudo.sudo',2431 [call],2432 expectSuccess,2433 );2434 }2435 };2436}226224372263export class UniqueBaseCollection {2438export class UniqueBaseCollection {2264 helper: UniqueHelper;2439 helper: UniqueHelper;2361 return await this.helper.collection.burn(signer, this.collectionId);2536 return await this.helper.collection.burn(signer, this.collectionId);2362 }2537 }25382539 scheduleAt<T extends UniqueHelper>(2540 scheduledId: string,2541 executionBlockNumber: number,2542 options: ISchedulerOptions = {},2543 ) {2544 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2545 return new UniqueBaseCollection(this.collectionId, scheduledHelper);2546 }25472548 scheduleAfter<T extends UniqueHelper>(2549 scheduledId: string,2550 blocksBeforeExecution: number,2551 options: ISchedulerOptions = {},2552 ) {2553 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2554 return new UniqueBaseCollection(this.collectionId, scheduledHelper);2555 }25562557 getSudo<T extends UniqueHelper>() {2558 return new UniqueBaseCollection(this.collectionId, this.helper.getSudo<T>());2559 }2363}2560}23642561236525622448 return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);2645 return await this.helper.nft.unnestToken(signer, {collectionId: this.collectionId, tokenId}, fromTokenObj, toAddressObj);2449 }2646 }26472648 scheduleAt<T extends UniqueHelper>(2649 scheduledId: string,2650 executionBlockNumber: number,2651 options: ISchedulerOptions = {},2652 ) {2653 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2654 return new UniqueNFTCollection(this.collectionId, scheduledHelper);2655 }26562657 scheduleAfter<T extends UniqueHelper>(2658 scheduledId: string,2659 blocksBeforeExecution: number,2660 options: ISchedulerOptions = {},2661 ) {2662 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2663 return new UniqueNFTCollection(this.collectionId, scheduledHelper);2664 }26652666 getSudo<T extends UniqueHelper>() {2667 return new UniqueNFTCollection(this.collectionId, this.helper.getSudo<T>());2668 }2450}2669}24512670245226712531 return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2750 return await this.helper.rft.setTokenPropertyPermissions(signer, this.collectionId, permissions);2532 }2751 }27522753 scheduleAt<T extends UniqueHelper>(2754 scheduledId: string,2755 executionBlockNumber: number,2756 options: ISchedulerOptions = {},2757 ) {2758 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2759 return new UniqueRFTCollection(this.collectionId, scheduledHelper);2760 }27612762 scheduleAfter<T extends UniqueHelper>(2763 scheduledId: string,2764 blocksBeforeExecution: number,2765 options: ISchedulerOptions = {},2766 ) {2767 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2768 return new UniqueRFTCollection(this.collectionId, scheduledHelper);2769 }27702771 getSudo<T extends UniqueHelper>() {2772 return new UniqueRFTCollection(this.collectionId, this.helper.getSudo<T>());2773 }2533}2774}25342775253527762578 return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);2819 return await this.helper.ft.approveTokens(signer, this.collectionId, toAddressObj, amount);2579 }2820 }28212822 scheduleAt<T extends UniqueHelper>(2823 scheduledId: string,2824 executionBlockNumber: number,2825 options: ISchedulerOptions = {},2826 ) {2827 const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);2828 return new UniqueFTCollection(this.collectionId, scheduledHelper);2829 }28302831 scheduleAfter<T extends UniqueHelper>(2832 scheduledId: string,2833 blocksBeforeExecution: number,2834 options: ISchedulerOptions = {},2835 ) {2836 const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2837 return new UniqueFTCollection(this.collectionId, scheduledHelper);2838 }28392840 getSudo<T extends UniqueHelper>() {2841 return new UniqueFTCollection(this.collectionId, this.helper.getSudo<T>());2842 }2580}2843}25812844258228452615 return this.collection.helper.util.getTokenAccount(this);2878 return this.collection.helper.util.getTokenAccount(this);2616 }2879 }28802881 scheduleAt<T extends UniqueHelper>(2882 scheduledId: string,2883 executionBlockNumber: number,2884 options: ISchedulerOptions = {},2885 ) {2886 const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);2887 return new UniqueBaseToken(this.tokenId, scheduledCollection);2888 }28892890 scheduleAfter<T extends UniqueHelper>(2891 scheduledId: string,2892 blocksBeforeExecution: number,2893 options: ISchedulerOptions = {},2894 ) {2895 const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2896 return new UniqueBaseToken(this.tokenId, scheduledCollection);2897 }28982899 getSudo<T extends UniqueHelper>() {2900 return new UniqueBaseToken(this.tokenId, this.collection.getSudo<T>());2901 }2617}2902}26182903261929042673 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj);2958 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj);2674 }2959 }29602961 scheduleAt<T extends UniqueHelper>(2962 scheduledId: string,2963 executionBlockNumber: number,2964 options: ISchedulerOptions = {},2965 ) {2966 const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);2967 return new UniqueNFToken(this.tokenId, scheduledCollection);2968 }29692970 scheduleAfter<T extends UniqueHelper>(2971 scheduledId: string,2972 blocksBeforeExecution: number,2973 options: ISchedulerOptions = {},2974 ) {2975 const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);2976 return new UniqueNFToken(this.tokenId, scheduledCollection);2977 }29782979 getSudo<T extends UniqueHelper>() {2980 return new UniqueNFToken(this.tokenId, this.collection.getSudo<T>());2981 }2675}2982}267629832677export class UniqueRFToken extends UniqueBaseToken {2984export class UniqueRFToken extends UniqueBaseToken {2726 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj, amount);3033 return await this.collection.burnTokenFrom(signer, this.tokenId, fromAddressObj, amount);2727 }3034 }30353036 scheduleAt<T extends UniqueHelper>(3037 scheduledId: string,3038 executionBlockNumber: number,3039 options: ISchedulerOptions = {},3040 ) {3041 const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);3042 return new UniqueRFToken(this.tokenId, scheduledCollection);3043 }30443045 scheduleAfter<T extends UniqueHelper>(3046 scheduledId: string,3047 blocksBeforeExecution: number,3048 options: ISchedulerOptions = {},3049 ) {3050 const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);3051 return new UniqueRFToken(this.tokenId, scheduledCollection);3052 }30533054 getSudo<T extends UniqueHelper>() {3055 return new UniqueRFToken(this.tokenId, this.collection.getSudo<T>());3056 }2728}3057}27293058tests/src/util/util.tsdiffbeforeafterbothno changes
tests/src/xcm/xcmOpal.test.tsdiffbeforeafterboth21import {ApiOptions} from '@polkadot/api/types';21import {ApiOptions} from '@polkadot/api/types';22import {IKeyringPair} from '@polkadot/types/types';22import {IKeyringPair} from '@polkadot/types/types';23import usingApi, {executeTransaction} from './../substrate/substrate-api';23import usingApi, {executeTransaction} from './../substrate/substrate-api';24import {bigIntToDecimals, describe_xcm, getGenericResult, paraSiblingSovereignAccount} from './../util/helpers';24import {bigIntToDecimals, describe_xcm, getGenericResult, paraSiblingSovereignAccount, normalizeAccountId} from './../deprecated-helpers/helpers';25import waitNewBlocks from './../substrate/wait-new-blocks';25import waitNewBlocks from './../substrate/wait-new-blocks';26import {normalizeAccountId} from './../util/helpers';27import getBalance from './../substrate/get-balance';26import getBalance from './../substrate/get-balance';28272928tests/src/xcm/xcmQuartz.test.tsdiffbeforeafterboth21import {ApiOptions} from '@polkadot/api/types';21import {ApiOptions} from '@polkadot/api/types';22import {IKeyringPair} from '@polkadot/types/types';22import {IKeyringPair} from '@polkadot/types/types';23import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';23import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';24import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../util/helpers';24import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../deprecated-helpers/helpers';25import {MultiLocation} from '@polkadot/types/interfaces';25import {MultiLocation} from '@polkadot/types/interfaces';26import {blake2AsHex} from '@polkadot/util-crypto';26import {blake2AsHex} from '@polkadot/util-crypto';27import waitNewBlocks from '../substrate/wait-new-blocks';27import waitNewBlocks from '../substrate/wait-new-blocks';tests/src/xcm/xcmUnique.test.tsdiffbeforeafterboth21import {ApiOptions} from '@polkadot/api/types';21import {ApiOptions} from '@polkadot/api/types';22import {IKeyringPair} from '@polkadot/types/types';22import {IKeyringPair} from '@polkadot/types/types';23import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';23import usingApi, {submitTransactionAsync} from '../substrate/substrate-api';24import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../util/helpers';24import {getGenericResult, generateKeyringPair, waitEvent, describe_xcm, bigIntToDecimals} from '../deprecated-helpers/helpers';25import {MultiLocation} from '@polkadot/types/interfaces';25import {MultiLocation} from '@polkadot/types/interfaces';26import {blake2AsHex} from '@polkadot/util-crypto';26import {blake2AsHex} from '@polkadot/util-crypto';27import waitNewBlocks from '../substrate/wait-new-blocks';27import waitNewBlocks from '../substrate/wait-new-blocks';tests/src/xcmTransfer.test.tsdiffbeforeafterbothno changes
tests/tsconfig.jsondiffbeforeafterboth21 "./src/**/*",21 "./src/**/*",22 "./src/interfaces/*.ts"22 "./src/interfaces/*.ts"23 ],23 ],24 "exclude": [25 "./src/.outdated"26 ],24 "lib": [27 "lib": [25 "es2017"28 "es2017"26 ],29 ],