"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint @typescript-eslint/no-var-requires: "off" */
const factory_1 = require("../src/factory");
const util_crypto_1 = require("@polkadot/util-crypto");
const yargs = require("yargs/yargs");
const { hideBin } = require("yargs/helpers");
const args = yargs(hideBin(process.argv))
    .option("clients-version", {
    description: "The version of the clients",
    type: "string",
    demandOption: true,
})
    .option("parachain-endpoint", {
    description: "The wss url of the parachain",
    type: "string",
})
    .option("parachain-version", {
    description: "The version of the parachain",
    type: "string",
    demandOption: true,
})
    .option("runtime-name", {
    description: "The name of the runtime",
    type: "string",
})
    .option("with-defaults-of", {
    description: "Which default values to use",
    choices: ['kintsugi', 'interlay'],
})
    .argv;
main().catch((err) => {
    console.log("Error thrown by script:");
    console.log(err);
});
function toUrl(extrinsic, endpoint) {
    return "https://polkadot.js.org/apps/?rpc=" +
        encodeURIComponent(endpoint) +
        "#/extrinsics/decode/" +
        extrinsic.method.toHex();
}
function constructProposal(api, extrinsic) {
    const deposit = api.consts.democracy.minimumDeposit.toNumber();
    const preImageSubmission = api.tx.democracy.notePreimage(extrinsic.method.toHex());
    const proposal = api.tx.democracy.propose(extrinsic.method.hash.toHex(), deposit);
    const batched = api.tx.utility.batchAll([preImageSubmission, proposal]);
    return batched;
}
function printDiscordProposal(description, extrinsic, endpoint, api) {
    return __awaiter(this, void 0, void 0, function* () {
        const proposal = constructProposal(api, extrinsic);
        const invocation = process.argv.map(function (x) { return x.substring(x.lastIndexOf('/') + 1); }).join(" ");
        console.log("");
        console.log("");
        console.log("**" + description + "**");
        console.log("");
        console.log("**Extrinsic:**", toUrl(extrinsic, endpoint));
        console.log("");
        console.log("**Proposal:**", toUrl(proposal, endpoint));
        console.log("");
        console.log("_Generated with_: `" + invocation + "`");
        console.log("");
        console.log("");
    });
}
function main() {
    return __awaiter(this, void 0, void 0, function* () {
        yield util_crypto_1.cryptoWaitReady();
        switch (args['with-defaults-of']) {
            case 'interlay':
                if (args['parachain-endpoint'] === undefined) {
                    args['parachain-endpoint'] = "wss://api.interlay.io/parachain";
                }
                if (args['runtime-name'] === undefined) {
                    args['runtime-name'] = "interlay";
                }
                break;
            case 'kintsugi':
                if (args['parachain-endpoint'] === undefined) {
                    args['parachain-endpoint'] = "wss://api-kusama.interlay.io/parachain";
                }
                if (args['runtime-name'] === undefined) {
                    args['runtime-name'] = "kintsugi";
                }
                break;
        }
        if (args['parachain-endpoint'] === undefined
            || args['runtime-name'] === undefined) {
            console.log("Not all required arguments supplied");
            return;
        }
        const parachainRepo = "https://github.com/interlay/interbtc";
        const parachainVersion = args['parachain-version'];
        console.log(`Downloading parachain runtime (${parachainVersion})...`);
        const runtimeFileName = `${args['runtime-name']}_runtime_parachain.compact.compressed.wasm`;
        // NOTE: fetch flagged as experimental, not sure if there is a better alternative
        const wasmRuntime = yield fetch(`${parachainRepo}/releases/download/${parachainVersion}/${runtimeFileName}`);
        const wasmRuntimeRaw = yield wasmRuntime.arrayBuffer();
        const codeHash = util_crypto_1.blake2AsHex(Buffer.from(wasmRuntimeRaw));
        console.log(`Blake2-256 hash: ${codeHash}`);
        const clientsRepo = "https://github.com/interlay/interbtc-clients";
        const clientsVersion = args['clients-version'];
        console.log(`Downloading vault binary (${clientsVersion})...`);
        const vaultFileName = `vault-parachain-metadata-${args['runtime-name']}`;
        const vaultBinaryUri = `${clientsRepo}/releases/download/${clientsVersion}/${vaultFileName}`;
        const vaultBinary = yield fetch(vaultBinaryUri);
        const vaultBinaryRaw = yield vaultBinary.arrayBuffer();
        const vaultChecksum = util_crypto_1.sha256AsU8a(Buffer.from(vaultBinaryRaw));
        const vaultRelease = { uri: vaultBinaryUri, checksum: vaultChecksum };
        const paraApi = yield factory_1.createSubstrateAPI(args['parachain-endpoint']);
        const batched = paraApi.tx.utility.batchAll([
            paraApi.tx.parachainSystem.authorizeUpgrade(codeHash),
            paraApi.tx.clientsInfo.setPendingClientRelease("vault", vaultRelease),
        ]);
        const title = `Runtime Upgrade ${parachainVersion}`;
        printDiscordProposal(title, batched, args["parachain-endpoint"], paraApi);
        yield paraApi.disconnect();
    });
}
//# sourceMappingURL=runtime-upgrade.js.map