difftreelog
test(scheduler) enable and add more coverage, leave sponsorship disabled
in: master
2 files changed
tests/src/.outdated/scheduler.test.tsdiffbeforeafterboth35 normalizeAccountId,35 normalizeAccountId,36 getTokenOwner,36 getTokenOwner,37 getGenericResult,37 getGenericResult,38 scheduleTransferFundsPeriodicExpectSuccess,38 scheduleTransferFundsExpectSuccess,39 getFreeBalance,39 getFreeBalance,40 confirmSponsorshipByKeyExpectSuccess,40 confirmSponsorshipByKeyExpectSuccess,41 scheduleExpectFailure,41 scheduleExpectFailure,42 scheduleAfter,43 cancelScheduled,42} from '../deprecated-helpers/helpers';44} from '../deprecated-helpers/helpers';43import {IKeyringPair} from '@polkadot/types/types';45import {IKeyringPair} from '@polkadot/types/types';46import {ApiPromise} from '@polkadot/api';444745chai.use(chaiAsPromised);48chai.use(chaiAsPromised);464947// todo:playgrounds skipped ~ postponed50const scheduledIdBase: string = '0x' + '0'.repeat(31);51let scheduledIdSlider = 0;5253// Loop scheduledId around 10. Unless there are concurrent tasks with long periods/repetitions, tests' tasks' ids shouldn't ovelap.54function makeScheduledId(): string {55 return scheduledIdBase + ((scheduledIdSlider++) % 10);56}5758// Check that there are no failing Dispatched events in the block59function checkForFailedSchedulerEvents(api: ApiPromise, events: any[]) {60 return new Promise((res, rej) => {61 let schedulerEventPresent = false;62 63 for (const {event} of events) {64 if (api.events.scheduler.Dispatched.is(event)) {65 schedulerEventPresent = true;66 const result = event.data.result;67 if (result.isErr) {68 const decoded = api.registry.findMetaError(result.asErr.asModule);69 const {method, section} = decoded;70 rej(new Error(`${section}.${method}`));71 }72 }73 }74 res(schedulerEventPresent);75 });76}7778describe('Scheduling token and balance transfers', () => {79 let alice: IKeyringPair;80 let bob: IKeyringPair;8182 before(async() => {83 await usingApi(async (_, privateKeyWrapper) => {84 alice = privateKeyWrapper('//Alice');85 bob = privateKeyWrapper('//Bob');86 });87 });888990 it('Can delay a transfer of an owned token', async () => {91 await usingApi(async api => {92 const collectionId = await createCollectionExpectSuccess();93 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');9495 await scheduleTransferAndWaitExpectSuccess(api, collectionId, tokenId, alice, bob, 1, 4, makeScheduledId());96 });97 });9899 it('Can transfer funds periodically', async () => {100 await usingApi(async api => {101 const waitForBlocks = 1;102 const period = 2;103 const repetitions = 2;104105 await scheduleTransferFundsExpectSuccess(api, 1n * UNIQUE, alice, bob, waitForBlocks, makeScheduledId(), period, repetitions);106 const bobsBalanceBefore = await getFreeBalance(bob);107108 await waitNewBlocks(waitForBlocks + 1);109 const bobsBalanceAfterFirst = await getFreeBalance(bob);110 expect(bobsBalanceAfterFirst > bobsBalanceBefore, '#1 Balance of the recipient did not increase').to.be.true;111112 await waitNewBlocks(period);113 const bobsBalanceAfterSecond = await getFreeBalance(bob);114 expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst, '#2 Balance of the recipient did not increase').to.be.true;115 });116 });117118 it('Can cancel a scheduled operation which has not yet taken effect', async () => {119 await usingApi(async api => {120 const collectionId = await createCollectionExpectSuccess();121 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');122 const scheduledId = makeScheduledId();123 const waitForBlocks = 4;124125 await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 1, waitForBlocks, scheduledId);126 await expect(cancelScheduled(api, alice, scheduledId)).to.not.be.rejected;127128 await waitNewBlocks(waitForBlocks);129130 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));131 });132 });133134 it('Can cancel a periodic operation (transfer of funds)', async () => {135 await usingApi(async api => {136 const waitForBlocks = 1;137 const period = 3;138 const repetitions = 2;139140 const scheduledId = makeScheduledId();141142 const bobsBalanceBefore = await getFreeBalance(bob);143 await scheduleTransferFundsExpectSuccess(api, 1n * UNIQUE, alice, bob, waitForBlocks, scheduledId, period, repetitions);144145 await waitNewBlocks(waitForBlocks + 1);146 const bobsBalanceAfterFirst = await getFreeBalance(bob);147 expect(bobsBalanceAfterFirst > bobsBalanceBefore, '#1 Balance of the recipient did not increase').to.be.true;148149 await expect(cancelScheduled(api, alice, scheduledId)).to.not.be.rejected;150151 await waitNewBlocks(period);152 const bobsBalanceAfterSecond = await getFreeBalance(bob);153 expect(bobsBalanceAfterSecond == bobsBalanceAfterFirst, '#2 Balance of the recipient changed').to.be.true;154 });155 });156157 it('Can schedule a scheduled operation of canceling the scheduled operation', async () => {158 await usingApi(async api => {159 const scheduledId = makeScheduledId();160161 const waitForBlocks = 2;162 const period = 3;163 const repetitions = 2;164165 await expect(scheduleAfter(166 api, 167 api.tx.scheduler.cancelNamed(scheduledId), 168 alice, 169 waitForBlocks, 170 scheduledId, 171 period, 172 repetitions,173 )).to.not.be.rejected;174175176 await waitNewBlocks(waitForBlocks);177178 // todo:scheduler debug line; doesn't work (and doesn't appear in events) when executed in the same block as the scheduled transaction179 //await expect(executeTransaction(api, alice, api.tx.scheduler.cancelNamed(scheduledId))).to.not.be.rejected;180181 let schedulerEvents = 0;182 for (let i = 0; i < period * repetitions; i++) {183 const events = await api.query.system.events();184 schedulerEvents += await expect(checkForFailedSchedulerEvents(api, events)).to.not.be.rejected;185 await waitNewBlocks(1);186 }187 expect(schedulerEvents).to.be.equal(repetitions);188 });189 });190191 after(async () => {192 // todo:scheduler to avoid the failed results of the previous test interfering with the next, delete after the problem is fixed193 await waitNewBlocks(6);194 });195});196197describe('Negative Test: Scheduling', () => {198 let alice: IKeyringPair;199 let bob: IKeyringPair;200201 before(async() => {202 await usingApi(async (_, privateKeyWrapper) => {203 alice = privateKeyWrapper('//Alice');204 bob = privateKeyWrapper('//Bob');205 });206 });207208 it('Can\'t overwrite a scheduled ID', async () => {209 await usingApi(async api => {210 const collectionId = await createCollectionExpectSuccess();211 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');212 const scheduledId = makeScheduledId();213214 await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 1, 4, scheduledId);215 await expect(scheduleAfter(216 api, 217 api.tx.balances.transfer(alice.address, 1n * UNIQUE), 218 bob, 219 2, 220 scheduledId,221 )).to.be.rejectedWith(/scheduler\.FailedToSchedule/);222 const bobsBalance = await getFreeBalance(bob);223224 await waitNewBlocks(3);225226 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(bob.address));227 expect(bobsBalance).to.be.equal(await getFreeBalance(bob));228 });229 });230231 it('Can\'t cancel an operation which is not scheduled', async () => {232 await usingApi(async api => {233 const scheduledId = makeScheduledId();234 await expect(cancelScheduled(api, alice, scheduledId)).to.be.rejectedWith(/scheduler\.NotFound/);235 });236 });237238 it('Can\'t cancel a non-owned scheduled operation', async () => {239 await usingApi(async api => {240 const collectionId = await createCollectionExpectSuccess();241 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');242 const scheduledId = makeScheduledId();243 const waitForBlocks = 3;244245 await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 1, waitForBlocks, scheduledId);246 await expect(cancelScheduled(api, bob, scheduledId)).to.be.rejected;247248 await waitNewBlocks(waitForBlocks);249250 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));251 });252 });253});254255// Implementation of the functionality tested here was postponed/shelved48describe.skip('Scheduling token and balance transfers', () => {256describe.skip('Sponsoring scheduling', () => {49 let alice: IKeyringPair;257 let alice: IKeyringPair;50 let bob: IKeyringPair;258 let bob: IKeyringPair;51 let scheduledIdBase: string;52 let scheduledIdSlider: number;5325954 before(async() => {260 before(async() => {55 await usingApi(async (api, privateKeyWrapper) => {261 await usingApi(async (_, privateKeyWrapper) => {56 alice = privateKeyWrapper('//Alice');262 alice = privateKeyWrapper('//Alice');57 bob = privateKeyWrapper('//Bob');263 bob = privateKeyWrapper('//Bob');58 });264 });5960 scheduledIdBase = '0x' + '0'.repeat(31);61 scheduledIdSlider = 0;62 });265 });6364 // Loop scheduledId around 10. Unless there are concurrent tasks with long periods/repetitions, tests' tasks' ids shouldn't ovelap.65 function makeScheduledId(): string {66 return scheduledIdBase + ((scheduledIdSlider++) % 10);67 }6869 it('Can schedule a transfer of an owned token with delay', async () => {70 await usingApi(async () => {71 const nftCollectionId = await createCollectionExpectSuccess();72 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');73 await setCollectionSponsorExpectSuccess(nftCollectionId, alice.address);74 await confirmSponsorshipExpectSuccess(nftCollectionId);7576 await scheduleTransferAndWaitExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 4, makeScheduledId());77 });78 });7980 it('Can transfer funds periodically', async () => {81 await usingApi(async () => {82 const waitForBlocks = 4;83 const period = 2;84 await scheduleTransferFundsPeriodicExpectSuccess(1n * UNIQUE, alice, bob, waitForBlocks, makeScheduledId(), period, 2);85 const bobsBalanceBefore = await getFreeBalance(bob);8687 // discounting already waited-for operations88 await waitNewBlocks(waitForBlocks - 2);89 const bobsBalanceAfterFirst = await getFreeBalance(bob);90 expect(bobsBalanceAfterFirst > bobsBalanceBefore).to.be.true;9192 await waitNewBlocks(period);93 const bobsBalanceAfterSecond = await getFreeBalance(bob);94 expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst).to.be.true;95 });96 });9726698 it('Can sponsor scheduling a transaction', async () => {267 it('Can sponsor scheduling a transaction', async () => {99 const collectionId = await createCollectionExpectSuccess();268 const collectionId = await createCollectionExpectSuccess();100 await setCollectionSponsorExpectSuccess(collectionId, bob.address);269 await setCollectionSponsorExpectSuccess(collectionId, bob.address);101 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');270 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');102271103 await usingApi(async () => {272 await usingApi(async api => {104 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);273 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);105274106 const bobBalanceBefore = await getFreeBalance(bob);275 const bobBalanceBefore = await getFreeBalance(bob);107 const waitForBlocks = 4;276 const waitForBlocks = 4;108 // no need to wait to check, fees must be deducted on scheduling, immediately277 // no need to wait to check, fees must be deducted on scheduling, immediately109 await scheduleTransferExpectSuccess(collectionId, tokenId, alice, bob, 0, waitForBlocks, makeScheduledId());278 await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 0, waitForBlocks, makeScheduledId());110 const bobBalanceAfter = await getFreeBalance(bob);279 const bobBalanceAfter = await getFreeBalance(bob);111 // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;280 // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;112 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;281 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;135304136 // Schedule transfer of the NFT a few blocks ahead305 // Schedule transfer of the NFT a few blocks ahead137 const waitForBlocks = 5;306 const waitForBlocks = 5;138 await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, makeScheduledId());307 await scheduleTransferExpectSuccess(api, collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, makeScheduledId());139308140 // Get rid of the account's funds before the scheduled transaction takes place309 // Get rid of the account's funds before the scheduled transaction takes place141 const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n);310 const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n);167 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);336 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);168337169 const waitForBlocks = 5;338 const waitForBlocks = 5;170 await scheduleTransferExpectSuccess(collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, makeScheduledId());339 await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, makeScheduledId());171340172 const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);341 const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);173 const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);342 const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);181 });350 });182 });351 });183352184 it.skip('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => {353 it('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => {185 const collectionId = await createCollectionExpectSuccess();354 const collectionId = await createCollectionExpectSuccess();186 await setCollectionSponsorExpectSuccess(collectionId, bob.address);355 await setCollectionSponsorExpectSuccess(collectionId, bob.address);187 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');356 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');202 };371 };203 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/372 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/204373205 await scheduleExpectFailure(creationTx, zeroBalance, 3, makeScheduledId(), 1, 3);374 await expect(scheduleAfter(api, creationTx, zeroBalance, 3, makeScheduledId(), 1, 3)).to.be.rejectedWith(/Inability to pay some fees/);206375207 expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore);376 expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore);208 });377 });tests/src/deprecated-helpers/helpers.tsdiffbeforeafterbothno changes