git.delta.rocks / unique-network / refs/commits / f71c05b56b64

difftreelog

fix test both scheduling variants - anon and named

Daniel Shiposha2022-11-10parent: #786ff7e.patch.diff
in: master

8 files changed

modifiedtests/src/eth/scheduling.test.tsdiffbeforeafterboth
--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -15,7 +15,7 @@
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
 import {expect} from 'chai';
-import {EthUniqueHelper, itEth} from './util';
+import {EthUniqueHelper, itSchedEth} from './util';
 import {Pallets, usingPlaygrounds} from '../util';
 
 describe('Scheduing EVM smart contracts', () => {
@@ -26,11 +26,11 @@
     });
   });
 
-  itEth.ifWithPallets('Successfully schedules and periodically executes an EVM contract', [Pallets.Scheduler], async ({helper, privateKey}) => {
+  itSchedEth.ifWithPallets('Successfully schedules and periodically executes an EVM contract', [Pallets.Scheduler], async (scheduleKind, {helper, privateKey}) => {
     const donor = await privateKey({filename: __filename});
     const [alice] = await helper.arrange.createAccounts([1000n], donor);
 
-    const scheduledId = await helper.arrange.makeScheduledId();
+    const scheduledId = scheduleKind == 'named' ? helper.arrange.makeScheduledId() : undefined;
 
     const deployer = await helper.eth.createAccountWithBalance(alice);
     const flipper = await helper.eth.deployFlipper(deployer);
@@ -44,7 +44,7 @@
       repetitions: 2,
     };
 
-    await helper.scheduler.scheduleAfter<EthUniqueHelper>(scheduledId, waitForBlocks, {periodic})
+    await helper.scheduler.scheduleAfter<EthUniqueHelper>(waitForBlocks, {scheduledId, periodic})
       .eth.sendEVM(
         alice,
         flipper.options.address,
modifiedtests/src/eth/util/index.tsdiffbeforeafterboth
--- a/tests/src/eth/util/index.ts
+++ b/tests/src/eth/util/index.ts
@@ -8,6 +8,7 @@
 
 import {EthUniqueHelper} from './playgrounds/unique.dev';
 import {SilentLogger, SilentConsole} from '../../util/playgrounds/unique.dev';
+import {SchedKind} from '../../util';
 
 export {EthUniqueHelper} from './playgrounds/unique.dev';
 
@@ -81,3 +82,19 @@
 itEthIfWithPallet.only = (name: string, required: string[], cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any) => itEthIfWithPallet(name, required, cb, {only: true});
 itEthIfWithPallet.skip = (name: string, required: string[], cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any) => itEthIfWithPallet(name, required, cb, {skip: true});
 itEth.ifWithPallets = itEthIfWithPallet;
+
+export function itSchedEth(
+  name: string,
+  cb: (schedKind: SchedKind, apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any,
+  opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {},
+) {
+  itEth(name + ' (anonymous scheduling)', (apis) => cb('anon', apis), opts);
+  itEth(name + ' (named scheduling)', (apis) => cb('named', apis), opts);
+}
+itSchedEth.only = (name: string, cb: (schedKind: SchedKind, apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any) => itSchedEth(name, cb, {only: true});
+itSchedEth.skip = (name: string, cb: (schedKind: SchedKind, apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any) => itSchedEth(name, cb, {skip: true});
+itSchedEth.ifWithPallets = itSchedIfWithPallets;
+
+function itSchedIfWithPallets(name: string, required: string[], cb: (schedKind: SchedKind, apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {
+  return itSchedEth(name, cb, {requiredPallets: required, ...opts});
+}
modifiedtests/src/maintenanceMode.seqtest.tsdiffbeforeafterboth
--- a/tests/src/maintenanceMode.seqtest.ts
+++ b/tests/src/maintenanceMode.seqtest.ts
@@ -16,7 +16,7 @@
 
 import {IKeyringPair} from '@polkadot/types/types';
 import {ApiPromise} from '@polkadot/api';
-import {expect, itSub, Pallets, usingPlaygrounds} from './util';
+import {expect, itSched, itSub, Pallets, usingPlaygrounds} from './util';
 import {itEth} from './eth/util';
 
 async function maintenanceEnabled(api: ApiPromise): Promise<boolean> {
@@ -162,7 +162,7 @@
     await expect(helper.balance.transferToSubstrate(bob, superuser.address, 1n)).to.be.fulfilled;
   });
 
-  itSub.ifWithPallets('MM blocks scheduled calls and the scheduler itself', [Pallets.Scheduler], async ({helper}) => {
+  itSched.ifWithPallets('MM blocks scheduled calls and the scheduler itself', [Pallets.Scheduler], async (scheduleKind, {helper}) => {
     const collection = await helper.nft.mintCollection(bob);
 
     const nftBeforeMM = await collection.mintToken(bob);
@@ -175,23 +175,25 @@
       scheduledIdBunkerThroughMM,
       scheduledIdAttemptDuringMM,
       scheduledIdAfterMM,
-    ] = await helper.arrange.makeScheduledIds(5);
+    ] = scheduleKind == 'named'
+      ? helper.arrange.makeScheduledIds(5)
+      : new Array(5);
 
     const blocksToWait = 6;
 
     // Scheduling works before the maintenance
-    await nftBeforeMM.scheduleAfter(scheduledIdBeforeMM, blocksToWait)
+    await nftBeforeMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdBeforeMM})
       .transfer(bob, {Substrate: superuser.address});
 
     await helper.wait.newBlocks(blocksToWait + 1);
     expect(await nftBeforeMM.getOwner()).to.be.deep.equal({Substrate: superuser.address});
 
     // Schedule a transaction that should occur *during* the maintenance
-    await nftDuringMM.scheduleAfter(scheduledIdDuringMM, blocksToWait)
+    await nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdDuringMM})
       .transfer(bob, {Substrate: superuser.address});
     
     // Schedule a transaction that should occur *after* the maintenance
-    await nftDuringMM.scheduleAfter(scheduledIdBunkerThroughMM, blocksToWait * 2)
+    await nftDuringMM.scheduleAfter(blocksToWait * 2, {scheduledId: scheduledIdBunkerThroughMM})
       .transfer(bob, {Substrate: superuser.address});
 
     await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []);
@@ -202,7 +204,7 @@
     expect(await nftDuringMM.getOwner()).to.be.deep.equal({Substrate: bob.address});
 
     // Any attempts to schedule a tx during the MM should be rejected
-    await expect(nftDuringMM.scheduleAfter(scheduledIdAttemptDuringMM, blocksToWait)
+    await expect(nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAttemptDuringMM})
       .transfer(bob, {Substrate: superuser.address}))
       .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/);
 
@@ -210,7 +212,7 @@
     expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false;
 
     // Scheduling works after the maintenance
-    await nftAfterMM.scheduleAfter(scheduledIdAfterMM, blocksToWait)
+    await nftAfterMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAfterMM})
       .transfer(bob, {Substrate: superuser.address});
     
     await helper.wait.newBlocks(blocksToWait + 1);
modifiedtests/src/scheduler.seqtest.tsdiffbeforeafterboth
before · tests/src/scheduler.seqtest.ts
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, requirePalletsOrSkip, usingPlaygrounds} from './util';18import {IKeyringPair} from '@polkadot/types/types';19import {DevUniqueHelper} from './util/playgrounds/unique.dev';2021describe('Scheduling token and balance transfers', () => {22  let superuser: IKeyringPair;23  let alice: IKeyringPair;24  let bob: IKeyringPair;25  let charlie: IKeyringPair;2627  before(async function() {28    await usingPlaygrounds(async (helper, privateKey) => {29      requirePalletsOrSkip(this, helper, [Pallets.Scheduler]);3031      superuser = await privateKey('//Alice');32      const donor = await privateKey({filename: __filename});33      [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 100n], donor);3435      await helper.testUtils.enable();36    });37  });3839  itSub('Can delay a transfer of an owned token', async ({helper}) => {40    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});41    const token = await collection.mintToken(alice);42    const schedulerId = await helper.arrange.makeScheduledId();43    const blocksBeforeExecution = 4;44    45    await token.scheduleAfter(schedulerId, blocksBeforeExecution)46      .transfer(alice, {Substrate: bob.address});47    const executionBlock = await helper.chain.getLatestBlockNumber() + blocksBeforeExecution + 1;4849    expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});5051    await helper.wait.forParachainBlockNumber(executionBlock);5253    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});54  });5556  itSub('Can transfer funds periodically', async ({helper}) => {57    const scheduledId = await helper.arrange.makeScheduledId();58    const waitForBlocks = 1;5960    const amount = 1n * helper.balance.getOneTokenNominal();61    const periodic = {62      period: 2,63      repetitions: 2,64    };6566    const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);6768    await helper.scheduler.scheduleAfter(scheduledId, waitForBlocks, {periodic})69      .balance.transferToSubstrate(alice, bob.address, amount);70    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;7172    await helper.wait.forParachainBlockNumber(executionBlock);7374    const bobsBalanceAfterFirst = await helper.balance.getSubstrate(bob.address);75    expect(bobsBalanceAfterFirst)76      .to.be.equal(77        bobsBalanceBefore + 1n * amount,78        '#1 Balance of the recipient should be increased by 1 * amount',79      );8081    await helper.wait.forParachainBlockNumber(executionBlock + periodic.period);8283    const bobsBalanceAfterSecond = await helper.balance.getSubstrate(bob.address);84    expect(bobsBalanceAfterSecond)85      .to.be.equal(86        bobsBalanceBefore + 2n * amount,87        '#2 Balance of the recipient should be increased by 2 * amount',88      );89  });9091  itSub('Can cancel a scheduled operation which has not yet taken effect', async ({helper}) => {92    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});93    const token = await collection.mintToken(alice);9495    const scheduledId = await helper.arrange.makeScheduledId();96    const waitForBlocks = 4;9798    expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});99100    await token.scheduleAfter(scheduledId, waitForBlocks)101      .transfer(alice, {Substrate: bob.address});102    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;103104    await helper.scheduler.cancelScheduled(alice, scheduledId);105106    await helper.wait.forParachainBlockNumber(executionBlock);107108    expect(await token.getOwner()).to.be.deep.equal({Substrate: alice.address});109  });110111  itSub('Can cancel a periodic operation (transfer of funds)', async ({helper}) => {112    const waitForBlocks = 1;113    const periodic = {114      period: 3,115      repetitions: 2,116    };117118    const scheduledId = await helper.arrange.makeScheduledId();119120    const amount = 1n * helper.balance.getOneTokenNominal();121122    const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);123124    await helper.scheduler.scheduleAfter(scheduledId, waitForBlocks, {periodic})125      .balance.transferToSubstrate(alice, bob.address, amount);126    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;127128    await helper.wait.forParachainBlockNumber(executionBlock);129130    const bobsBalanceAfterFirst = await helper.balance.getSubstrate(bob.address);131132    expect(bobsBalanceAfterFirst)133      .to.be.equal(134        bobsBalanceBefore + 1n * amount,135        '#1 Balance of the recipient should be increased by 1 * amount',136      );137138    await helper.scheduler.cancelScheduled(alice, scheduledId);139    await helper.wait.forParachainBlockNumber(executionBlock + periodic.period);140141    const bobsBalanceAfterSecond = await helper.balance.getSubstrate(bob.address);142    expect(bobsBalanceAfterSecond)143      .to.be.equal(144        bobsBalanceAfterFirst,145        '#2 Balance of the recipient should not be changed',146      );147  });148149  itSub('scheduler will not insert more tasks than allowed', async ({helper}) => {150    const maxScheduledPerBlock = 50;151    const scheduledIds = await helper.arrange.makeScheduledIds(maxScheduledPerBlock + 1);152    const fillScheduledIds = scheduledIds.slice(0, maxScheduledPerBlock);153    const extraScheduledId = scheduledIds[maxScheduledPerBlock];154155    // Since the dev node has Instant Seal,156    // we need a larger gap between the current block and the target one.157    //158    // We will schedule `maxScheduledPerBlock` transaction into the target block,159    // so we need at least `maxScheduledPerBlock`-wide gap.160    // We add some additional blocks to this gap to mitigate possible PolkadotJS delays.161    const waitForBlocks = await helper.arrange.isDevNode() ? maxScheduledPerBlock + 5 : 5;162163    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks;164165    const amount = 1n * helper.balance.getOneTokenNominal();166167    const balanceBefore = await helper.balance.getSubstrate(bob.address);168169    // Fill the target block170    for (let i = 0; i < maxScheduledPerBlock; i++) {171      await helper.scheduler.scheduleAt(fillScheduledIds[i], executionBlock)172        .balance.transferToSubstrate(superuser, bob.address, amount);173    }174175    // Try to schedule a task into a full block176    await expect(helper.scheduler.scheduleAt(extraScheduledId, executionBlock)177      .balance.transferToSubstrate(superuser, bob.address, amount))178      .to.be.rejectedWith(/scheduler\.AgendaIsExhausted/);179180    await helper.wait.forParachainBlockNumber(executionBlock);181182    const balanceAfter = await helper.balance.getSubstrate(bob.address);183184    expect(balanceAfter > balanceBefore).to.be.true;185186    const diff = balanceAfter - balanceBefore;187    expect(diff).to.be.equal(amount * BigInt(maxScheduledPerBlock));188  });189190  itSub.ifWithPallets('Scheduled tasks are transactional', [Pallets.TestUtils], async ({helper}) => {191    const scheduledId = await helper.arrange.makeScheduledId();192    const waitForBlocks = 4;193194    const initTestVal = 42;195    const changedTestVal = 111;196197    await helper.testUtils.setTestValue(alice, initTestVal);198199    await helper.scheduler.scheduleAfter<DevUniqueHelper>(scheduledId, waitForBlocks)200      .testUtils.setTestValueAndRollback(alice, changedTestVal);201    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;202203    await helper.wait.forParachainBlockNumber(executionBlock);204205    const testVal = await helper.testUtils.testValue();206    expect(testVal, 'The test value should NOT be commited')207      .to.be.equal(initTestVal);208  });209210  itSub.ifWithPallets('Scheduled tasks should take correct fees', [Pallets.TestUtils], async function({helper}) {211    const scheduledId = await helper.arrange.makeScheduledId();212    const waitForBlocks = 4;213    const periodic = {214      period: 2,215      repetitions: 2,216    };217218    const dummyTx = helper.constructApiCall('api.tx.testUtils.justTakeFee', []);219    const scheduledLen = dummyTx.callIndex.length;220221    const expectedScheduledFee = (await helper.getPaymentInfo(alice, dummyTx, scheduledLen))222      .partialFee.toBigInt();223224    await helper.scheduler.scheduleAfter<DevUniqueHelper>(scheduledId, waitForBlocks, {periodic})225      .testUtils.justTakeFee(alice);226    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;227228    const aliceInitBalance = await helper.balance.getSubstrate(alice.address);229    let diff;230231    await helper.wait.forParachainBlockNumber(executionBlock);232233    const aliceBalanceAfterFirst = await helper.balance.getSubstrate(alice.address);234    expect(235      aliceBalanceAfterFirst < aliceInitBalance,236      '[after execution #1] Scheduled task should take a fee',237    ).to.be.true;238239    diff = aliceInitBalance - aliceBalanceAfterFirst;240    expect(diff).to.be.equal(241      expectedScheduledFee,242      'Scheduled task should take the right amount of fees',243    );244245    await helper.wait.forParachainBlockNumber(executionBlock + periodic.period);246247    const aliceBalanceAfterSecond = await helper.balance.getSubstrate(alice.address);248    expect(249      aliceBalanceAfterSecond < aliceBalanceAfterFirst,250      '[after execution #2] Scheduled task should take a fee',251    ).to.be.true;252253    diff = aliceBalanceAfterFirst - aliceBalanceAfterSecond;254    expect(diff).to.be.equal(255      expectedScheduledFee,256      'Scheduled task should take the right amount of fees',257    );258  });259260  // Check if we can cancel a scheduled periodic operation261  // in the same block in which it is running262  itSub.ifWithPallets('Can cancel the periodic sheduled tx when the tx is running', [Pallets.TestUtils], async ({helper}) => {263    const currentBlockNumber = await helper.chain.getLatestBlockNumber();264    const blocksBeforeExecution = 10;265    const firstExecutionBlockNumber = currentBlockNumber + blocksBeforeExecution;266267    const [268      scheduledId,269      scheduledCancelId,270    ] = await helper.arrange.makeScheduledIds(2);271272    const periodic = {273      period: 5,274      repetitions: 5,275    };276277    const initTestVal = 0;278    const incTestVal = initTestVal + 1;279    const finalTestVal = initTestVal + 2;280281    await helper.testUtils.setTestValue(alice, initTestVal);282283    await helper.scheduler.scheduleAt<DevUniqueHelper>(scheduledId, firstExecutionBlockNumber, {periodic})284      .testUtils.incTestValue(alice);285286    // Cancel the inc tx after 2 executions287    // *in the same block* in which the second execution is scheduled288    await helper.scheduler.scheduleAt(289      scheduledCancelId,290      firstExecutionBlockNumber + periodic.period,291    ).scheduler.cancelScheduled(alice, scheduledId);292293    await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber);294295    // execution #0296    expect(await helper.testUtils.testValue())297      .to.be.equal(incTestVal);298299    await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber + periodic.period);300301    // execution #1302    expect(await helper.testUtils.testValue())303      .to.be.equal(finalTestVal);304305    for (let i = 1; i < periodic.repetitions; i++) {306      await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber + periodic.period * (i + 1));307      expect(await helper.testUtils.testValue())308        .to.be.equal(finalTestVal);309    }310  });311312  itSub.ifWithPallets('A scheduled operation can cancel itself', [Pallets.TestUtils], async ({helper}) => {313    const scheduledId = await helper.arrange.makeScheduledId();314    const waitForBlocks = 4;315    const periodic = {316      period: 2,317      repetitions: 5,318    };319320    const initTestVal = 0;321    const maxTestVal = 2;322323    await helper.testUtils.setTestValue(alice, initTestVal);324325    await helper.scheduler.scheduleAfter<DevUniqueHelper>(scheduledId, waitForBlocks, {periodic})326      .testUtils.selfCancelingInc(alice, scheduledId, maxTestVal);327    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;328329    await helper.wait.forParachainBlockNumber(executionBlock);330331    // execution #0332    expect(await helper.testUtils.testValue())333      .to.be.equal(initTestVal + 1);334335    await helper.wait.forParachainBlockNumber(executionBlock + periodic.period);336337    // execution #1338    expect(await helper.testUtils.testValue())339      .to.be.equal(initTestVal + 2);340341    await helper.wait.forParachainBlockNumber(executionBlock + 2 * periodic.period);342343    // <canceled>344    expect(await helper.testUtils.testValue())345      .to.be.equal(initTestVal + 2);346  });347348  itSub('Root can cancel any scheduled operation', async ({helper}) => {349    const collection = await helper.nft.mintCollection(bob, {tokenPrefix: 'schd'});350    const token = await collection.mintToken(bob);351352    const scheduledId = await helper.arrange.makeScheduledId();353    const waitForBlocks = 4;354355    await token.scheduleAfter(scheduledId, waitForBlocks)356      .transfer(bob, {Substrate: alice.address});357    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;358359    await helper.getSudo().scheduler.cancelScheduled(superuser, scheduledId);360361    await helper.wait.forParachainBlockNumber(executionBlock);362363    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});364  });365366  itSub('Root can set prioritized scheduled operation', async ({helper}) => {367    const scheduledId = await helper.arrange.makeScheduledId();368    const waitForBlocks = 4;369370    const amount = 42n * helper.balance.getOneTokenNominal();371372    const balanceBefore = await helper.balance.getSubstrate(charlie.address);373374    await helper.getSudo()375      .scheduler.scheduleAfter(scheduledId, waitForBlocks, {priority: 42})376      .balance.forceTransferToSubstrate(superuser, bob.address, charlie.address, amount);377    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;378379    await helper.wait.forParachainBlockNumber(executionBlock);380381    const balanceAfter = await helper.balance.getSubstrate(charlie.address);382383    expect(balanceAfter > balanceBefore).to.be.true;384385    const diff = balanceAfter - balanceBefore;386    expect(diff).to.be.equal(amount);387  });388389  itSub("Root can change scheduled operation's priority", async ({helper}) => {390    const collection = await helper.nft.mintCollection(bob, {tokenPrefix: 'schd'});391    const token = await collection.mintToken(bob);392393    const scheduledId = await helper.arrange.makeScheduledId();394    const waitForBlocks = 6;395396    await token.scheduleAfter(scheduledId, waitForBlocks)397      .transfer(bob, {Substrate: alice.address});398    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;399400    const priority = 112;401    await helper.getSudo().scheduler.changePriority(superuser, scheduledId, priority);402403    const priorityChanged = await helper.wait.event(404      waitForBlocks,405      'scheduler',406      'PriorityChanged',407    );408409    expect(priorityChanged !== null).to.be.true;410411    const [blockNumber, index] = priorityChanged!.event.data[0].toJSON() as any[];412    expect(blockNumber).to.be.equal(executionBlock);413    expect(index).to.be.equal(0);414415    expect(priorityChanged!.event.data[1].toString()).to.be.equal(priority.toString());416  });417418  itSub('Prioritized operations execute in valid order', async ({helper}) => {419    const [420      scheduledFirstId,421      scheduledSecondId,422    ] = await helper.arrange.makeScheduledIds(2);423424    const currentBlockNumber = await helper.chain.getLatestBlockNumber();425    const blocksBeforeExecution = 6;426    const firstExecutionBlockNumber = currentBlockNumber + blocksBeforeExecution;427428    const prioHigh = 0;429    const prioLow = 255;430431    const periodic = {432      period: 6,433      repetitions: 2,434    };435436    const amount = 1n * helper.balance.getOneTokenNominal();437438    // Scheduler a task with a lower priority first, then with a higher priority439    await helper.getSudo().scheduler.scheduleAt(scheduledFirstId, firstExecutionBlockNumber, {priority: prioLow, periodic})440      .balance.forceTransferToSubstrate(superuser, alice.address, bob.address, amount);441442    await helper.getSudo().scheduler.scheduleAt(scheduledSecondId, firstExecutionBlockNumber, {priority: prioHigh, periodic})443      .balance.forceTransferToSubstrate(superuser, alice.address, bob.address, amount);444445    const capture = await helper.arrange.captureEvents('scheduler', 'Dispatched');446447    await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber);448449    // Flip priorities450    await helper.getSudo().scheduler.changePriority(superuser, scheduledFirstId, prioHigh);451    await helper.getSudo().scheduler.changePriority(superuser, scheduledSecondId, prioLow);452453    await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber + periodic.period);454455    const dispatchEvents = capture.extractCapturedEvents();456    expect(dispatchEvents.length).to.be.equal(4);457458    const dispatchedIds = dispatchEvents.map(r => r.event.data[1].toString());459460    const firstExecuctionIds = [dispatchedIds[0], dispatchedIds[1]];461    const secondExecuctionIds = [dispatchedIds[2], dispatchedIds[3]];462463    expect(firstExecuctionIds[0]).to.be.equal(scheduledSecondId);464    expect(firstExecuctionIds[1]).to.be.equal(scheduledFirstId);465466    expect(secondExecuctionIds[0]).to.be.equal(scheduledFirstId);467    expect(secondExecuctionIds[1]).to.be.equal(scheduledSecondId);468  });469470  itSub('Periodic operations always can be rescheduled', async ({helper}) => {471    const maxScheduledPerBlock = 50;472    const numFilledBlocks = 3;473    const ids = await helper.arrange.makeScheduledIds(numFilledBlocks * maxScheduledPerBlock + 1);474    const periodicId = ids[0];475    const fillIds = ids.slice(1);476477    const initTestVal = 0;478    const firstExecTestVal = 1;479    const secondExecTestVal = 2;480    await helper.testUtils.setTestValue(alice, initTestVal);481482    const currentBlockNumber = await helper.chain.getLatestBlockNumber();483    const blocksBeforeExecution = 8;484    const firstExecutionBlockNumber = currentBlockNumber + blocksBeforeExecution;485486    const period = 5;487488    const periodic = {489      period,490      repetitions: 2,491    };492493    // Fill `numFilledBlocks` blocks beginning from the block in which the second execution should occur494    const txs = [];495    for (let offset = 0; offset < numFilledBlocks; offset ++) {496      for (let i = 0; i < maxScheduledPerBlock; i++) {497498        const scheduledTx = helper.constructApiCall('api.tx.balances.transfer', [bob.address, 1n]);499500        const when = firstExecutionBlockNumber + period + offset;501        const tx = helper.constructApiCall('api.tx.scheduler.scheduleNamed', [fillIds[i + offset * maxScheduledPerBlock], when, null, null, scheduledTx]);502503        txs.push(tx);504      }505    }506    await helper.executeExtrinsic(alice, 'api.tx.testUtils.batchAll', [txs], true);507508    await helper.scheduler.scheduleAt<DevUniqueHelper>(periodicId, firstExecutionBlockNumber, {periodic})509      .testUtils.incTestValue(alice);510511    await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber);512    expect(await helper.testUtils.testValue()).to.be.equal(firstExecTestVal);513514    await helper.wait.forParachainBlockNumber(firstExecutionBlockNumber + period + numFilledBlocks);515516    // The periodic operation should be postponed by `numFilledBlocks`517    for (let i = 0; i < numFilledBlocks; i++) {518      expect(await helper.testUtils.testValue(firstExecutionBlockNumber + period + i)).to.be.equal(firstExecTestVal);519    }520521    // After the `numFilledBlocks` the periodic operation will eventually be executed522    expect(await helper.testUtils.testValue()).to.be.equal(secondExecTestVal);523  });524525  itSub('scheduled operations does not change nonce', async ({helper}) => {526    const scheduledId = await helper.arrange.makeScheduledId();527    const blocksBeforeExecution = 4;528529    await helper.scheduler530      .scheduleAfter<DevUniqueHelper>(scheduledId, blocksBeforeExecution)531      .balance.transferToSubstrate(alice, bob.address, 1n);532    const executionBlock = await helper.chain.getLatestBlockNumber() + blocksBeforeExecution + 1;533534    const initNonce = await helper.chain.getNonce(alice.address);535536    await helper.wait.forParachainBlockNumber(executionBlock);537538    const finalNonce = await helper.chain.getNonce(alice.address);539540    expect(initNonce).to.be.equal(finalNonce);541  });542});543544describe('Negative Test: Scheduling', () => {545  let alice: IKeyringPair;546  let bob: IKeyringPair;547548  before(async function() {549    await usingPlaygrounds(async (helper, privateKey) => {550      requirePalletsOrSkip(this, helper, [Pallets.Scheduler]);551552      const donor = await privateKey({filename: __filename});553      [alice, bob] = await helper.arrange.createAccounts([100n, 100n], donor);554555      await helper.testUtils.enable();556    });557  });558559  itSub("Can't overwrite a scheduled ID", async ({helper}) => {560    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});561    const token = await collection.mintToken(alice);562563    const scheduledId = await helper.arrange.makeScheduledId();564    const waitForBlocks = 4;565566    await token.scheduleAfter(scheduledId, waitForBlocks)567      .transfer(alice, {Substrate: bob.address});568    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;569570    const scheduled = helper.scheduler.scheduleAfter(scheduledId, waitForBlocks);571    await expect(scheduled.balance.transferToSubstrate(alice, bob.address, 1n * helper.balance.getOneTokenNominal()))572      .to.be.rejectedWith(/scheduler\.FailedToSchedule/);573574    const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address);575576    await helper.wait.forParachainBlockNumber(executionBlock);577578    const bobsBalanceAfter = await helper.balance.getSubstrate(bob.address);579580    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});581    expect(bobsBalanceBefore).to.be.equal(bobsBalanceAfter);582  });583584  itSub("Can't cancel an operation which is not scheduled", async ({helper}) => {585    const scheduledId = await helper.arrange.makeScheduledId();586    await expect(helper.scheduler.cancelScheduled(alice, scheduledId))587      .to.be.rejectedWith(/scheduler\.NotFound/);588  });589590  itSub("Can't cancel a non-owned scheduled operation", async ({helper}) => {591    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'schd'});592    const token = await collection.mintToken(alice);593594    const scheduledId = await helper.arrange.makeScheduledId();595    const waitForBlocks = 4;596597    await token.scheduleAfter(scheduledId, waitForBlocks)598      .transfer(alice, {Substrate: bob.address});599    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;600601    await expect(helper.scheduler.cancelScheduled(bob, scheduledId))602      .to.be.rejectedWith(/BadOrigin/);603604    await helper.wait.forParachainBlockNumber(executionBlock);605606    expect(await token.getOwner()).to.be.deep.equal({Substrate: bob.address});607  });608609  itSub("Regular user can't set prioritized scheduled operation", async ({helper}) => {610    const scheduledId = await helper.arrange.makeScheduledId();611    const waitForBlocks = 4;612613    const amount = 42n * helper.balance.getOneTokenNominal();614615    const balanceBefore = await helper.balance.getSubstrate(bob.address);616617    const scheduled = helper.scheduler.scheduleAfter(scheduledId, waitForBlocks, {priority: 42});618    619    await expect(scheduled.balance.transferToSubstrate(alice, bob.address, amount))620      .to.be.rejectedWith(/BadOrigin/);621622    const executionBlock = await helper.chain.getLatestBlockNumber() + waitForBlocks + 1;623624    await helper.wait.forParachainBlockNumber(executionBlock);625626    const balanceAfter = await helper.balance.getSubstrate(bob.address);627628    expect(balanceAfter).to.be.equal(balanceBefore);629  });630631  itSub("Regular user can't change scheduled operation's priority", async ({helper}) => {632    const collection = await helper.nft.mintCollection(bob, {tokenPrefix: 'schd'});633    const token = await collection.mintToken(bob);634635    const scheduledId = await helper.arrange.makeScheduledId();636    const waitForBlocks = 4;637638    await token.scheduleAfter(scheduledId, waitForBlocks)639      .transfer(bob, {Substrate: alice.address});640641    const priority = 112;642    await expect(helper.scheduler.changePriority(alice, scheduledId, priority))643      .to.be.rejectedWith(/BadOrigin/);644645    const priorityChanged = await helper.wait.event(646      waitForBlocks,647      'scheduler',648      'PriorityChanged',649    );650651    expect(priorityChanged === null).to.be.true;652  });653});654655// Implementation of the functionality tested here was postponed/shelved656describe.skip('Sponsoring scheduling', () => {657  // let alice: IKeyringPair;658  // let bob: IKeyringPair;659660  // before(async() => {661  //   await usingApi(async (_, privateKey) => {662  //     alice = privateKey('//Alice');663  //     bob = privateKey('//Bob');664  //   });665  // });666667  it('Can sponsor scheduling a transaction', async () => {668    // const collectionId = await createCollectionExpectSuccess();669    // await setCollectionSponsorExpectSuccess(collectionId, bob.address);670    // await confirmSponsorshipExpectSuccess(collectionId, '//Bob');671672    // await usingApi(async api => {673    //   const scheduledId = await makeScheduledId();674    //   const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);675676    //   const bobBalanceBefore = await getFreeBalance(bob);677    //   const waitForBlocks = 4;678    //   // no need to wait to check, fees must be deducted on scheduling, immediately679    //   await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 0, waitForBlocks, scheduledId);680    //   const bobBalanceAfter = await getFreeBalance(bob);681    //   // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;682    //   expect(bobBalanceAfter < bobBalanceBefore).to.be.true;683    //   // wait for sequentiality matters684    //   await waitNewBlocks(waitForBlocks - 1);685    // });686  });687688  it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => {689    // await usingApi(async (api, privateKey) => {690    //   // Find an empty, unused account691    //   const zeroBalance = await findUnusedAddress(api, privateKey);692693    //   const collectionId = await createCollectionExpectSuccess();694695    //   // Add zeroBalance address to allow list696    //   await enablePublicMintingExpectSuccess(alice, collectionId);697    //   await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);698699    //   // Grace zeroBalance with money, enough to cover future transactions700    //   const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);701    //   await submitTransactionAsync(alice, balanceTx);702703    //   // Mint a fresh NFT704    //   const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT');705    //   const scheduledId = await makeScheduledId();706707    //   // Schedule transfer of the NFT a few blocks ahead708    //   const waitForBlocks = 5;709    //   await scheduleTransferExpectSuccess(api, collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, scheduledId);710711    //   // Get rid of the account's funds before the scheduled transaction takes place712    //   const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n);713    //   const events = await submitTransactionAsync(zeroBalance, balanceTx2);714    //   expect(getGenericResult(events).success).to.be.true;715    //   /*const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved?716    //   const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any);717    //   const events = await submitTransactionAsync(alice, sudoTx);718    //   expect(getGenericResult(events).success).to.be.true;*/719720    //   // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions721    //   await waitNewBlocks(waitForBlocks - 3);722723    //   expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));724    // });725  });726727  it('Sponsor going bankrupt does not impact a scheduled transaction', async () => {728    // const collectionId = await createCollectionExpectSuccess();729730    // await usingApi(async (api, privateKey) => {731    //   const zeroBalance = await findUnusedAddress(api, privateKey);732    //   const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);733    //   await submitTransactionAsync(alice, balanceTx);734735    //   await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address);736    //   await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance);737738    //   const scheduledId = await makeScheduledId();739    //   const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);740741    //   const waitForBlocks = 5;742    //   await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, scheduledId);743744    //   const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);745    //   const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);746    //   const events = await submitTransactionAsync(alice, sudoTx);747    //   expect(getGenericResult(events).success).to.be.true;748749    //   // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions750    //   await waitNewBlocks(waitForBlocks - 3);751752    //   expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address));753    // });754  });755756  it('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => {757    // const collectionId = await createCollectionExpectSuccess();758    // await setCollectionSponsorExpectSuccess(collectionId, bob.address);759    // await confirmSponsorshipExpectSuccess(collectionId, '//Bob');760761    // await usingApi(async (api, privateKey) => {762    //   const zeroBalance = await findUnusedAddress(api, privateKey);763764    //   await enablePublicMintingExpectSuccess(alice, collectionId);765    //   await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);766767    //   const bobBalanceBefore = await getFreeBalance(bob);768769    //   const createData = {nft: {const_data: [], variable_data: []}};770    //   const creationTx = api.tx.unique.createItem(collectionId, normalizeAccountId(zeroBalance), createData as any);771    //   const scheduledId = await makeScheduledId();772773    //   /*const badTransaction = async function () {774    //     await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);775    //   };776    //   await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/777778    //   await expect(scheduleAfter(api, creationTx, zeroBalance, 3, scheduledId, 1, 3)).to.be.rejectedWith(/Inability to pay some fees/);779780    //   expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore);781    // });782  });783});
modifiedtests/src/util/index.tsdiffbeforeafterboth
--- a/tests/src/util/index.ts
+++ b/tests/src/util/index.ts
@@ -130,6 +130,24 @@
 itSubIfWithPallet.skip = (name: string, required: string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSubIfWithPallet(name, required, cb, {skip: true});
 itSub.ifWithPallets = itSubIfWithPallet;
 
+export type SchedKind = 'anon' | 'named';
+
+export function itSched(
+  name: string,
+  cb: (schedKind: SchedKind, apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any,
+  opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {},
+) {
+  itSub(name + ' (anonymous scheduling)', (apis) => cb('anon', apis), opts);
+  itSub(name + ' (named scheduling)', (apis) => cb('named', apis), opts);
+}
+itSched.only = (name: string, cb: (schedKind: SchedKind, apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSched(name, cb, {only: true});
+itSched.skip = (name: string, cb: (schedKind: SchedKind, apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSched(name, cb, {skip: true});
+itSched.ifWithPallets = itSchedIfWithPallets;
+
+function itSchedIfWithPallets(name: string, required: string[], cb: (schedKind: SchedKind, apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {
+  return itSched(name, cb, {requiredPallets: required, ...opts});
+}
+
 export function describeXCM(title: string, fn: (this: Mocha.Suite) => void, opts: {skip?: boolean} = {}) {
   (process.env.RUN_XCM_TESTS && !opts.skip
     ? describe
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/types.ts
+++ b/tests/src/util/playgrounds/types.ts
@@ -172,6 +172,7 @@
 }
 
 export interface ISchedulerOptions {
+  scheduledId?: string,
   priority?: number,
   periodic?: {
     period: number,
modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -308,9 +308,7 @@
     return encodeAddress(address);
   }
 
-  async makeScheduledIds(num: number): Promise<string[]> {
-    await this.helper.wait.noScheduledTasks();
-
+  makeScheduledIds(num: number): string[] {
     function makeId(slider: number) {
       const scheduledIdSize = 64;
       const hexId = slider.toString(16);
@@ -330,8 +328,8 @@
     return ids;
   }
 
-  async makeScheduledId(): Promise<string> {
-    return (await this.makeScheduledIds(1))[0];
+  makeScheduledId(): string {
+    return (this.makeScheduledIds(1))[0];
   }
 
   async captureEvents(eventSection: string, eventMethod: string): Promise<EventCapture> {
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
--- a/tests/src/util/playgrounds/unique.ts
+++ b/tests/src/util/playgrounds/unique.ts
@@ -2560,24 +2560,21 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    return this.schedule<T>('scheduleNamed', scheduledId, executionBlockNumber, options);
+    return this.schedule<T>('schedule', executionBlockNumber, options);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    return this.schedule<T>('scheduleNamedAfter', scheduledId, blocksBeforeExecution, options);
+    return this.schedule<T>('scheduleAfter', blocksBeforeExecution, options);
   }
 
   schedule<T extends UniqueHelper>(
-    scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter',
-    scheduledId: string,
+    scheduleFn: 'schedule' | 'scheduleAfter',
     blocksNum: number,
     options: ISchedulerOptions = {},
   ) {
@@ -2585,7 +2582,6 @@
     const ScheduledHelperType = ScheduledUniqueHelper(this.helper.helperBase);
     return this.helper.clone(ScheduledHelperType, {
       scheduleFn,
-      scheduledId,
       blocksNum,
       options,
     }) as T;
@@ -2874,16 +2870,14 @@
 // eslint-disable-next-line @typescript-eslint/naming-convention
 function ScheduledUniqueHelper<T extends UniqueHelperConstructor>(Base: T) {
   return class extends Base {
-    scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter';
-    scheduledId: string;
+    scheduleFn: 'schedule' | 'scheduleAfter';
     blocksNum: number;
     options: ISchedulerOptions;
 
     constructor(...args: any[]) {
       const logger = args[0] as ILogger;
       const options = args[1] as {
-        scheduleFn: 'scheduleNamed' | 'scheduleNamedAfter',
-        scheduledId: string,
+        scheduleFn: 'schedule' | 'scheduleAfter',
         blocksNum: number,
         options: ISchedulerOptions
       };
@@ -2891,25 +2885,42 @@
       super(logger);
 
       this.scheduleFn = options.scheduleFn;
-      this.scheduledId = options.scheduledId;
       this.blocksNum = options.blocksNum;
       this.options = options.options;
     }
 
     executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise<ITransactionResult> {
       const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams);
-      const extrinsic = 'api.tx.scheduler.' +  this.scheduleFn;
+      
+      const mandatorySchedArgs = [
+        this.blocksNum,
+        this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,
+        this.options.priority ?? null,
+        scheduledTx,
+      ];
+      
+      let schedArgs;
+      let scheduleFn;
+
+      if (this.options.scheduledId) {
+        schedArgs = [this.options.scheduledId!, ...mandatorySchedArgs];
 
+        if (this.scheduleFn == 'schedule') {
+          scheduleFn = 'scheduleNamed';
+        } else if (this.scheduleFn == 'scheduleAfter') {
+          scheduleFn = 'scheduleNamedAfter';
+        }
+      } else {
+        schedArgs = mandatorySchedArgs;
+        scheduleFn = this.scheduleFn;
+      }
+
+      const extrinsic = 'api.tx.scheduler.' +  scheduleFn;
+
       return super.executeExtrinsic(
         sender,
         extrinsic,
-        [
-          this.scheduledId,
-          this.blocksNum,
-          this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,
-          this.options.priority ?? null,
-          scheduledTx,
-        ],
+        schedArgs,
         expectSuccess,
       );
     }
@@ -3046,20 +3057,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueBaseCollection(this.collectionId, scheduledHelper);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueBaseCollection(this.collectionId, scheduledHelper);
   }
 
@@ -3155,20 +3164,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueNFTCollection(this.collectionId, scheduledHelper);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueNFTCollection(this.collectionId, scheduledHelper);
   }
 
@@ -3260,20 +3267,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueRFTCollection(this.collectionId, scheduledHelper);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueRFTCollection(this.collectionId, scheduledHelper);
   }
 
@@ -3329,20 +3334,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueFTCollection(this.collectionId, scheduledHelper);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledHelper = this.helper.scheduler.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueFTCollection(this.collectionId, scheduledHelper);
   }
 
@@ -3388,20 +3391,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueBaseToken(this.tokenId, scheduledCollection);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueBaseToken(this.tokenId, scheduledCollection);
   }
 
@@ -3468,20 +3469,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueNFToken(this.tokenId, scheduledCollection);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueNFToken(this.tokenId, scheduledCollection);
   }
 
@@ -3543,20 +3542,18 @@
   }
 
   scheduleAt<T extends UniqueHelper>(
-    scheduledId: string,
     executionBlockNumber: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledCollection = this.collection.scheduleAt<T>(scheduledId, executionBlockNumber, options);
+    const scheduledCollection = this.collection.scheduleAt<T>(executionBlockNumber, options);
     return new UniqueRFToken(this.tokenId, scheduledCollection);
   }
 
   scheduleAfter<T extends UniqueHelper>(
-    scheduledId: string,
     blocksBeforeExecution: number,
     options: ISchedulerOptions = {},
   ) {
-    const scheduledCollection = this.collection.scheduleAfter<T>(scheduledId, blocksBeforeExecution, options);
+    const scheduledCollection = this.collection.scheduleAfter<T>(blocksBeforeExecution, options);
     return new UniqueRFToken(this.tokenId, scheduledCollection);
   }