git.delta.rocks / unique-network / refs/commits / 71ea0c3827eb

difftreelog

source

tests/src/scheduler.test.ts24.7 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {expect, itSub, Pallets, usingPlaygrounds} from './util/playgrounds';18import {IKeyringPair} from '@polkadot/types/types';19import {DevUniqueHelper} from './util/playgrounds/unique.dev';2021describe('Scheduling token and balance transfers', () => {22  let alice: IKeyringPair;23  let bob: IKeyringPair;24  let charlie: IKeyringPair;2526  before(async () => {27    await usingPlaygrounds(async (_, privateKeyWrapper) => {28      alice = privateKeyWrapper('//Alice');29      bob = privateKeyWrapper('//Bob');30      charlie = privateKeyWrapper('//Charlie');31    });32  });3334  itSub.ifWithPallets('Can delay a transfer of an owned token', [Pallets.Scheduler], async ({helper}) => {35    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});36    const token = await collection.mintToken(alice);37    const schedulerId = await helper.arrange.makeScheduledId();38    const blocksBeforeExecution = 4;3940    await token.scheduleAfter(schedulerId, blocksBeforeExecution)41      .transfer(alice, {Substrate: bob.address});4243    expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});4445    await helper.wait.newBlocks(blocksBeforeExecution + 1);4647    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});48  });4950  itSub.ifWithPallets('Can transfer funds periodically', [Pallets.Scheduler], async ({helper}) => {51    const scheduledId = await helper.arrange.makeScheduledId();52    const waitForBlocks = 1;5354    const amount = 1n * helper.balance.getOneTokenNominal();55    const periodic = {56      period: 2,57      repetitions: 2,58    };5960    const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);6162    await helper.scheduler.scheduleAfter(scheduledId, waitForBlocks, {periodic})63      .balance.transferToSubstrate(alice, bob.address, amount);6465    await helper.wait.newBlocks(waitForBlocks + 1);6667    const bobsBalanceAfterFirst = await helper.balance.getSubstrate(bob.address);68    expect(bobsBalanceAfterFirst)69      .to.be.equal(70        bobsBalanceBefore + 1n * amount,71        '#1 Balance of the recipient should be increased by 1 * amount',72      );7374    await helper.wait.newBlocks(periodic.period);7576    const bobsBalanceAfterSecond = await helper.balance.getSubstrate(bob.address);77    expect(bobsBalanceAfterSecond)78      .to.be.equal(79        bobsBalanceBefore + 2n * amount,80        '#2 Balance of the recipient should be increased by 2 * amount',81      );82  });8384  itSub.ifWithPallets('Can cancel a scheduled operation which has not yet taken effect', [Pallets.Scheduler], async ({helper}) => {85    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});86    const token = await collection.mintToken(alice);8788    const scheduledId = await helper.arrange.makeScheduledId();89    const waitForBlocks = 4;9091    expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});9293    await token.scheduleAfter(scheduledId, waitForBlocks)94      .transfer(alice, {Substrate: bob.address});9596    await helper.scheduler.cancelScheduled(alice, scheduledId);9798    await helper.wait.newBlocks(waitForBlocks + 1);99100    expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});101  });102103  itSub.ifWithPallets('Can cancel a periodic operation (transfer of funds)', [Pallets.Scheduler], async ({helper}) => {104    const waitForBlocks = 1;105    const periodic = {106      period: 3,107      repetitions: 2,108    };109110    const scheduledId = await helper.arrange.makeScheduledId();111112    const amount = 1n * helper.balance.getOneTokenNominal();113114    const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);115116    await helper.scheduler.scheduleAfter(scheduledId, waitForBlocks, {periodic})117      .balance.transferToSubstrate(alice, bob.address, amount);118119    await helper.wait.newBlocks(waitForBlocks + 1);120121    const bobsBalanceAfterFirst = await helper.balance.getSubstrate(bob.address);122123    expect(bobsBalanceAfterFirst)124      .to.be.equal(125        bobsBalanceBefore + 1n * amount,126        '#1 Balance of the recipient should be increased by 1 * amount',127      );128129    await helper.scheduler.cancelScheduled(alice, scheduledId);130    await helper.wait.newBlocks(periodic.period);131132    const bobsBalanceAfterSecond = await helper.balance.getSubstrate(bob.address);133    expect(bobsBalanceAfterSecond)134      .to.be.equal(135        bobsBalanceAfterFirst,136        '#2 Balance of the recipient should not be changed',137      );138  });139140  itSub.ifWithPallets('Scheduled tasks are transactional', [Pallets.Scheduler, Pallets.TestUtils], async ({helper}) => {141    const scheduledId = await helper.arrange.makeScheduledId();142    const waitForBlocks = 4;143144    const initTestVal = 42;145    const changedTestVal = 111;146147    await helper.testUtils.setTestValue(alice, initTestVal);148149    await helper.scheduler.scheduleAfter<DevUniqueHelper>(scheduledId, waitForBlocks)150      .testUtils.setTestValueAndRollback(alice, changedTestVal);151152    await helper.wait.newBlocks(waitForBlocks + 1);153154    const testVal = await helper.testUtils.testValue();155    expect(testVal, 'The test value should NOT be commited')156      .to.be.equal(initTestVal);157  });158159  itSub.ifWithPallets('Scheduled tasks should take correct fees', [Pallets.Scheduler, Pallets.TestUtils], async function({helper}) {160    const scheduledId = await helper.arrange.makeScheduledId();161    const waitForBlocks = 4;162    const periodic = {163      period: 2,164      repetitions: 2,165    };166167    const dummyTx = helper.constructApiCall('api.tx.testUtils.justTakeFee', []);168    const scheduledLen = dummyTx.callIndex.length;169170    const expectedScheduledFee = (await helper.getPaymentInfo(alice, dummyTx, scheduledLen))171      .partialFee.toBigInt();172173    await helper.scheduler.scheduleAfter<DevUniqueHelper>(scheduledId, waitForBlocks, {periodic})174      .testUtils.justTakeFee(alice);175176    await helper.wait.newBlocks(1);177178    const aliceInitBalance = await helper.balance.getSubstrate(alice.address);179    let diff;180181    await helper.wait.newBlocks(waitForBlocks);182183    const aliceBalanceAfterFirst = await helper.balance.getSubstrate(alice.address);184    expect(185      aliceBalanceAfterFirst < aliceInitBalance,186      '[after execution #1] Scheduled task should take a fee',187    ).to.be.true;188189    diff = aliceInitBalance - aliceBalanceAfterFirst;190    expect(diff).to.be.equal(191      expectedScheduledFee,192      'Scheduled task should take the right amount of fees',193    );194195    await helper.wait.newBlocks(periodic.period);196197    const aliceBalanceAfterSecond = await helper.balance.getSubstrate(alice.address);198    expect(199      aliceBalanceAfterSecond < aliceBalanceAfterFirst,200      '[after execution #2] Scheduled task should take a fee',201    ).to.be.true;202203    diff = aliceBalanceAfterFirst - aliceBalanceAfterSecond;204    expect(diff).to.be.equal(205      expectedScheduledFee,206      'Scheduled task should take the right amount of fees',207    );208  });209210  // Check if we can cancel a scheduled periodic operation211  // in the same block in which it is running212  itSub.ifWithPallets('Can cancel the periodic sheduled tx when the tx is running', [Pallets.Scheduler, Pallets.TestUtils], async ({helper}) => {213    const currentBlockNumber = await helper.chain.getLatestBlockNumber();214    const blocksBeforeExecution = 10;215    const firstExecutionBlockNumber = currentBlockNumber + blocksBeforeExecution;216217    const [218      scheduledId,219      scheduledCancelId,220    ] = await helper.arrange.makeScheduledIds(2);221222    const periodic = {223      period: 5,224      repetitions: 5,225    };226227    const initTestVal = 0;228    const incTestVal = initTestVal + 1;229    const finalTestVal = initTestVal + 2;230231    await helper.testUtils.setTestValue(alice, initTestVal);232233    await helper.scheduler.scheduleAt<DevUniqueHelper>(scheduledId, firstExecutionBlockNumber, {periodic})234      .testUtils.incTestValue(alice);235236    // Cancel the inc tx after 2 executions237    // *in the same block* in which the second execution is scheduled238    await helper.scheduler.scheduleAt(239      scheduledCancelId,240      firstExecutionBlockNumber + periodic.period,241    ).scheduler.cancelScheduled(alice, scheduledId);242243    await helper.wait.newBlocks(blocksBeforeExecution);244245    // execution #0246    expect(await helper.testUtils.testValue())247      .to.be.equal(incTestVal);248249    await helper.wait.newBlocks(periodic.period);250251    // execution #1252    expect(await helper.testUtils.testValue())253      .to.be.equal(finalTestVal);254255    for (let i = 1; i < periodic.repetitions; i++) {256      await helper.wait.newBlocks(periodic.period);257      expect(await helper.testUtils.testValue())258        .to.be.equal(finalTestVal);259    }260  });261262  itSub.ifWithPallets('A scheduled operation can cancel itself', [Pallets.Scheduler, Pallets.TestUtils], async ({helper}) => {263    const scheduledId = await helper.arrange.makeScheduledId();264    const waitForBlocks = 4;265    const periodic = {266      period: 2,267      repetitions: 5,268    };269270    const initTestVal = 0;271    const maxTestVal = 2;272273    await helper.testUtils.setTestValue(alice, initTestVal);274275    await helper.scheduler.scheduleAfter<DevUniqueHelper>(scheduledId, waitForBlocks, {periodic})276      .testUtils.selfCancelingInc(alice, scheduledId, maxTestVal);277278    await helper.wait.newBlocks(waitForBlocks + 1);279280    // execution #0281    expect(await helper.testUtils.testValue())282      .to.be.equal(initTestVal + 1);283284    await helper.wait.newBlocks(periodic.period);285286    // execution #1287    expect(await helper.testUtils.testValue())288      .to.be.equal(initTestVal + 2);289290    await helper.wait.newBlocks(periodic.period);291292    // <canceled>293    expect(await helper.testUtils.testValue())294      .to.be.equal(initTestVal + 2);295  });296297  itSub.ifWithPallets('Root can cancel any scheduled operation', [Pallets.Scheduler], async ({helper}) => {298    const collection = await helper.nft.mintCollection(bob, {tokenPrefix: 'schd'});299    const token = await collection.mintToken(bob);300301    const scheduledId = await helper.arrange.makeScheduledId();302    const waitForBlocks = 4;303304    await token.scheduleAfter(scheduledId, waitForBlocks)305      .transfer(bob, {Substrate: alice.address});306307    await helper.getSudo().scheduler.cancelScheduled(alice, scheduledId);308309    await helper.wait.newBlocks(waitForBlocks + 1);310311    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});312  });313314  itSub.ifWithPallets('Root can set prioritized scheduled operation', [Pallets.Scheduler], async ({helper}) => {315    const scheduledId = await helper.arrange.makeScheduledId();316    const waitForBlocks = 4;317318    const amount = 42n * helper.balance.getOneTokenNominal();319320    const balanceBefore = await helper.balance.getSubstrate(charlie.address);321322    await helper.getSudo()323      .scheduler.scheduleAfter(scheduledId, waitForBlocks, {priority: 42})324      .balance.forceTransferToSubstrate(alice, bob.address, charlie.address, amount);325326    await helper.wait.newBlocks(waitForBlocks + 1);327328    const balanceAfter = await helper.balance.getSubstrate(charlie.address);329330    expect(balanceAfter > balanceBefore).to.be.true;331332    const diff = balanceAfter - balanceBefore;333    expect(diff).to.be.equal(amount);334  });335336  itSub.ifWithPallets("Root can change scheduled operation's priority", [Pallets.Scheduler], async ({helper}) => {337    const collection = await helper.nft.mintCollection(bob, {tokenPrefix: 'schd'});338    const token = await collection.mintToken(bob);339340    const scheduledId = await helper.arrange.makeScheduledId();341    const waitForBlocks = 6;342343    await token.scheduleAfter(scheduledId, waitForBlocks)344      .transfer(bob, {Substrate: alice.address});345346    const priority = 112;347    await helper.getSudo().scheduler.changePriority(alice, scheduledId, priority);348349    const priorityChanged = await helper.wait.event(350      waitForBlocks,351      'scheduler',352      'PriorityChanged',353    );354355    expect(priorityChanged !== null).to.be.true;356    expect(priorityChanged!.event.data[2].toString()).to.be.equal(priority.toString());357  });358359  itSub.ifWithPallets('Prioritized operations executes in valid order', [Pallets.Scheduler], async ({helper}) => {360    const [361      scheduledFirstId,362      scheduledSecondId,363    ] = await helper.arrange.makeScheduledIds(2);364365    const currentBlockNumber = await helper.chain.getLatestBlockNumber();366    const blocksBeforeExecution = 4;367    const firstExecutionBlockNumber = currentBlockNumber + blocksBeforeExecution;368369    const prioHigh = 0;370    const prioLow = 255;371372    const periodic = {373      period: 6,374      repetitions: 2,375    };376377    const amount = 1n * helper.balance.getOneTokenNominal();378379    // Scheduler a task with a lower priority first, then with a higher priority380    await helper.getSudo().scheduler.scheduleAt(scheduledFirstId, firstExecutionBlockNumber, {priority: prioLow, periodic})381      .balance.forceTransferToSubstrate(alice, alice.address, bob.address, amount);382383    await helper.getSudo().scheduler.scheduleAt(scheduledSecondId, firstExecutionBlockNumber, {priority: prioHigh, periodic})384      .balance.forceTransferToSubstrate(alice, alice.address, bob.address, amount);385386    const capture = await helper.arrange.captureEvents('scheduler', 'Dispatched');387388    await helper.wait.newBlocks(blocksBeforeExecution);389390    // Flip priorities391    await helper.getSudo().scheduler.changePriority(alice, scheduledFirstId, prioHigh);392    await helper.getSudo().scheduler.changePriority(alice, scheduledSecondId, prioLow);393394    await helper.wait.newBlocks(periodic.period);395396    const dispatchEvents = capture.extractCapturedEvents();397    expect(dispatchEvents.length).to.be.equal(4);398399    const dispatchedIds = dispatchEvents.map(r => r.event.data[1].toString());400401    const firstExecuctionIds = [dispatchedIds[0], dispatchedIds[1]];402    const secondExecuctionIds = [dispatchedIds[2], dispatchedIds[3]];403404    expect(firstExecuctionIds[0]).to.be.equal(scheduledSecondId);405    expect(firstExecuctionIds[1]).to.be.equal(scheduledFirstId);406407    expect(secondExecuctionIds[0]).to.be.equal(scheduledFirstId);408    expect(secondExecuctionIds[1]).to.be.equal(scheduledSecondId);409  });410});411412describe('Negative Test: Scheduling', () => {413  let alice: IKeyringPair;414  let bob: IKeyringPair;415416  before(async () => {417    await usingPlaygrounds(async (_, privateKeyWrapper) => {418      alice = privateKeyWrapper('//Alice');419      bob = privateKeyWrapper('//Bob');420    });421  });422423  itSub.ifWithPallets("Can't overwrite a scheduled ID", [Pallets.Scheduler], async ({helper}) => {424    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});425    const token = await collection.mintToken(alice);426427    const scheduledId = await helper.arrange.makeScheduledId();428    const waitForBlocks = 4;429430    await token.scheduleAfter(scheduledId, waitForBlocks)431      .transfer(alice, {Substrate: bob.address});432433    const scheduled = helper.scheduler.scheduleAfter(scheduledId, waitForBlocks);434    await expect(scheduled.balance.transferToSubstrate(alice, bob.address, 1n * helper.balance.getOneTokenNominal()))435      .to.be.rejectedWith(/scheduler\.FailedToSchedule/);436437    const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);438439    await helper.wait.newBlocks(waitForBlocks + 1);440441    const bobsBalanceAfter = await helper.balance.getSubstrate(bob.address);442443    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});444    expect(bobsBalanceBefore).to.be.equal(bobsBalanceAfter);445  });446447  itSub.ifWithPallets("Can't cancel an operation which is not scheduled", [Pallets.Scheduler], async ({helper}) => {448    const scheduledId = await helper.arrange.makeScheduledId();449    await expect(helper.scheduler.cancelScheduled(alice, scheduledId))450      .to.be.rejectedWith(/scheduler\.NotFound/);451  });452453  itSub.ifWithPallets("Can't cancel a non-owned scheduled operation", [Pallets.Scheduler], async ({helper}) => {454    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});455    const token = await collection.mintToken(alice);456457    const scheduledId = await helper.arrange.makeScheduledId();458    const waitForBlocks = 4;459460    await token.scheduleAfter(scheduledId, waitForBlocks)461      .transfer(alice, {Substrate: bob.address});462463    await expect(helper.scheduler.cancelScheduled(bob, scheduledId))464      .to.be.rejectedWith(/BadOrigin/);465466    await helper.wait.newBlocks(waitForBlocks + 1);467468    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});469  });470471  itSub.ifWithPallets("Regular user can't set prioritized scheduled operation", [Pallets.Scheduler], async ({helper}) => {472    const scheduledId = await helper.arrange.makeScheduledId();473    const waitForBlocks = 4;474475    const amount = 42n * helper.balance.getOneTokenNominal();476477    const balanceBefore = await helper.balance.getSubstrate(bob.address);478479    const scheduled = helper.scheduler.scheduleAfter(scheduledId, waitForBlocks, {priority: 42});480    481    await expect(scheduled.balance.transferToSubstrate(alice, bob.address, amount))482      .to.be.rejectedWith(/BadOrigin/);483484    await helper.wait.newBlocks(waitForBlocks + 1);485486    const balanceAfter = await helper.balance.getSubstrate(bob.address);487488    expect(balanceAfter).to.be.equal(balanceBefore);489  });490491  itSub.ifWithPallets("Regular user can't change scheduled operation's priority", [Pallets.Scheduler], async ({helper}) => {492    const collection = await helper.nft.mintCollection(bob, {tokenPrefix: 'schd'});493    const token = await collection.mintToken(bob);494495    const scheduledId = await helper.arrange.makeScheduledId();496    const waitForBlocks = 4;497498    await token.scheduleAfter(scheduledId, waitForBlocks)499      .transfer(bob, {Substrate: alice.address});500501    const priority = 112;502    await expect(helper.scheduler.changePriority(alice, scheduledId, priority))503      .to.be.rejectedWith(/BadOrigin/);504505    const priorityChanged = await helper.wait.event(506      waitForBlocks,507      'scheduler',508      'PriorityChanged',509    );510511    expect(priorityChanged === null).to.be.true;512  });513});514515// Implementation of the functionality tested here was postponed/shelved516describe.skip('Sponsoring scheduling', () => {517  // let alice: IKeyringPair;518  // let bob: IKeyringPair;519520  // before(async() => {521  //   await usingApi(async (_, privateKeyWrapper) => {522  //     alice = privateKeyWrapper('//Alice');523  //     bob = privateKeyWrapper('//Bob');524  //   });525  // });526527  it('Can sponsor scheduling a transaction', async () => {528    // const collectionId = await createCollectionExpectSuccess();529    // await setCollectionSponsorExpectSuccess(collectionId, bob.address);530    // await confirmSponsorshipExpectSuccess(collectionId, '//Bob');531532    // await usingApi(async api => {533    //   const scheduledId = await makeScheduledId();534    //   const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);535536    //   const bobBalanceBefore = await getFreeBalance(bob);537    //   const waitForBlocks = 4;538    //   // no need to wait to check, fees must be deducted on scheduling, immediately539    //   await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 0, waitForBlocks, scheduledId);540    //   const bobBalanceAfter = await getFreeBalance(bob);541    //   // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;542    //   expect(bobBalanceAfter < bobBalanceBefore).to.be.true;543    //   // wait for sequentiality matters544    //   await waitNewBlocks(waitForBlocks - 1);545    // });546  });547548  it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => {549    // await usingApi(async (api, privateKeyWrapper) => {550    //   // Find an empty, unused account551    //   const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);552553    //   const collectionId = await createCollectionExpectSuccess();554555    //   // Add zeroBalance address to allow list556    //   await enablePublicMintingExpectSuccess(alice, collectionId);557    //   await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);558559    //   // Grace zeroBalance with money, enough to cover future transactions560    //   const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);561    //   await submitTransactionAsync(alice, balanceTx);562563    //   // Mint a fresh NFT564    //   const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT');565    //   const scheduledId = await makeScheduledId();566567    //   // Schedule transfer of the NFT a few blocks ahead568    //   const waitForBlocks = 5;569    //   await scheduleTransferExpectSuccess(api, collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, scheduledId);570571    //   // Get rid of the account's funds before the scheduled transaction takes place572    //   const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n);573    //   const events = await submitTransactionAsync(zeroBalance, balanceTx2);574    //   expect(getGenericResult(events).success).to.be.true;575    //   /*const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved?576    //   const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any);577    //   const events = await submitTransactionAsync(alice, sudoTx);578    //   expect(getGenericResult(events).success).to.be.true;*/579580    //   // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions581    //   await waitNewBlocks(waitForBlocks - 3);582583    //   expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));584    // });585  });586587  it('Sponsor going bankrupt does not impact a scheduled transaction', async () => {588    // const collectionId = await createCollectionExpectSuccess();589590    // await usingApi(async (api, privateKeyWrapper) => {591    //   const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);592    //   const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);593    //   await submitTransactionAsync(alice, balanceTx);594595    //   await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address);596    //   await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance);597598    //   const scheduledId = await makeScheduledId();599    //   const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);600601    //   const waitForBlocks = 5;602    //   await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, scheduledId);603604    //   const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);605    //   const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);606    //   const events = await submitTransactionAsync(alice, sudoTx);607    //   expect(getGenericResult(events).success).to.be.true;608609    //   // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions610    //   await waitNewBlocks(waitForBlocks - 3);611612    //   expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address));613    // });614  });615616  it('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => {617    // const collectionId = await createCollectionExpectSuccess();618    // await setCollectionSponsorExpectSuccess(collectionId, bob.address);619    // await confirmSponsorshipExpectSuccess(collectionId, '//Bob');620621    // await usingApi(async (api, privateKeyWrapper) => {622    //   const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);623624    //   await enablePublicMintingExpectSuccess(alice, collectionId);625    //   await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);626627    //   const bobBalanceBefore = await getFreeBalance(bob);628629    //   const createData = {nft: {const_data: [], variable_data: []}};630    //   const creationTx = api.tx.unique.createItem(collectionId, normalizeAccountId(zeroBalance), createData as any);631    //   const scheduledId = await makeScheduledId();632633    //   /*const badTransaction = async function () {634    //     await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);635    //   };636    //   await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/637638    //   await expect(scheduleAfter(api, creationTx, zeroBalance, 3, scheduledId, 1, 3)).to.be.rejectedWith(/Inability to pay some fees/);639640    //   expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore);641    // });642  });643});