1import config from '../config';2import {usingPlaygrounds} from '../util';3456const WS_ENDPOINT = config.substrateUrl;7const DONOR_SEED = '//Alice';89export const main = async(options: { wsEndpoint: string; donorSeed: string } = {10 wsEndpoint: WS_ENDPOINT,11 donorSeed: DONOR_SEED,12}) => {13 await usingPlaygrounds(async (helper, privateKey) => {14 const api = helper.getApi();1516 if((await api.query.maintenance.enabled()).valueOf()) {17 throw Error('The network is still in maintenance mode');18 }1920 const pendingBlocks = (21 await api.query.appPromotion.pendingUnstake.entries()22 ).map(([k, _v]) =>23 k.args[0]);2425 const currentBlock = await api.query.system.number();2627 const filteredBlocks = pendingBlocks.filter((b) => currentBlock.gt(b));2829 if(filteredBlocks.length != 0) {30 console.log(`During maintenance mode, ${filteredBlocks.length} block(s) were not processed. Number(s): ${filteredBlocks}`);31 } else {32 console.log('Nothing to change');33 return;34 }3536 const skippedBlocks = chunk(filteredBlocks, 10);3738 const signer = await privateKey(options.donorSeed);3940 const txs = skippedBlocks.map((b) =>41 api.tx.sudo.sudo(api.tx.appPromotion.forceUnstake(b)));424344 const promises = txs.map((tx) => () => helper.signTransaction(signer, tx));4546 await Promise.allSettled(promises.map((p) => p()));4748 const failedBlocks: bigint[] = [];49 let isSuccess = true;5051 for(const b of filteredBlocks) {52 if(((await api.query.appPromotion.pendingUnstake(b)).toJSON() as any[]).length != 0) {53 failedBlocks.push(b.toBigInt());54 isSuccess = false;55 }56 }5758 if(isSuccess) {59 console.log('Done. %d block(s) were processed.', filteredBlocks.length);60 } else {61 throw new Error(`Something went wrong. Block(s) have not been processed: ${failedBlocks}`);62 }636465 }, options.wsEndpoint);66};6768const chunk = <T>(arr: T[], size: number) =>69 Array.from({length: Math.ceil(arr.length / size)}, (_: any, i: number) =>70 arr.slice(i * size, i * size + size));