PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-sui/dist/src

Просмотр файла: sui.js

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sui = void 0;
const sdk_core_1 = require("@bitgo/sdk-core");
const statics_1 = require("@bitgo/statics");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const lib_1 = require("./lib");
const utils_1 = __importDefault(require("./lib/utils"));
const _ = __importStar(require("lodash"));
const iface_1 = require("./lib/iface");
const constants_1 = require("./lib/constants");
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
class Sui extends sdk_core_1.BaseCoin {
    constructor(bitgo, staticsCoin) {
        super(bitgo);
        if (!staticsCoin) {
            throw new Error('missing required constructor parameter staticsCoin');
        }
        this._staticsCoin = staticsCoin;
    }
    static createInstance(bitgo, staticsCoin) {
        return new Sui(bitgo, staticsCoin);
    }
    /**
     * Factor between the coin's base unit and its smallest subdivison
     */
    getBaseFactor() {
        return 1e9;
    }
    getChain() {
        return 'sui';
    }
    getFamily() {
        return 'sui';
    }
    getFullName() {
        return 'Sui';
    }
    getNetwork() {
        return this._staticsCoin.network;
    }
    /** @inheritDoc */
    supportsTss() {
        return true;
    }
    /** inherited doc */
    getDefaultMultisigType() {
        return sdk_core_1.multisigTypes.tss;
    }
    getMPCAlgorithm() {
        return 'eddsa';
    }
    allowsAccountConsolidations() {
        return true;
    }
    async verifyTransaction(params) {
        let totalAmount = new bignumber_js_1.default(0);
        const coinConfig = statics_1.coins.get(this.getChain());
        const { txPrebuild: txPrebuild, txParams: txParams, verification, wallet } = params;
        const transaction = new lib_1.TransferTransaction(coinConfig);
        const rawTx = txPrebuild.txHex;
        if (!rawTx) {
            throw new Error('missing required tx prebuild property txHex');
        }
        transaction.fromRawTransaction(Buffer.from(rawTx, 'hex').toString('base64'));
        const explainedTx = transaction.explainTransaction();
        if (txParams.recipients && txParams.recipients.length > 0) {
            const filteredRecipients = txParams.recipients?.map((recipient) => {
                const filteredRecipient = _.pick(recipient, ['address', 'amount']);
                filteredRecipient.amount = new bignumber_js_1.default(filteredRecipient.amount).toFixed();
                return filteredRecipient;
            });
            const filteredOutputs = explainedTx.outputs.map((output) => {
                const filteredOutput = _.pick(output, ['address', 'amount']);
                filteredOutput.amount = new bignumber_js_1.default(filteredOutput.amount).toFixed();
                return filteredOutput;
            });
            if (!_.isEqual(filteredOutputs, filteredRecipients)) {
                throw new Error('Tx outputs does not match with expected txParams recipients');
            }
            for (const recipients of txParams.recipients) {
                totalAmount = totalAmount.plus(recipients.amount);
            }
            if (!totalAmount.isEqualTo(explainedTx.outputAmount)) {
                throw new Error('Tx total amount does not match with expected total amount field');
            }
        }
        if (verification?.consolidationToBaseAddress) {
            const baseAddress = wallet.coinSpecific()?.baseAddress || wallet.coinSpecific()?.rootAddress;
            for (const output of explainedTx.outputs) {
                if (output.address !== baseAddress) {
                    throw new Error('Consolidation transaction output address does not match wallet base address');
                }
            }
        }
        return true;
    }
    async isWalletAddress(params) {
        const { address: newAddress } = params;
        if (!this.isValidAddress(newAddress)) {
            throw new sdk_core_1.InvalidAddressError(`invalid address: ${newAddress}`);
        }
        return true;
    }
    async parseTransaction(params) {
        const transactionExplanation = await this.explainTransaction({ txHex: params.txHex });
        if (!transactionExplanation) {
            throw new Error('Invalid transaction');
        }
        let fee = new bignumber_js_1.default(0);
        const suiTransaction = transactionExplanation;
        if (suiTransaction.outputs.length <= 0) {
            return {
                inputs: [],
                outputs: [],
                fee,
            };
        }
        const senderAddress = suiTransaction.outputs[0].address;
        if (suiTransaction.fee.fee !== '') {
            fee = new bignumber_js_1.default(suiTransaction.fee.fee);
        }
        // assume 1 sender, who is also the fee payer
        const inputs = [
            {
                address: senderAddress,
                amount: new bignumber_js_1.default(suiTransaction.outputAmount).plus(fee).toFixed(),
            },
        ];
        const outputs = suiTransaction.outputs.map((output) => {
            return {
                address: output.address,
                amount: new bignumber_js_1.default(output.amount).toFixed(),
            };
        });
        return {
            inputs,
            outputs,
            fee,
        };
    }
    generateKeyPair(seed) {
        const keyPair = seed ? new lib_1.KeyPair({ seed }) : new lib_1.KeyPair();
        const keys = keyPair.getKeys();
        if (!keys.prv) {
            throw new Error('Missing prv in key generation.');
        }
        return {
            pub: keys.pub,
            prv: keys.prv,
        };
    }
    isValidPub(_) {
        throw new Error('Method not implemented.');
    }
    isValidPrv(_) {
        throw new Error('Method not implemented.');
    }
    isValidAddress(address) {
        return utils_1.default.isValidAddress(address);
    }
    signTransaction(_) {
        throw new Error('Method not implemented.');
    }
    /**
     * Explain a Sui transaction
     * @param params
     */
    async explainTransaction(params) {
        const factory = this.getBuilder();
        let rebuiltTransaction;
        try {
            const transactionBuilder = factory.from(Buffer.from(params.txHex, 'hex').toString('base64'));
            rebuiltTransaction = await transactionBuilder.build();
        }
        catch {
            throw new Error('Invalid transaction');
        }
        return rebuiltTransaction.explainTransaction();
    }
    getBuilder() {
        return new lib_1.TransactionBuilderFactory(statics_1.coins.get(this.getChain()));
    }
    getAddressFromPublicKey(derivedPublicKey) {
        // TODO(BG-59016) replace with account lib implementation
        return utils_1.default.getAddressFromPublicKey(derivedPublicKey);
    }
    /** @inheritDoc */
    async getSignablePayload(serializedTx) {
        const factory = this.getBuilder();
        const rebuiltTransaction = await factory.from(serializedTx).build();
        return rebuiltTransaction.signablePayload;
    }
    getPublicNodeUrl() {
        return sdk_core_1.Environments[this.bitgo.getEnv()].suiNodeUrl;
    }
    async getBalance(owner, coinType) {
        const url = this.getPublicNodeUrl();
        return await utils_1.default.getBalance(url, owner, coinType);
    }
    async getInputCoins(owner, coinType) {
        const url = this.getPublicNodeUrl();
        return await utils_1.default.getInputCoins(url, owner, coinType);
    }
    async getFeeEstimate(txHex) {
        const url = this.getPublicNodeUrl();
        return await utils_1.default.getFeeEstimate(url, txHex);
    }
    /**
     * Builds funds recovery transaction(s) without BitGo
     *
     * @param {MPCRecoveryOptions} params parameters needed to construct and
     * (maybe) sign the transaction
     *
     * @returns {MPCTx | MPCSweepTxs} array of the serialized transaction hex strings and indices
     * of the addresses being swept
     */
    async recover(params) {
        if (!params.bitgoKey) {
            throw new Error('missing bitgoKey');
        }
        if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
            throw new Error('invalid recoveryDestination');
        }
        const startIdx = utils_1.default.validateNonNegativeNumber(0, 'Invalid starting index to scan for addresses', params.startingScanIndex);
        const numIterations = utils_1.default.validateNonNegativeNumber(20, 'Invalid scanning factor', params.scan);
        const endIdx = startIdx + numIterations;
        const bitgoKey = params.bitgoKey.replace(/\s/g, '');
        const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
        for (let idx = startIdx; idx < endIdx; idx++) {
            const derivationPath = (params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) : 'm') + `/${idx}`;
            const derivedPublicKey = MPC.deriveUnhardened(bitgoKey, derivationPath).slice(0, 64);
            const senderAddress = this.getAddressFromPublicKey(derivedPublicKey);
            let availableBalance = new bignumber_js_1.default(0);
            try {
                availableBalance = new bignumber_js_1.default(await this.getBalance(senderAddress));
            }
            catch (e) {
                continue;
            }
            if (availableBalance.minus(constants_1.MAX_GAS_BUDGET).toNumber() <= 0) {
                continue;
            }
            // check for possible token recovery, recover the token provide by user
            if (params.tokenContractAddress) {
                const token = utils_1.default.getSuiTokenFromAddress(params.tokenContractAddress, this.getNetwork());
                if (!token) {
                    throw new Error(`Sui Token Package ID not supported.`);
                }
                const coinType = `${token.packageId}::${token.module}::${token.symbol}`;
                try {
                    const availableTokenBalance = new bignumber_js_1.default(await this.getBalance(senderAddress, coinType));
                    if (availableTokenBalance.toNumber() <= 0) {
                        continue;
                    }
                }
                catch (e) {
                    continue;
                }
                return this.recoverSuiToken(params, token, senderAddress, derivationPath, derivedPublicKey, idx, bitgoKey);
            }
            let inputCoins = await this.getInputCoins(senderAddress);
            inputCoins = inputCoins.sort((a, b) => {
                return b.balance.minus(a.balance).toNumber();
            });
            if (inputCoins.length > constants_1.MAX_OBJECT_LIMIT) {
                inputCoins = inputCoins.slice(0, constants_1.MAX_OBJECT_LIMIT);
            }
            let netAmount = inputCoins.reduce((acc, obj) => acc.plus(obj.balance), new bignumber_js_1.default(0));
            netAmount = netAmount.minus(constants_1.MAX_GAS_BUDGET);
            const recipients = [
                {
                    address: params.recoveryDestination,
                    amount: netAmount.toString(),
                },
            ];
            // first build the unsigned txn
            const factory = new lib_1.TransactionBuilderFactory(statics_1.coins.get(this.getChain()));
            const txBuilder = factory
                .getTransferBuilder()
                .type(iface_1.SuiTransactionType.Transfer)
                .sender(senderAddress)
                .send(recipients)
                .gasData({
                owner: senderAddress,
                price: constants_1.DEFAULT_GAS_PRICE,
                budget: constants_1.MAX_GAS_BUDGET,
                payment: inputCoins,
            });
            const tempTx = (await txBuilder.build());
            const feeEstimate = await this.getFeeEstimate(tempTx.toBroadcastFormat());
            const gasBudget = Math.trunc(feeEstimate.toNumber() * constants_1.DEFAULT_GAS_OVERHEAD);
            netAmount = netAmount.plus(constants_1.MAX_GAS_BUDGET).minus(gasBudget);
            recipients[0].amount = netAmount.toString();
            txBuilder.send(recipients);
            txBuilder.gasData({
                owner: senderAddress,
                price: constants_1.DEFAULT_GAS_PRICE,
                budget: gasBudget,
                payment: inputCoins,
            });
            const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
            if (isUnsignedSweep) {
                return this.buildUnsignedSweepTransaction(txBuilder, senderAddress, bitgoKey, idx, derivationPath);
            }
            await this.signRecoveryTransaction(txBuilder, params, derivationPath, derivedPublicKey, false);
            const tx = (await txBuilder.build());
            return {
                transactions: [
                    {
                        scanIndex: idx,
                        recoveryAmount: netAmount.toString(),
                        serializedTx: tx.toBroadcastFormat(),
                        signature: Buffer.from(tx.serializedSig).toString('base64'),
                        coin: this.getChain(),
                    },
                ],
                lastScanIndex: idx,
            };
        }
        throw new Error(`Did not find an address with sufficient funds to recover. Please start the next scan at address index ${endIdx}. If it is token transaction, please keep sufficient Sui balance in the address for the transaction fee.`);
    }
    async recoverSuiToken(params, token, senderAddress, derivationPath, derivedPublicKey, idx, bitgoKey) {
        const coinType = `${token.packageId}::${token.module}::${token.symbol}`;
        let tokenObjects = await this.getInputCoins(senderAddress, coinType);
        tokenObjects = tokenObjects.sort((a, b) => {
            return b.balance.minus(a.balance).toNumber();
        });
        if (tokenObjects.length > constants_1.TOKEN_OBJECT_LIMIT) {
            tokenObjects = tokenObjects.slice(0, constants_1.TOKEN_OBJECT_LIMIT);
        }
        const netAmount = tokenObjects.reduce((acc, obj) => acc.plus(obj.balance), new bignumber_js_1.default(0));
        const recipients = [
            {
                address: params.recoveryDestination,
                amount: netAmount.toString(),
            },
        ];
        const gasAmount = new bignumber_js_1.default(constants_1.MAX_GAS_BUDGET);
        let gasObjects = await this.getInputCoins(senderAddress);
        gasObjects = utils_1.default.selectObjectsInDescOrderOfBalance(gasObjects, gasAmount);
        if (gasObjects.length >= constants_1.MAX_GAS_OBJECTS) {
            gasObjects = gasObjects.slice(0, constants_1.MAX_GAS_OBJECTS - 1);
        }
        // first build the unsigned txn
        const factory = new lib_1.TransactionBuilderFactory(token);
        const txBuilder = factory
            .getTokenTransferBuilder()
            .type(iface_1.SuiTransactionType.TokenTransfer)
            .sender(senderAddress)
            .send(recipients)
            .inputObjects(tokenObjects)
            .gasData({
            owner: senderAddress,
            price: constants_1.DEFAULT_GAS_PRICE,
            budget: constants_1.MAX_GAS_BUDGET,
            payment: gasObjects,
        });
        const tempTx = (await txBuilder.build());
        const feeEstimate = await this.getFeeEstimate(tempTx.toBroadcastFormat());
        const gasBudget = Math.trunc(feeEstimate.toNumber() * constants_1.DEFAULT_GAS_OVERHEAD);
        txBuilder.gasData({
            owner: senderAddress,
            price: constants_1.DEFAULT_GAS_PRICE,
            budget: gasBudget,
            payment: gasObjects,
        });
        const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
        if (isUnsignedSweep) {
            return this.buildUnsignedSweepTransaction(txBuilder, senderAddress, bitgoKey, idx, derivationPath, token);
        }
        await this.signRecoveryTransaction(txBuilder, params, derivationPath, derivedPublicKey, true);
        const tx = (await txBuilder.build());
        return {
            transactions: [
                {
                    scanIndex: idx,
                    recoveryAmount: netAmount.toString(),
                    serializedTx: tx.toBroadcastFormat(),
                    signature: Buffer.from(tx.serializedSig).toString('base64'),
                    coin: token.name,
                },
            ],
            lastScanIndex: idx,
        };
    }
    async buildUnsignedSweepTransaction(txBuilder, senderAddress, bitgoKey, index, derivationPath, token) {
        const isTokenTransaction = !!token;
        const unsignedTransaction = isTokenTransaction
            ? (await txBuilder.build())
            : (await txBuilder.build());
        const serializedTx = unsignedTransaction.toBroadcastFormat();
        const serializedTxHex = Buffer.from(serializedTx, 'base64').toString('hex');
        const parsedTx = await this.parseTransaction({ txHex: serializedTxHex });
        const walletCoin = isTokenTransaction ? token.name : this.getChain();
        const output = parsedTx.outputs[0];
        const inputs = [
            {
                address: senderAddress,
                valueString: output.amount,
                value: new bignumber_js_1.default(output.amount),
            },
        ];
        const outputs = [
            {
                address: output.address,
                valueString: output.amount,
                coinName: walletCoin,
            },
        ];
        const spendAmount = output.amount;
        const completedParsedTx = {
            inputs: inputs,
            outputs: outputs,
            spendAmount: spendAmount,
            type: isTokenTransaction ? iface_1.SuiTransactionType.TokenTransfer : iface_1.SuiTransactionType.Transfer,
        };
        const fee = parsedTx.fee;
        const feeInfo = { fee: fee.toNumber(), feeString: fee.toString() };
        const coinSpecific = { commonKeychain: bitgoKey };
        const transaction = {
            serializedTx: serializedTxHex,
            scanIndex: index,
            coin: walletCoin,
            signableHex: unsignedTransaction.signablePayload.toString('hex'),
            derivationPath,
            parsedTx: completedParsedTx,
            feeInfo: feeInfo,
            coinSpecific: coinSpecific,
        };
        const unsignedTx = { unsignedTx: transaction, signatureShares: [] };
        const transactions = [unsignedTx];
        const txRequest = {
            transactions: transactions,
            walletCoin: walletCoin,
        };
        return { txRequests: [txRequest] };
    }
    async signRecoveryTransaction(txBuilder, params, derivationPath, derivedPublicKey, isTokenTransaction) {
        // TODO(BG-51092): This looks like a common part which can be extracted out too
        const unsignedTx = isTokenTransaction
            ? (await txBuilder.build())
            : (await txBuilder.build());
        if (!params.userKey) {
            throw new Error('missing userKey');
        }
        if (!params.backupKey) {
            throw new Error('missing backupKey');
        }
        if (!params.walletPassphrase) {
            throw new Error('missing wallet passphrase');
        }
        // Clean up whitespace from entered values
        const userKey = params.userKey.replace(/\s/g, '');
        const backupKey = params.backupKey.replace(/\s/g, '');
        // Decrypt private keys from KeyCard values
        let userPrv;
        try {
            userPrv = this.bitgo.decrypt({
                input: userKey,
                password: params.walletPassphrase,
            });
        }
        catch (e) {
            throw new Error(`Error decrypting user keychain: ${e.message}`);
        }
        /** TODO BG-52419 Implement Codec for parsing */
        const userSigningMaterial = JSON.parse(userPrv);
        let backupPrv;
        try {
            backupPrv = this.bitgo.decrypt({
                input: backupKey,
                password: params.walletPassphrase,
            });
        }
        catch (e) {
            throw new Error(`Error decrypting backup keychain: ${e.message}`);
        }
        const backupSigningMaterial = JSON.parse(backupPrv);
        /* ********************** END ***********************************/
        // add signature
        const signatureHex = await sdk_core_1.EDDSAMethods.getTSSSignature(userSigningMaterial, backupSigningMaterial, derivationPath, unsignedTx);
        txBuilder.addSignature({ pub: derivedPublicKey }, signatureHex);
    }
    async broadcastTransaction({ transactions, }) {
        const txIds = [];
        const url = this.getPublicNodeUrl();
        let digest = '';
        if (!!transactions) {
            for (const txn of transactions) {
                try {
                    digest = await utils_1.default.executeTransactionBlock(url, txn.serializedTx, [txn.signature]);
                }
                catch (e) {
                    throw new Error(`Failed to broadcast transaction, error: ${e.message}`);
                }
                txIds.push(digest);
            }
        }
        return { txIds };
    }
    /** inherited doc */
    async createBroadcastableSweepTransaction(params) {
        const req = params.signatureShares;
        const broadcastableTransactions = [];
        let lastScanIndex = 0;
        for (let i = 0; i < req.length; i++) {
            const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
            const transaction = req[i].txRequest.transactions[0].unsignedTx;
            if (!req[i].ovc || !req[i].ovc[0].eddsaSignature) {
                throw new Error('Missing signature(s)');
            }
            const signature = req[i].ovc[0].eddsaSignature;
            if (!transaction.signableHex) {
                throw new Error('Missing signable hex');
            }
            const messageBuffer = Buffer.from(transaction.signableHex, 'hex');
            const result = MPC.verify(messageBuffer, signature);
            if (!result) {
                throw new Error('Invalid signature');
            }
            const signatureHex = Buffer.concat([Buffer.from(signature.R, 'hex'), Buffer.from(signature.sigma, 'hex')]);
            const serializedTxBase64 = Buffer.from(transaction.serializedTx, 'hex').toString('base64');
            const txBuilder = this.getBuilder().from(serializedTxBase64);
            if (!transaction.coinSpecific?.commonKeychain) {
                throw new Error('Missing common keychain');
            }
            const commonKeychain = transaction.coinSpecific.commonKeychain;
            if (!transaction.derivationPath) {
                throw new Error('Missing derivation path');
            }
            const derivationPath = transaction.derivationPath;
            const derivedPublicKey = MPC.deriveUnhardened(commonKeychain, derivationPath).slice(0, 64);
            // add combined signature from ovc
            txBuilder.addSignature({ pub: derivedPublicKey }, signatureHex);
            const signedTransaction = (await txBuilder.build());
            const serializedTx = signedTransaction.toBroadcastFormat();
            const outputAmount = signedTransaction.explainTransaction().outputAmount;
            broadcastableTransactions.push({
                serializedTx: serializedTx,
                scanIndex: transaction.scanIndex,
                signature: Buffer.from(signedTransaction.serializedSig).toString('base64'),
                recoveryAmount: outputAmount.toString(),
            });
            if (i === req.length - 1 && transaction.coinSpecific.lastScanIndex) {
                lastScanIndex = transaction.coinSpecific.lastScanIndex;
            }
        }
        return { transactions: broadcastableTransactions, lastScanIndex };
    }
    /**
     * Builds native SUI recoveries of receive addresses in batch without BitGo.
     * Funds will be recovered to base address first. You need to initiate another sweep txn after that.
     *
     * @param {MPCConsolidationRecoveryOptions} params - options for consolidation recovery.
     * @param {string} [params.startingScanIndex] - receive address index to start scanning from. default to 1 (inclusive).
     * @param {string} [params.endingScanIndex] - receive address index to end scanning at. default to startingScanIndex + 20 (exclusive).
     */
    async recoverConsolidations(params) {
        const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
        const startIdx = utils_1.default.validateNonNegativeNumber(1, 'Invalid starting index to scan for addresses', params.startingScanIndex);
        const endIdx = utils_1.default.validateNonNegativeNumber(startIdx + constants_1.DEFAULT_SCAN_FACTOR, 'Invalid ending index to scan for addresses', params.endingScanIndex);
        if (startIdx < 1 || endIdx <= startIdx || endIdx - startIdx > 10 * constants_1.DEFAULT_SCAN_FACTOR) {
            throw new Error(`Invalid starting or ending index to scan for addresses. startingScanIndex: ${startIdx}, endingScanIndex: ${endIdx}.`);
        }
        const bitgoKey = params.bitgoKey.replace(/\s/g, '');
        const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
        const derivationPath = (params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) : 'm') + '/0';
        const derivedPublicKey = MPC.deriveUnhardened(bitgoKey, derivationPath).slice(0, 64);
        const baseAddress = this.getAddressFromPublicKey(derivedPublicKey);
        const consolidationTransactions = [];
        let lastScanIndex = startIdx;
        for (let idx = startIdx; idx < endIdx; idx++) {
            const recoverParams = {
                userKey: params.userKey,
                backupKey: params.backupKey,
                bitgoKey: params.bitgoKey,
                walletPassphrase: params.walletPassphrase,
                seed: params.seed,
                tokenContractAddress: params.tokenContractAddress,
                recoveryDestination: baseAddress,
                startingScanIndex: idx,
                scan: 1,
            };
            let recoveryTransaction;
            try {
                recoveryTransaction = await this.recover(recoverParams);
            }
            catch (e) {
                if (e.message.startsWith('Did not find an address with sufficient funds to recover.')) {
                    lastScanIndex = idx;
                    continue;
                }
                throw e;
            }
            if (isUnsignedSweep) {
                consolidationTransactions.push(recoveryTransaction.txRequests[0]);
            }
            else {
                consolidationTransactions.push(recoveryTransaction.transactions[0]);
            }
            lastScanIndex = idx;
        }
        if (consolidationTransactions.length === 0) {
            throw new Error(`Did not find an address with sufficient funds to recover. Please start the next scan at address index ${lastScanIndex + 1}.`);
        }
        if (isUnsignedSweep) {
            // lastScanIndex will be used to inform user the last address index scanned for available funds (so they can
            // appropriately adjust the scan range on the next iteration of consolidation recoveries). In the case of unsigned
            // sweep consolidations, this lastScanIndex will be provided in the coinSpecific of the last txn made.
            consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific.lastScanIndex = lastScanIndex;
            return { txRequests: consolidationTransactions };
        }
        return { transactions: consolidationTransactions, lastScanIndex };
    }
    /** inherited doc */
    setCoinSpecificFieldsInIntent(intent, params) {
        intent.unspents = params.unspents;
    }
    /** inherited doc */
    auditDecryptedKey({ publicKey, prv, multiSigType }) {
        if (multiSigType !== 'tss') {
            throw new Error('Unsupported multiSigType');
        }
        (0, sdk_lib_mpc_1.auditEddsaPrivateKey)(prv, publicKey ?? '');
    }
}
exports.Sui = Sui;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N1aS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw4Q0FnQ3lCO0FBQ3pCLDRDQUEwRjtBQUMxRixnRUFBcUM7QUFDckMsK0JBTWU7QUFDZix3REFBZ0M7QUFDaEMsMENBQTRCO0FBQzVCLHVDQUFnRTtBQUNoRSwrQ0FReUI7QUFDekIsb0RBQTZFO0FBNkI3RSxNQUFhLEdBQUksU0FBUSxtQkFBUTtJQUUvQixZQUFzQixLQUFnQixFQUFFLFdBQXVDO1FBQzdFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUViLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDeEUsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsT0FBTyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksYUFBYTtRQUNsQixPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTSxRQUFRO1FBQ2IsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU0sU0FBUztRQUNkLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVNLFdBQVc7UUFDaEIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsVUFBVTtRQUNSLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7SUFDbkMsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsb0JBQW9CO0lBQ3BCLHNCQUFzQjtRQUNwQixPQUFPLHdC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RztZQUM1RyxrSEFBa0g7WUFDbEgsc0dBQXNHO1lBQ3RHLHlCQUF5QixDQUN2Qix5QkFBeUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUNyQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7WUFDeEUsT0FBTyxFQUFFLFVBQVUsRUFBRSx5QkFBeUIsRUFBRSxDQUFDO1FBQ25ELENBQUM7UUFFRCxPQUFPLEVBQUUsWUFBWSxFQUFFLHlCQUF5QixFQUFFLGFBQWEsRUFBRSxDQUFDO0lBQ3BFLENBQUM7SUFFRCxvQkFBb0I7SUFDcEIsNkJBQTZCLENBQUMsTUFBdUIsRUFBRSxNQUE0QztRQUNqRyxNQUFNLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUM7SUFDcEMsQ0FBQztJQUVELG9CQUFvQjtJQUNwQixpQkFBaUIsQ0FBQyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUEyQjtRQUN6RSxJQUFJLFlBQVksS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUVELElBQUEsa0NBQW9CLEVBQUMsR0FBRyxFQUFFLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM3QyxDQUFDO0NBQ0Y7QUF6dUJELGtCQXl1QkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25PcHRpb25zLFxuICBCYXNlQnJvYWRjYXN0VHJhbnNhY3Rpb25SZXN1bHQsXG4gIEJhc2VDb2luLFxuICBCYXNlVHJhbnNhY3Rpb24sXG4gIEJpdEdvQmFzZSxcbiAgRUREU0FNZXRob2RzLFxuICBFRERTQU1ldGhvZFR5cGVzLFxuICBFbnZpcm9ubWVudHMsXG4gIEludmFsaWRBZGRyZXNzRXJyb3IsXG4gIEtleVBhaXIsXG4gIE1QQ0FsZ29yaXRobSxcbiAgTVBDUmVjb3ZlcnlPcHRpb25zLFxuICBNUENDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zLFxuICBNUENTd2VlcFJlY292ZXJ5T3B0aW9ucyxcbiAgTVBDU3dlZXBUeHMsXG4gIE1QQ1R4LFxuICBNUENUeHMsXG4gIE1QQ1Vuc2lnbmVkVHgsXG4gIFBhcnNlZFRyYW5zYWN0aW9uLFxuICBQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyBhcyBCYXNlUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFJlY292ZXJ5VHhSZXF1ZXN0LFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbixcbiAgVHNzVmVyaWZ5QWRkcmVzc09wdGlvbnMsXG4gIFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgUG9wdWxhdGVkSW50ZW50LFxuICBQcmVidWlsZFRyYW5zYWN0aW9uV2l0aEludGVudE9wdGlvbnMsXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4sIEJhc2VOZXR3b3JrLCBjb2lucywgU3VpQ29pbiB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7XG4gIEtleVBhaXIgYXMgU3VpS2V5UGFpcixcbiAgVG9rZW5UcmFuc2ZlclRyYW5zYWN0aW9uLFxuICBUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gIFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnksXG4gIFRyYW5zZmVyVHJhbnNhY3Rpb24sXG59IGZyb20gJy4vbGliJztcbmltcG9ydCB1dGlscyBmcm9tICcuL2xpYi91dGlscyc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBTdWlPYmplY3RJbmZvLCBTdWlUcmFuc2FjdGlvblR5cGUgfSBmcm9tICcuL2xpYi9pZmFjZSc7XG5pbXBvcnQge1xuICBERUZBVUxUX0dBU19PVkVSSEVBRCxcbiAgREVGQVVMVF9HQVNfUFJJQ0UsXG4gIERFRkFVTFRfU0NBTl9GQUNUT1IsXG4gIE1BWF9HQVNfQlVER0VULFxuICBNQVhfR0FTX09CSkVDVFMsXG4gIE1BWF9PQkpFQ1RfTElNSVQsXG4gIFRPS0VOX09CSkVDVF9MSU1JVCxcbn0gZnJvbSAnLi9saWIvY29uc3RhbnRzJztcbmltcG9ydCB7IGF1ZGl0RWRkc2FQcml2YXRlS2V5LCBnZXREZXJpdmF0aW9uUGF0aCB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIHR4SGV4OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VpUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMgZXh0ZW5kcyBCYXNlUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eEhleDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgVHJhbnNhY3Rpb25PdXRwdXQge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogc3RyaW5nO1xufVxuXG50eXBlIFRyYW5zYWN0aW9uSW5wdXQgPSBUcmFuc2FjdGlvbk91dHB1dDtcblxuZXhwb3J0IGludGVyZmFjZSBTdWlQYXJzZWRUcmFuc2FjdGlvbiBleHRlbmRzIFBhcnNlZFRyYW5zYWN0aW9uIHtcbiAgLy8gdG90YWwgYXNzZXRzIGJlaW5nIG1vdmVkLCBpbmNsdWRpbmcgZmVlc1xuICBpbnB1dHM6IFRyYW5zYWN0aW9uSW5wdXRbXTtcblxuICAvLyB3aGVyZSBhc3NldHMgYXJlIG1vdmVkIHRvXG4gIG91dHB1dHM6IFRyYW5zYWN0aW9uT3V0cHV0W107XG5cbiAgZmVlOiBCaWdOdW1iZXI7XG59XG5cbmV4cG9ydCB0eXBlIFN1aVRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uO1xuXG5leHBvcnQgY2xhc3MgU3VpIGV4dGVuZHMgQmFzZUNvaW4ge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX3N0YXRpY3NDb2luOiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+O1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlSW5zdGFuY2UoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KTogQmFzZUNvaW4ge1xuICAgIHJldHVybiBuZXcgU3VpKGJpdGdvLCBzdGF0aWNzQ29pbik7XG4gIH1cblxuICAvKipcbiAgICogRmFjdG9yIGJldHdlZW4gdGhlIGNvaW4ncyBiYXNlIHVuaXQgYW5kIGl0cyBzbWFsbGVzdCBzdWJkaXZpc29uXG4gICAqL1xuICBwdWJsaWMgZ2V0QmFzZUZhY3RvcigpOiBudW1iZXIge1xuICAgIHJldHVybiAxZTk7XG4gIH1cblxuICBwdWJsaWMgZ2V0Q2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ3N1aSc7XG4gIH1cblxuICBwdWJsaWMgZ2V0RmFtaWx5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdzdWknO1xuICB9XG5cbiAgcHVibGljIGdldEZ1bGxOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdTdWknO1xuICB9XG5cbiAgZ2V0TmV0d29yaygpOiBCYXNlTmV0d29yayB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRpY3NDb2luLm5ldHdvcms7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgc3VwcG9ydHNUc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogaW5oZXJpdGVkIGRvYyAqL1xuICBnZXREZWZhdWx0TXVsdGlzaWdUeXBlKCk6IE11bHRpc2lnVHlwZSB7XG4gICAgcmV0dXJuIG11bHRpc2lnVHlwZXMudHNzO1xuICB9XG5cbiAgZ2V0TVBDQWxnb3JpdGhtKCk6IE1QQ0FsZ29yaXRobSB7XG4gICAgcmV0dXJuICdlZGRzYSc7XG4gIH1cblxuICBhbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBhc3luYyB2ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXM6IFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGxldCB0b3RhbEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgY29uc3QgY29pbkNvbmZpZyA9IGNvaW5zLmdldCh0aGlzLmdldENoYWluKCkpO1xuICAgIGNvbnN0IHsgdHhQcmVidWlsZDogdHhQcmVidWlsZCwgdHhQYXJhbXM6IHR4UGFyYW1zLCB2ZXJpZmljYXRpb24sIHdhbGxldCB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gbmV3IFRyYW5zZmVyVHJhbnNhY3Rpb24oY29pbkNvbmZpZyk7XG4gICAgY29uc3QgcmF3VHggPSB0eFByZWJ1aWxkLnR4SGV4O1xuICAgIGlmICghcmF3VHgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0eCBwcmVidWlsZCBwcm9wZXJ0eSB0eEhleCcpO1xuICAgIH1cblxuICAgIHRyYW5zYWN0aW9uLmZyb21SYXdUcmFuc2FjdGlvbihCdWZmZXIuZnJvbShyYXdUeCwgJ2hleCcpLnRvU3RyaW5nKCdiYXNlNjQnKSk7XG4gICAgY29uc3QgZXhwbGFpbmVkVHggPSB0cmFuc2FjdGlvbi5leHBsYWluVHJhbnNhY3Rpb24oKTtcblxuICAgIGlmICh0eFBhcmFtcy5yZWNpcGllbnRzICYmIHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZmlsdGVyZWRSZWNpcGllbnRzID0gdHhQYXJhbXMucmVjaXBpZW50cz8ubWFwKChyZWNpcGllbnQpID0+IHtcbiAgICAgICAgY29uc3QgZmlsdGVyZWRSZWNpcGllbnQgPSBfLnBpY2socmVjaXBpZW50LCBbJ2FkZHJlc3MnLCAnYW1vdW50J10pO1xuICAgICAgICBmaWx0ZXJlZFJlY2lwaWVudC5hbW91bnQgPSBuZXcgQmlnTnVtYmVyKGZpbHRlcmVkUmVjaXBpZW50LmFtb3VudCkudG9GaXhlZCgpO1xuICAgICAgICByZXR1cm4gZmlsdGVyZWRSZWNpcGllbnQ7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkT3V0cHV0cyA9IGV4cGxhaW5lZFR4Lm91dHB1dHMubWFwKChvdXRwdXQpID0+IHtcbiAgICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXQgPSBfLnBpY2sob3V0cHV0LCBbJ2FkZHJlc3MnLCAnYW1vdW50J10pO1xuICAgICAgICBmaWx0ZXJlZE91dHB1dC5hbW91bnQgPSBuZXcgQmlnTnVtYmVyKGZpbHRlcmVkT3V0cHV0LmFtb3VudCkudG9GaXhlZCgpO1xuICAgICAgICByZXR1cm4gZmlsdGVyZWRPdXRwdXQ7XG4gICAgICB9KTtcblxuICAgICAgaWYgKCFfLmlzRXF1YWwoZmlsdGVyZWRPdXRwdXRzLCBmaWx0ZXJlZFJlY2lwaWVudHMpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVHggb3V0cHV0cyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIHR4UGFyYW1zIHJlY2lwaWVudHMnKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgcmVjaXBpZW50cyBvZiB0eFBhcmFtcy5yZWNpcGllbnRzKSB7XG4gICAgICAgIHRvdGFsQW1vdW50ID0gdG90YWxBbW91bnQucGx1cyhyZWNpcGllbnRzLmFtb3VudCk7XG4gICAgICB9XG4gICAgICBpZiAoIXRvdGFsQW1vdW50LmlzRXF1YWxUbyhleHBsYWluZWRUeC5vdXRwdXRBbW91bnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVHggdG90YWwgYW1vdW50IGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdG90YWwgYW1vdW50IGZpZWxkJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZlcmlmaWNhdGlvbj8uY29uc29saWRhdGlvblRvQmFzZUFkZHJlc3MpIHtcbiAgICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gd2FsbGV0LmNvaW5TcGVjaWZpYygpPy5iYXNlQWRkcmVzcyB8fCB3YWxsZXQuY29pblNwZWNpZmljKCk/LnJvb3RBZGRyZXNzO1xuXG4gICAgICBmb3IgKGNvbnN0IG91dHB1dCBvZiBleHBsYWluZWRUeC5vdXRwdXRzKSB7XG4gICAgICAgIGlmIChvdXRwdXQuYWRkcmVzcyAhPT0gYmFzZUFkZHJlc3MpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnNvbGlkYXRpb24gdHJhbnNhY3Rpb24gb3V0cHV0IGFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggd2FsbGV0IGJhc2UgYWRkcmVzcycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBhc3luYyBpc1dhbGxldEFkZHJlc3MocGFyYW1zOiBUc3NWZXJpZnlBZGRyZXNzT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHsgYWRkcmVzczogbmV3QWRkcmVzcyB9ID0gcGFyYW1zO1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKG5ld0FkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAke25ld0FkZHJlc3N9YCk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFN1aVBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxTdWlQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSBhd2FpdCB0aGlzLmV4cGxhaW5UcmFuc2FjdGlvbih7IHR4SGV4OiBwYXJhbXMudHhIZXggfSk7XG5cbiAgICBpZiAoIXRyYW5zYWN0aW9uRXhwbGFuYXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGxldCBmZWUgPSBuZXcgQmlnTnVtYmVyKDApO1xuXG4gICAgY29uc3Qgc3VpVHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbkV4cGxhbmF0aW9uIGFzIFN1aVRyYW5zYWN0aW9uRXhwbGFuYXRpb247XG4gICAgaWYgKHN1aVRyYW5zYWN0aW9uLm91dHB1dHMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGlucHV0czogW10sXG4gICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgICBmZWUsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBzdWlUcmFuc2FjdGlvbi5vdXRwdXRzWzBdLmFkZHJlc3M7XG4gICAgaWYgKHN1aVRyYW5zYWN0aW9uLmZlZS5mZWUgIT09ICcnKSB7XG4gICAgICBmZWUgPSBuZXcgQmlnTnVtYmVyKHN1aVRyYW5zYWN0aW9uLmZlZS5mZWUpO1xuICAgIH1cblxuICAgIC8vIGFzc3VtZSAxIHNlbmRlciwgd2hvIGlzIGFsc28gdGhlIGZlZSBwYXllclxuICAgIGNvbnN0IGlucHV0cyA9IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogc2VuZGVyQWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKHN1aVRyYW5zYWN0aW9uLm91dHB1dEFtb3VudCkucGx1cyhmZWUpLnRvRml4ZWQoKSxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIGNvbnN0IG91dHB1dHM6IFRyYW5zYWN0aW9uT3V0cHV0W10gPSBzdWlUcmFuc2FjdGlvbi5vdXRwdXRzLm1hcCgob3V0cHV0KSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhZGRyZXNzOiBvdXRwdXQuYWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKG91dHB1dC5hbW91bnQpLnRvRml4ZWQoKSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaW5wdXRzLFxuICAgICAgb3V0cHV0cyxcbiAgICAgIGZlZSxcbiAgICB9O1xuICB9XG5cbiAgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIpOiBLZXlQYWlyIHtcbiAgICBjb25zdCBrZXlQYWlyID0gc2VlZCA/IG5ldyBTdWlLZXlQYWlyKHsgc2VlZCB9KSA6IG5ldyBTdWlLZXlQYWlyKCk7XG4gICAgY29uc3Qga2V5cyA9IGtleVBhaXIuZ2V0S2V5cygpO1xuICAgIGlmICgha2V5cy5wcnYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBwcnYgaW4ga2V5IGdlbmVyYXRpb24uJyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBwdWI6IGtleXMucHViLFxuICAgICAgcHJ2OiBrZXlzLnBydixcbiAgICB9O1xuICB9XG5cbiAgaXNWYWxpZFB1YihfOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gIH1cblxuICBpc1ZhbGlkUHJ2KF86IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuXG4gIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKTtcbiAgfVxuXG4gIHNpZ25UcmFuc2FjdGlvbihfOiBTaWduVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxTaWduZWRUcmFuc2FjdGlvbj4ge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBsYWluIGEgU3VpIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIGFzeW5jIGV4cGxhaW5UcmFuc2FjdGlvbihwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFN1aVRyYW5zYWN0aW9uRXhwbGFuYXRpb24+IHtcbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyKCk7XG4gICAgbGV0IHJlYnVpbHRUcmFuc2FjdGlvbjogQmFzZVRyYW5zYWN0aW9uO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uQnVpbGRlciA9IGZhY3RvcnkuZnJvbShCdWZmZXIuZnJvbShwYXJhbXMudHhIZXgsICdoZXgnKS50b1N0cmluZygnYmFzZTY0JykpO1xuICAgICAgcmVidWlsdFRyYW5zYWN0aW9uID0gYXdhaXQgdHJhbnNhY3Rpb25CdWlsZGVyLmJ1aWxkKCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVidWlsdFRyYW5zYWN0aW9uLmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRCdWlsZGVyKCk6IFRyYW5zYWN0aW9uQnVpbGRlckZhY3Rvcnkge1xuICAgIHJldHVybiBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2lucy5nZXQodGhpcy5nZXRDaGFpbigpKSk7XG4gIH1cblxuICBwcml2YXRlIGdldEFkZHJlc3NGcm9tUHVibGljS2V5KGRlcml2ZWRQdWJsaWNLZXk6IHN0cmluZykge1xuICAgIC8vIFRPRE8oQkctNTkwMTYpIHJlcGxhY2Ugd2l0aCBhY2NvdW50IGxpYiBpbXBsZW1lbnRhdGlvblxuICAgIHJldHVybiB1dGlscy5nZXRBZGRyZXNzRnJvbVB1YmxpY0tleShkZXJpdmVkUHVibGljS2V5KTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhc3luYyBnZXRTaWduYWJsZVBheWxvYWQoc2VyaWFsaXplZFR4OiBzdHJpbmcpOiBQcm9taXNlPEJ1ZmZlcj4ge1xuICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXIoKTtcbiAgICBjb25zdCByZWJ1aWx0VHJhbnNhY3Rpb24gPSBhd2FpdCBmYWN0b3J5LmZyb20oc2VyaWFsaXplZFR4KS5idWlsZCgpO1xuICAgIHJldHVybiByZWJ1aWx0VHJhbnNhY3Rpb24uc2lnbmFibGVQYXlsb2FkO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFB1YmxpY05vZGVVcmwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLnN1aU5vZGVVcmw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0QmFsYW5jZShvd25lcjogc3RyaW5nLCBjb2luVHlwZT86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgdXJsID0gdGhpcy5nZXRQdWJsaWNOb2RlVXJsKCk7XG4gICAgcmV0dXJuIGF3YWl0IHV0aWxzLmdldEJhbGFuY2UodXJsLCBvd25lciwgY29pblR5cGUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldElucHV0Q29pbnMob3duZXI6IHN0cmluZywgY29pblR5cGU/OiBzdHJpbmcpOiBQcm9taXNlPFN1aU9iamVjdEluZm9bXT4ge1xuICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0UHVibGljTm9kZVVybCgpO1xuICAgIHJldHVybiBhd2FpdCB1dGlscy5nZXRJbnB1dENvaW5zKHVybCwgb3duZXIsIGNvaW5UeXBlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRGZWVFc3RpbWF0ZSh0eEhleDogc3RyaW5nKTogUHJvbWlzZTxCaWdOdW1iZXI+IHtcbiAgICBjb25zdCB1cmwgPSB0aGlzLmdldFB1YmxpY05vZGVVcmwoKTtcbiAgICByZXR1cm4gYXdhaXQgdXRpbHMuZ2V0RmVlRXN0aW1hdGUodXJsLCB0eEhleCk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGZ1bmRzIHJlY292ZXJ5IHRyYW5zYWN0aW9uKHMpIHdpdGhvdXQgQml0R29cbiAgICpcbiAgICogQHBhcmFtIHtNUENSZWNvdmVyeU9wdGlvbnN9IHBhcmFtcyBwYXJhbWV0ZXJzIG5lZWRlZCB0byBjb25zdHJ1Y3QgYW5kXG4gICAqIChtYXliZSkgc2lnbiB0aGUgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHJldHVybnMge01QQ1R4IHwgTVBDU3dlZXBUeHN9IGFycmF5IG9mIHRoZSBzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGhleCBzdHJpbmdzIGFuZCBpbmRpY2VzXG4gICAqIG9mIHRoZSBhZGRyZXNzZXMgYmVpbmcgc3dlcHRcbiAgICovXG4gIGFzeW5jIHJlY292ZXIocGFyYW1zOiBNUENSZWNvdmVyeU9wdGlvbnMpOiBQcm9taXNlPE1QQ1R4cyB8IE1QQ1N3ZWVwVHhzPiB7XG4gICAgaWYgKCFwYXJhbXMuYml0Z29LZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiaXRnb0tleScpO1xuICAgIH1cbiAgICBpZiAoIXBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFydElkeCA9IHV0aWxzLnZhbGlkYXRlTm9uTmVnYXRpdmVOdW1iZXIoXG4gICAgICAwLFxuICAgICAgJ0ludmFsaWQgc3RhcnRpbmcgaW5kZXggdG8gc2NhbiBmb3IgYWRkcmVzc2VzJyxcbiAgICAgIHBhcmFtcy5zdGFydGluZ1NjYW5JbmRleFxuICAgICk7XG4gICAgY29uc3QgbnVtSXRlcmF0aW9ucyA9IHV0aWxzLnZhbGlkYXRlTm9uTmVnYXRpdmVOdW1iZXIoMjAsICdJbnZhbGlkIHNjYW5uaW5nIGZhY3RvcicsIHBhcmFtcy5zY2FuKTtcbiAgICBjb25zdCBlbmRJZHggPSBzdGFydElkeCArIG51bUl0ZXJhdGlvbnM7XG4gICAgY29uc3QgYml0Z29LZXkgPSBwYXJhbXMuYml0Z29LZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBNUEMgPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpO1xuXG4gICAgZm9yIChsZXQgaWR4ID0gc3RhcnRJZHg7IGlkeCA8IGVuZElkeDsgaWR4KyspIHtcbiAgICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gKHBhcmFtcy5zZWVkID8gZ2V0RGVyaXZhdGlvblBhdGgocGFyYW1zLnNlZWQpIDogJ20nKSArIGAvJHtpZHh9YDtcbiAgICAgIGNvbnN0IGRlcml2ZWRQdWJsaWNLZXkgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChiaXRnb0tleSwgZGVyaXZhdGlvblBhdGgpLnNsaWNlKDAsIDY0KTtcbiAgICAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSB0aGlzLmdldEFkZHJlc3NGcm9tUHVibGljS2V5KGRlcml2ZWRQdWJsaWNLZXkpO1xuICAgICAgbGV0IGF2YWlsYWJsZUJhbGFuY2UgPSBuZXcgQmlnTnVtYmVyKDApO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXZhaWxhYmxlQmFsYW5jZSA9IG5ldyBCaWdOdW1iZXIoYXdhaXQgdGhpcy5nZXRCYWxhbmNlKHNlbmRlckFkZHJlc3MpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoYXZhaWxhYmxlQmFsYW5jZS5taW51cyhNQVhfR0FTX0JVREdFVCkudG9OdW1iZXIoKSA8PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBjaGVjayBmb3IgcG9zc2libGUgdG9rZW4gcmVjb3ZlcnksIHJlY292ZXIgdGhlIHRva2VuIHByb3ZpZGUgYnkgdXNlclxuICAgICAgaWYgKHBhcmFtcy50b2tlbkNvbnRyYWN0QWRkcmVzcykge1xuICAgICAgICBjb25zdCB0b2tlbiA9IHV0aWxzLmdldFN1aVRva2VuRnJvbUFkZHJlc3MocGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzISwgdGhpcy5nZXROZXR3b3JrKCkpIGFzIFN1aUNvaW47XG4gICAgICAgIGlmICghdG9rZW4pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFN1aSBUb2tlbiBQYWNrYWdlIElEIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29pblR5cGUgPSBgJHt0b2tlbi5wYWNrYWdlSWR9Ojoke3Rva2VuLm1vZHVsZX06OiR7dG9rZW4uc3ltYm9sfWA7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYXZhaWxhYmxlVG9rZW5CYWxhbmNlID0gbmV3IEJpZ051bWJlcihhd2FpdCB0aGlzLmdldEJhbGFuY2Uoc2VuZGVyQWRkcmVzcywgY29pblR5cGUpKTtcbiAgICAgICAgICBpZiAoYXZhaWxhYmxlVG9rZW5CYWxhbmNlLnRvTnVtYmVyKCkgPD0gMCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmVjb3ZlclN1aVRva2VuKHBhcmFtcywgdG9rZW4sIHNlbmRlckFkZHJlc3MsIGRlcml2YXRpb25QYXRoLCBkZXJpdmVkUHVibGljS2V5LCBpZHgsIGJpdGdvS2V5KTtcbiAgICAgIH1cblxuICAgICAgbGV0IGlucHV0Q29pbnMgPSBhd2FpdCB0aGlzLmdldElucHV0Q29pbnMoc2VuZGVyQWRkcmVzcyk7XG4gICAgICBpbnB1dENvaW5zID0gaW5wdXRDb2lucy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgIHJldHVybiBiLmJhbGFuY2UubWludXMoYS5iYWxhbmNlKS50b051bWJlcigpO1xuICAgICAgfSk7XG4gICAgICBpZiAoaW5wdXRDb2lucy5sZW5ndGggPiBNQVhfT0JKRUNUX0xJTUlUKSB7XG4gICAgICAgIGlucHV0Q29pbnMgPSBpbnB1dENvaW5zLnNsaWNlKDAsIE1BWF9PQkpFQ1RfTElNSVQpO1xuICAgICAgfVxuICAgICAgbGV0IG5ldEFtb3VudCA9IGlucHV0Q29pbnMucmVkdWNlKChhY2MsIG9iaikgPT4gYWNjLnBsdXMob2JqLmJhbGFuY2UpLCBuZXcgQmlnTnVtYmVyKDApKTtcbiAgICAgIG5ldEFtb3VudCA9IG5ldEFtb3VudC5taW51cyhNQVhfR0FTX0JVREdFVCk7XG5cbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICBhbW91bnQ6IG5ldEFtb3VudC50b1N0cmluZygpLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgLy8gZmlyc3QgYnVpbGQgdGhlIHVuc2lnbmVkIHR4blxuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW5zLmdldCh0aGlzLmdldENoYWluKCkpKTtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgICAgLmdldFRyYW5zZmVyQnVpbGRlcigpXG4gICAgICAgIC50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2ZlcilcbiAgICAgICAgLnNlbmRlcihzZW5kZXJBZGRyZXNzKVxuICAgICAgICAuc2VuZChyZWNpcGllbnRzKVxuICAgICAgICAuZ2FzRGF0YSh7XG4gICAgICAgICAgb3duZXI6IHNlbmRlckFkZHJlc3MsXG4gICAgICAgICAgcHJpY2U6IERFRkFVTFRfR0FTX1BSSUNFLFxuICAgICAgICAgIGJ1ZGdldDogTUFYX0dBU19CVURHRVQsXG4gICAgICAgICAgcGF5bWVudDogaW5wdXRDb2lucyxcbiAgICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBUeCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNmZXJUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IGZlZUVzdGltYXRlID0gYXdhaXQgdGhpcy5nZXRGZWVFc3RpbWF0ZSh0ZW1wVHgudG9Ccm9hZGNhc3RGb3JtYXQoKSk7XG4gICAgICBjb25zdCBnYXNCdWRnZXQgPSBNYXRoLnRydW5jKGZlZUVzdGltYXRlLnRvTnVtYmVyKCkgKiBERUZBVUxUX0dBU19PVkVSSEVBRCk7XG5cbiAgICAgIG5ldEFtb3VudCA9IG5ldEFtb3VudC5wbHVzKE1BWF9HQVNfQlVER0VUKS5taW51cyhnYXNCdWRnZXQpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQgPSBuZXRBbW91bnQudG9TdHJpbmcoKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoe1xuICAgICAgICBvd25lcjogc2VuZGVyQWRkcmVzcyxcbiAgICAgICAgcHJpY2U6IERFRkFVTFRfR0FTX1BSSUNFLFxuICAgICAgICBidWRnZXQ6IGdhc0J1ZGdldCxcbiAgICAgICAgcGF5bWVudDogaW5wdXRDb2lucyxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSAhcGFyYW1zLnVzZXJLZXkgJiYgIXBhcmFtcy5iYWNrdXBLZXkgJiYgIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlO1xuICAgICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgICByZXR1cm4gdGhpcy5idWlsZFVuc2lnbmVkU3dlZXBUcmFuc2FjdGlvbih0eEJ1aWxkZXIsIHNlbmRlckFkZHJlc3MsIGJpdGdvS2V5LCBpZHgsIGRlcml2YXRpb25QYXRoKTtcbiAgICAgIH1cblxuICAgICAgYXdhaXQgdGhpcy5zaWduUmVjb3ZlcnlUcmFuc2FjdGlvbih0eEJ1aWxkZXIsIHBhcmFtcywgZGVyaXZhdGlvblBhdGgsIGRlcml2ZWRQdWJsaWNLZXksIGZhbHNlKTtcbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2ZlclRyYW5zYWN0aW9uO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgc2NhbkluZGV4OiBpZHgsXG4gICAgICAgICAgICByZWNvdmVyeUFtb3VudDogbmV0QW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBzZXJpYWxpemVkVHg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgICAgICBzaWduYXR1cmU6IEJ1ZmZlci5mcm9tKHR4LnNlcmlhbGl6ZWRTaWcpLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgICAgIGNvaW46IHRoaXMuZ2V0Q2hhaW4oKSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBsYXN0U2NhbkluZGV4OiBpZHgsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIHN1ZmZpY2llbnQgZnVuZHMgdG8gcmVjb3Zlci4gUGxlYXNlIHN0YXJ0IHRoZSBuZXh0IHNjYW4gYXQgYWRkcmVzcyBpbmRleCAke2VuZElkeH0uIElmIGl0IGlzIHRva2VuIHRyYW5zYWN0aW9uLCBwbGVhc2Uga2VlcCBzdWZmaWNpZW50IFN1aSBiYWxhbmNlIGluIHRoZSBhZGRyZXNzIGZvciB0aGUgdHJhbnNhY3Rpb24gZmVlLmBcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWNvdmVyU3VpVG9rZW4oXG4gICAgcGFyYW1zOiBNUENSZWNvdmVyeU9wdGlvbnMsXG4gICAgdG9rZW46IFN1aUNvaW4sXG4gICAgc2VuZGVyQWRkcmVzczogc3RyaW5nLFxuICAgIGRlcml2YXRpb25QYXRoOiBzdHJpbmcsXG4gICAgZGVyaXZlZFB1YmxpY0tleTogc3RyaW5nLFxuICAgIGlkeDogbnVtYmVyLFxuICAgIGJpdGdvS2V5OiBzdHJpbmdcbiAgKTogUHJvbWlzZTxNUENUeHMgfCBNUENTd2VlcFR4cz4ge1xuICAgIGNvbnN0IGNvaW5UeXBlID0gYCR7dG9rZW4ucGFja2FnZUlkfTo6JHt0b2tlbi5tb2R1bGV9Ojoke3Rva2VuLnN5bWJvbH1gO1xuICAgIGxldCB0b2tlbk9iamVjdHMgPSBhd2FpdCB0aGlzLmdldElucHV0Q29pbnMoc2VuZGVyQWRkcmVzcywgY29pblR5cGUpO1xuICAgIHRva2VuT2JqZWN0cyA9IHRva2VuT2JqZWN0cy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICByZXR1cm4gYi5iYWxhbmNlLm1pbnVzKGEuYmFsYW5jZSkudG9OdW1iZXIoKTtcbiAgICB9KTtcbiAgICBpZiAodG9rZW5PYmplY3RzLmxlbmd0aCA+IFRPS0VOX09CSkVDVF9MSU1JVCkge1xuICAgICAgdG9rZW5PYmplY3RzID0gdG9rZW5PYmplY3RzLnNsaWNlKDAsIFRPS0VOX09CSkVDVF9MSU1JVCk7XG4gICAgfVxuICAgIGNvbnN0IG5ldEFtb3VudCA9IHRva2VuT2JqZWN0cy5yZWR1Y2UoKGFjYywgb2JqKSA9PiBhY2MucGx1cyhvYmouYmFsYW5jZSksIG5ldyBCaWdOdW1iZXIoMCkpO1xuICAgIGNvbnN0IHJlY2lwaWVudHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQ6IG5ldEFtb3VudC50b1N0cmluZygpLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgY29uc3QgZ2FzQW1vdW50ID0gbmV3IEJpZ051bWJlcihNQVhfR0FTX0JVREdFVCk7XG4gICAgbGV0IGdhc09iamVjdHMgPSBhd2FpdCB0aGlzLmdldElucHV0Q29pbnMoc2VuZGVyQWRkcmVzcyk7XG4gICAgZ2FzT2JqZWN0cyA9IHV0aWxzLnNlbGVjdE9iamVjdHNJbkRlc2NPcmRlck9mQmFsYW5jZShnYXNPYmplY3RzLCBnYXNBbW91bnQpO1xuICAgIGlmIChnYXNPYmplY3RzLmxlbmd0aCA+PSBNQVhfR0FTX09CSkVDVFMpIHtcbiAgICAgIGdhc09iamVjdHMgPSBnYXNPYmplY3RzLnNsaWNlKDAsIE1BWF9HQVNfT0JKRUNUUyAtIDEpO1xuICAgIH1cblxuICAgIC8vIGZpcnN0IGJ1aWxkIHRoZSB1bnNpZ25lZCB0eG5cbiAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkodG9rZW4pO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnlcbiAgICAgIC5nZXRUb2tlblRyYW5zZmVyQnVpbGRlcigpXG4gICAgICAudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVG9rZW5UcmFuc2ZlcilcbiAgICAgIC5zZW5kZXIoc2VuZGVyQWRkcmVzcylcbiAgICAgIC5zZW5kKHJlY2lwaWVudHMpXG4gICAgICAuaW5wdXRPYmplY3RzKHRva2VuT2JqZWN0cylcbiAgICAgIC5nYXNEYXRhKHtcbiAgICAgICAgb3duZXI6IHNlbmRlckFkZHJlc3MsXG4gICAgICAgIHByaWNlOiBERUZBVUxUX0dBU19QUklDRSxcbiAgICAgICAgYnVkZ2V0OiBNQVhfR0FTX0JVREdFVCxcbiAgICAgICAgcGF5bWVudDogZ2FzT2JqZWN0cyxcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgdGVtcFR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUb2tlblRyYW5zZmVyVHJhbnNhY3Rpb247XG4gICAgY29uc3QgZmVlRXN0aW1hdGUgPSBhd2FpdCB0aGlzLmdldEZlZUVzdGltYXRlKHRlbXBUeC50b0Jyb2FkY2FzdEZvcm1hdCgpKTtcbiAgICBjb25zdCBnYXNCdWRnZXQgPSBNYXRoLnRydW5jKGZlZUVzdGltYXRlLnRvTnVtYmVyKCkgKiBERUZBVUxUX0dBU19PVkVSSEVBRCk7XG5cbiAgICB0eEJ1aWxkZXIuZ2FzRGF0YSh7XG4gICAgICBvd25lcjogc2VuZGVyQWRkcmVzcyxcbiAgICAgIHByaWNlOiBERUZBVUxUX0dBU19QUklDRSxcbiAgICAgIGJ1ZGdldDogZ2FzQnVkZ2V0LFxuICAgICAgcGF5bWVudDogZ2FzT2JqZWN0cyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9ICFwYXJhbXMudXNlcktleSAmJiAhcGFyYW1zLmJhY2t1cEtleSAmJiAhcGFyYW1zLndhbGxldFBhc3NwaHJhc2U7XG4gICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgcmV0dXJuIHRoaXMuYnVpbGRVbnNpZ25lZFN3ZWVwVHJhbnNhY3Rpb24odHhCdWlsZGVyLCBzZW5kZXJBZGRyZXNzLCBiaXRnb0tleSwgaWR4LCBkZXJpdmF0aW9uUGF0aCwgdG9rZW4pO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2lnblJlY292ZXJ5VHJhbnNhY3Rpb24odHhCdWlsZGVyLCBwYXJhbXMsIGRlcml2YXRpb25QYXRoLCBkZXJpdmVkUHVibGljS2V5LCB0cnVlKTtcbiAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVG9rZW5UcmFuc2ZlclRyYW5zYWN0aW9uO1xuICAgIHJldHVybiB7XG4gICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHNjYW5JbmRleDogaWR4LFxuICAgICAgICAgIHJlY292ZXJ5QW1vdW50OiBuZXRBbW91bnQudG9TdHJpbmcoKSxcbiAgICAgICAgICBzZXJpYWxpemVkVHg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgICAgc2lnbmF0dXJlOiBCdWZmZXIuZnJvbSh0eC5zZXJpYWxpemVkU2lnKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICAgICAgY29pbjogdG9rZW4ubmFtZSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBsYXN0U2NhbkluZGV4OiBpZHgsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYnVpbGRVbnNpZ25lZFN3ZWVwVHJhbnNhY3Rpb24oXG4gICAgdHhCdWlsZGVyOiBUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gICAgc2VuZGVyQWRkcmVzczogc3RyaW5nLFxuICAgIGJpdGdvS2V5OiBzdHJpbmcsXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBkZXJpdmF0aW9uUGF0aDogc3RyaW5nLFxuICAgIHRva2VuPzogU3VpQ29pblxuICApOiBQcm9taXNlPE1QQ1N3ZWVwVHhzPiB7XG4gICAgY29uc3QgaXNUb2tlblRyYW5zYWN0aW9uID0gISF0b2tlbjtcbiAgICBjb25zdCB1bnNpZ25lZFRyYW5zYWN0aW9uID0gaXNUb2tlblRyYW5zYWN0aW9uXG4gICAgICA/ICgoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRva2VuVHJhbnNmZXJUcmFuc2FjdGlvbilcbiAgICAgIDogKChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVHJhbnNmZXJUcmFuc2FjdGlvbik7XG4gICAgY29uc3Qgc2VyaWFsaXplZFR4ID0gdW5zaWduZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeEhleCA9IEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZWRUeCwgJ2Jhc2U2NCcpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBwYXJzZWRUeCA9IGF3YWl0IHRoaXMucGFyc2VUcmFuc2FjdGlvbih7IHR4SGV4OiBzZXJpYWxpemVkVHhIZXggfSk7XG4gICAgY29uc3Qgd2FsbGV0Q29pbiA9IGlzVG9rZW5UcmFuc2FjdGlvbiA/IHRva2VuLm5hbWUgOiB0aGlzLmdldENoYWluKCk7XG4gICAgY29uc3Qgb3V0cHV0ID0gcGFyc2VkVHgub3V0cHV0c1swXTtcbiAgICBjb25zdCBpbnB1dHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6IHNlbmRlckFkZHJlc3MsXG4gICAgICAgIHZhbHVlU3RyaW5nOiBvdXRwdXQuYW1vdW50LFxuICAgICAgICB2YWx1ZTogbmV3IEJpZ051bWJlcihvdXRwdXQuYW1vdW50KSxcbiAgICAgIH0sXG4gICAgXTtcbiAgICBjb25zdCBvdXRwdXRzID0gW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiBvdXRwdXQuYWRkcmVzcyxcbiAgICAgICAgdmFsdWVTdHJpbmc6IG91dHB1dC5hbW91bnQsXG4gICAgICAgIGNvaW5OYW1lOiB3YWxsZXRDb2luLFxuICAgICAgfSxcbiAgICBdO1xuICAgIGNvbnN0IHNwZW5kQW1vdW50ID0gb3V0cHV0LmFtb3VudDtcbiAgICBjb25zdCBjb21wbGV0ZWRQYXJzZWRUeCA9IHtcbiAgICAgIGlucHV0czogaW5wdXRzLFxuICAgICAgb3V0cHV0czogb3V0cHV0cyxcbiAgICAgIHNwZW5kQW1vdW50OiBzcGVuZEFtb3VudCxcbiAgICAgIHR5cGU6IGlzVG9rZW5UcmFuc2FjdGlvbiA/IFN1aVRyYW5zYWN0aW9uVHlwZS5Ub2tlblRyYW5zZmVyIDogU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyLFxuICAgIH07XG4gICAgY29uc3QgZmVlID0gcGFyc2VkVHguZmVlO1xuICAgIGNvbnN0IGZlZUluZm8gPSB7IGZlZTogZmVlLnRvTnVtYmVyKCksIGZlZVN0cmluZzogZmVlLnRvU3RyaW5nKCkgfTtcbiAgICBjb25zdCBjb2luU3BlY2lmaWMgPSB7IGNvbW1vbktleWNoYWluOiBiaXRnb0tleSB9O1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBNUENUeCA9IHtcbiAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4SGV4LFxuICAgICAgc2NhbkluZGV4OiBpbmRleCxcbiAgICAgIGNvaW46IHdhbGxldENvaW4sXG4gICAgICBzaWduYWJsZUhleDogdW5zaWduZWRUcmFuc2FjdGlvbi5zaWduYWJsZVBheWxvYWQudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICBwYXJzZWRUeDogY29tcGxldGVkUGFyc2VkVHgsXG4gICAgICBmZWVJbmZvOiBmZWVJbmZvLFxuICAgICAgY29pblNwZWNpZmljOiBjb2luU3BlY2lmaWMsXG4gICAgfTtcbiAgICBjb25zdCB1bnNpZ25lZFR4OiBNUENVbnNpZ25lZFR4ID0geyB1bnNpZ25lZFR4OiB0cmFuc2FjdGlvbiwgc2lnbmF0dXJlU2hhcmVzOiBbXSB9O1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uczogTVBDVW5zaWduZWRUeFtdID0gW3Vuc2lnbmVkVHhdO1xuICAgIGNvbnN0IHR4UmVxdWVzdDogUmVjb3ZlcnlUeFJlcXVlc3QgPSB7XG4gICAgICB0cmFuc2FjdGlvbnM6IHRyYW5zYWN0aW9ucyxcbiAgICAgIHdhbGxldENvaW46IHdhbGxldENvaW4sXG4gICAgfTtcbiAgICByZXR1cm4geyB0eFJlcXVlc3RzOiBbdHhSZXF1ZXN0XSB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzaWduUmVjb3ZlcnlUcmFuc2FjdGlvbihcbiAgICB0eEJ1aWxkZXI6IFRyYW5zYWN0aW9uQnVpbGRlcixcbiAgICBwYXJhbXM6IE1QQ1JlY292ZXJ5T3B0aW9ucyxcbiAgICBkZXJpdmF0aW9uUGF0aDogc3RyaW5nLFxuICAgIGRlcml2ZWRQdWJsaWNLZXk6IHN0cmluZyxcbiAgICBpc1Rva2VuVHJhbnNhY3Rpb246IGJvb2xlYW5cbiAgKSB7XG4gICAgLy8gVE9ETyhCRy01MTA5Mik6IFRoaXMgbG9va3MgbGlrZSBhIGNvbW1vbiBwYXJ0IHdoaWNoIGNhbiBiZSBleHRyYWN0ZWQgb3V0IHRvb1xuICAgIGNvbnN0IHVuc2lnbmVkVHggPSBpc1Rva2VuVHJhbnNhY3Rpb25cbiAgICAgID8gKChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVG9rZW5UcmFuc2ZlclRyYW5zYWN0aW9uKVxuICAgICAgOiAoKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2ZlclRyYW5zYWN0aW9uKTtcbiAgICBpZiAoIXBhcmFtcy51c2VyS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgdXNlcktleScpO1xuICAgIH1cbiAgICBpZiAoIXBhcmFtcy5iYWNrdXBLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiYWNrdXBLZXknKTtcbiAgICB9XG4gICAgaWYgKCFwYXJhbXMud2FsbGV0UGFzc3BocmFzZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHdhbGxldCBwYXNzcGhyYXNlJyk7XG4gICAgfVxuXG4gICAgLy8gQ2xlYW4gdXAgd2hpdGVzcGFjZSBmcm9tIGVudGVyZWQgdmFsdWVzXG4gICAgY29uc3QgdXNlcktleSA9IHBhcmFtcy51c2VyS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgY29uc3QgYmFja3VwS2V5ID0gcGFyYW1zLmJhY2t1cEtleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuXG4gICAgLy8gRGVjcnlwdCBwcml2YXRlIGtleXMgZnJvbSBLZXlDYXJkIHZhbHVlc1xuICAgIGxldCB1c2VyUHJ2OiBzdHJpbmc7XG4gICAgdHJ5IHtcbiAgICAgIHVzZXJQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICBpbnB1dDogdXNlcktleSxcbiAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBkZWNyeXB0aW5nIHVzZXIga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgICAvKiogVE9ETyBCRy01MjQxOSBJbXBsZW1lbnQgQ29kZWMgZm9yIHBhcnNpbmcgKi9cbiAgICBjb25zdCB1c2VyU2lnbmluZ01hdGVyaWFsID0gSlNPTi5wYXJzZSh1c2VyUHJ2KSBhcyBFRERTQU1ldGhvZFR5cGVzLlVzZXJTaWduaW5nTWF0ZXJpYWw7XG5cbiAgICBsZXQgYmFja3VwUHJ2OiBzdHJpbmc7XG4gICAgdHJ5IHtcbiAgICAgIGJhY2t1cFBydiA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgIGlucHV0OiBiYWNrdXBLZXksXG4gICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyBiYWNrdXAga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgICBjb25zdCBiYWNrdXBTaWduaW5nTWF0ZXJpYWwgPSBKU09OLnBhcnNlKGJhY2t1cFBydikgYXMgRUREU0FNZXRob2RUeXBlcy5CYWNrdXBTaWduaW5nTWF0ZXJpYWw7XG4gICAgLyogKioqKioqKioqKioqKioqKioqKioqKiBFTkQgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgICAvLyBhZGQgc2lnbmF0dXJlXG4gICAgY29uc3Qgc2lnbmF0dXJlSGV4ID0gYXdhaXQgRUREU0FNZXRob2RzLmdldFRTU1NpZ25hdHVyZShcbiAgICAgIHVzZXJTaWduaW5nTWF0ZXJpYWwsXG4gICAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwsXG4gICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgIHVuc2lnbmVkVHhcbiAgICApO1xuICAgIHR4QnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IGRlcml2ZWRQdWJsaWNLZXkgfSwgc2lnbmF0dXJlSGV4KTtcbiAgfVxuXG4gIGFzeW5jIGJyb2FkY2FzdFRyYW5zYWN0aW9uKHtcbiAgICB0cmFuc2FjdGlvbnMsXG4gIH06IEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIGNvbnN0IHR4SWRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGNvbnN0IHVybCA9IHRoaXMuZ2V0UHVibGljTm9kZVVybCgpO1xuICAgIGxldCBkaWdlc3QgPSAnJztcbiAgICBpZiAoISF0cmFuc2FjdGlvbnMpIHtcbiAgICAgIGZvciAoY29uc3QgdHhuIG9mIHRyYW5zYWN0aW9ucykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRpZ2VzdCA9IGF3YWl0IHV0aWxzLmV4ZWN1dGVUcmFuc2FjdGlvbkJsb2NrKHVybCwgdHhuLnNlcmlhbGl6ZWRUeCwgW3R4bi5zaWduYXR1cmUhXSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBicm9hZGNhc3QgdHJhbnNhY3Rpb24sIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgICAgICB0eElkcy5wdXNoKGRpZ2VzdCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHR4SWRzIH07XG4gIH1cblxuICAvKiogaW5oZXJpdGVkIGRvYyAqL1xuICBhc3luYyBjcmVhdGVCcm9hZGNhc3RhYmxlU3dlZXBUcmFuc2FjdGlvbihwYXJhbXM6IE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxNUENUeHM+IHtcbiAgICBjb25zdCByZXEgPSBwYXJhbXMuc2lnbmF0dXJlU2hhcmVzO1xuICAgIGNvbnN0IGJyb2FkY2FzdGFibGVUcmFuc2FjdGlvbnM6IE1QQ1R4W10gPSBbXTtcbiAgICBsZXQgbGFzdFNjYW5JbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlcS5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgTVBDID0gYXdhaXQgRUREU0FNZXRob2RzLmdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gcmVxW2ldLnR4UmVxdWVzdC50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeDtcbiAgICAgIGlmICghcmVxW2ldLm92YyB8fCAhcmVxW2ldLm92Y1swXS5lZGRzYVNpZ25hdHVyZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc2lnbmF0dXJlKHMpJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSByZXFbaV0ub3ZjWzBdLmVkZHNhU2lnbmF0dXJlO1xuICAgICAgaWYgKCF0cmFuc2FjdGlvbi5zaWduYWJsZUhleCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgc2lnbmFibGUgaGV4Jyk7XG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20odHJhbnNhY3Rpb24uc2lnbmFibGVIZXghLCAnaGV4Jyk7XG4gICAgICBjb25zdCByZXN1bHQgPSBNUEMudmVyaWZ5KG1lc3NhZ2VCdWZmZXIsIHNpZ25hdHVyZSk7XG4gICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzaWduYXR1cmVIZXggPSBCdWZmZXIuY29uY2F0KFtCdWZmZXIuZnJvbShzaWduYXR1cmUuUiwgJ2hleCcpLCBCdWZmZXIuZnJvbShzaWduYXR1cmUuc2lnbWEsICdoZXgnKV0pO1xuICAgICAgY29uc3Qgc2VyaWFsaXplZFR4QmFzZTY0ID0gQnVmZmVyLmZyb20odHJhbnNhY3Rpb24uc2VyaWFsaXplZFR4LCAnaGV4JykudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gdGhpcy5nZXRCdWlsZGVyKCkuZnJvbShzZXJpYWxpemVkVHhCYXNlNjQpO1xuICAgICAgaWYgKCF0cmFuc2FjdGlvbi5jb2luU3BlY2lmaWM/LmNvbW1vbktleWNoYWluKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBjb21tb24ga2V5Y2hhaW4nKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvbW1vbktleWNoYWluID0gdHJhbnNhY3Rpb24uY29pblNwZWNpZmljIS5jb21tb25LZXljaGFpbiEgYXMgc3RyaW5nO1xuICAgICAgaWYgKCF0cmFuc2FjdGlvbi5kZXJpdmF0aW9uUGF0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgZGVyaXZhdGlvbiBwYXRoJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9IHRyYW5zYWN0aW9uLmRlcml2YXRpb25QYXRoIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IGRlcml2ZWRQdWJsaWNLZXkgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChjb21tb25LZXljaGFpbiwgZGVyaXZhdGlvblBhdGgpLnNsaWNlKDAsIDY0KTtcblxuICAgICAgLy8gYWRkIGNvbWJpbmVkIHNpZ25hdHVyZSBmcm9tIG92Y1xuICAgICAgdHhCdWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogZGVyaXZlZFB1YmxpY0tleSB9LCBzaWduYXR1cmVIZXgpO1xuICAgICAgY29uc3Qgc2lnbmVkVHJhbnNhY3Rpb24gPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRyYW5zZmVyVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkVHggPSBzaWduZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gc2lnbmVkVHJhbnNhY3Rpb24uZXhwbGFpblRyYW5zYWN0aW9uKCkub3V0cHV0QW1vdW50O1xuXG4gICAgICBicm9hZGNhc3RhYmxlVHJhbnNhY3Rpb25zLnB1c2goe1xuICAgICAgICBzZXJpYWxpemVkVHg6IHNlcmlhbGl6ZWRUeCxcbiAgICAgICAgc2NhbkluZGV4OiB0cmFuc2FjdGlvbi5zY2FuSW5kZXgsXG4gICAgICAgIHNpZ25hdHVyZTogQnVmZmVyLmZyb20oc2lnbmVkVHJhbnNhY3Rpb24uc2VyaWFsaXplZFNpZykudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgICByZWNvdmVyeUFtb3VudDogb3V0cHV0QW1vdW50LnRvU3RyaW5nKCksXG4gICAgICB9KTtcblxuICAgICAgaWYgKGkgPT09IHJlcS5sZW5ndGggLSAxICYmIHRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYyEubGFzdFNjYW5JbmRleCkge1xuICAgICAgICBsYXN0U2NhbkluZGV4ID0gdHJhbnNhY3Rpb24uY29pblNwZWNpZmljIS5sYXN0U2NhbkluZGV4IGFzIG51bWJlcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyB0cmFuc2FjdGlvbnM6IGJyb2FkY2FzdGFibGVUcmFuc2FjdGlvbnMsIGxhc3RTY2FuSW5kZXggfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgbmF0aXZlIFNVSSByZWNvdmVyaWVzIG9mIHJlY2VpdmUgYWRkcmVzc2VzIGluIGJhdGNoIHdpdGhvdXQgQml0R28uXG4gICAqIEZ1bmRzIHdpbGwgYmUgcmVjb3ZlcmVkIHRvIGJhc2UgYWRkcmVzcyBmaXJzdC4gWW91IG5lZWQgdG8gaW5pdGlhdGUgYW5vdGhlciBzd2VlcCB0eG4gYWZ0ZXIgdGhhdC5cbiAgICpcbiAgICogQHBhcmFtIHtNUENDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zfSBwYXJhbXMgLSBvcHRpb25zIGZvciBjb25zb2xpZGF0aW9uIHJlY292ZXJ5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhcmFtcy5zdGFydGluZ1NjYW5JbmRleF0gLSByZWNlaXZlIGFkZHJlc3MgaW5kZXggdG8gc3RhcnQgc2Nhbm5pbmcgZnJvbS4gZGVmYXVsdCB0byAxIChpbmNsdXNpdmUpLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3BhcmFtcy5lbmRpbmdTY2FuSW5kZXhdIC0gcmVjZWl2ZSBhZGRyZXNzIGluZGV4IHRvIGVuZCBzY2FubmluZyBhdC4gZGVmYXVsdCB0byBzdGFydGluZ1NjYW5JbmRleCArIDIwIChleGNsdXNpdmUpLlxuICAgKi9cbiAgYXN5bmMgcmVjb3ZlckNvbnNvbGlkYXRpb25zKHBhcmFtczogTVBDQ29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8TVBDVHhzIHwgTVBDU3dlZXBUeHM+IHtcbiAgICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSAhcGFyYW1zLnVzZXJLZXkgJiYgIXBhcmFtcy5iYWNrdXBLZXkgJiYgIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlO1xuICAgIGNvbnN0IHN0YXJ0SWR4ID0gdXRpbHMudmFsaWRhdGVOb25OZWdhdGl2ZU51bWJlcihcbiAgICAgIDEsXG4gICAgICAnSW52YWxpZCBzdGFydGluZyBpbmRleCB0byBzY2FuIGZvciBhZGRyZXNzZXMnLFxuICAgICAgcGFyYW1zLnN0YXJ0aW5nU2NhbkluZGV4XG4gICAgKTtcbiAgICBjb25zdCBlbmRJZHggPSB1dGlscy52YWxpZGF0ZU5vbk5lZ2F0aXZlTnVtYmVyKFxuICAgICAgc3RhcnRJZHggKyBERUZBVUxUX1NDQU5fRkFDVE9SLFxuICAgICAgJ0ludmFsaWQgZW5kaW5nIGluZGV4IHRvIHNjYW4gZm9yIGFkZHJlc3NlcycsXG4gICAgICBwYXJhbXMuZW5kaW5nU2NhbkluZGV4XG4gICAgKTtcblxuICAgIGlmIChzdGFydElkeCA8IDEgfHwgZW5kSWR4IDw9IHN0YXJ0SWR4IHx8IGVuZElkeCAtIHN0YXJ0SWR4ID4gMTAgKiBERUZBVUxUX1NDQU5fRkFDVE9SKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIHN0YXJ0aW5nIG9yIGVuZGluZyBpbmRleCB0byBzY2FuIGZvciBhZGRyZXNzZXMuIHN0YXJ0aW5nU2NhbkluZGV4OiAke3N0YXJ0SWR4fSwgZW5kaW5nU2NhbkluZGV4OiAke2VuZElkeH0uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBiaXRnb0tleSA9IHBhcmFtcy5iaXRnb0tleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSAocGFyYW1zLnNlZWQgPyBnZXREZXJpdmF0aW9uUGF0aChwYXJhbXMuc2VlZCkgOiAnbScpICsgJy8wJztcbiAgICBjb25zdCBkZXJpdmVkUHVibGljS2V5ID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGRlcml2YXRpb25QYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgY29uc3QgYmFzZUFkZHJlc3MgPSB0aGlzLmdldEFkZHJlc3NGcm9tUHVibGljS2V5KGRlcml2ZWRQdWJsaWNLZXkpO1xuXG4gICAgY29uc3QgY29uc29saWRhdGlvblRyYW5zYWN0aW9uczogYW55W10gPSBbXTtcbiAgICBsZXQgbGFzdFNjYW5JbmRleCA9IHN0YXJ0SWR4O1xuICAgIGZvciAobGV0IGlkeCA9IHN0YXJ0SWR4OyBpZHggPCBlbmRJZHg7IGlkeCsrKSB7XG4gICAgICBjb25zdCByZWNvdmVyUGFyYW1zID0ge1xuICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogcGFyYW1zLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgc2VlZDogcGFyYW1zLnNlZWQsXG4gICAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGJhc2VBZGRyZXNzLFxuICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogaWR4LFxuICAgICAgICBzY2FuOiAxLFxuICAgICAgfTtcblxuICAgICAgbGV0IHJlY292ZXJ5VHJhbnNhY3Rpb246IE1QQ1R4cyB8IE1QQ1N3ZWVwVHhzO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVjb3ZlcnlUcmFuc2FjdGlvbiA9IGF3YWl0IHRoaXMucmVjb3ZlcihyZWNvdmVyUGFyYW1zKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUubWVzc2FnZS5zdGFydHNXaXRoKCdEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIHN1ZmZpY2llbnQgZnVuZHMgdG8gcmVjb3Zlci4nKSkge1xuICAgICAgICAgIGxhc3RTY2FuSW5kZXggPSBpZHg7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLnB1c2goKHJlY292ZXJ5VHJhbnNhY3Rpb24gYXMgTVBDU3dlZXBUeHMpLnR4UmVxdWVzdHNbMF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5wdXNoKChyZWNvdmVyeVRyYW5zYWN0aW9uIGFzIE1QQ1R4cykudHJhbnNhY3Rpb25zWzBdKTtcbiAgICAgIH1cbiAgICAgIGxhc3RTY2FuSW5kZXggPSBpZHg7XG4gICAgfVxuXG4gICAgaWYgKGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIHN1ZmZpY2llbnQgZnVuZHMgdG8gcmVjb3Zlci4gUGxlYXNlIHN0YXJ0IHRoZSBuZXh0IHNjYW4gYXQgYWRkcmVzcyBpbmRleCAke1xuICAgICAgICAgIGxhc3RTY2FuSW5kZXggKyAxXG4gICAgICAgIH0uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICAvLyBsYXN0U2NhbkluZGV4IHdpbGwgYmUgdXNlZCB0byBpbmZvcm0gdXNlciB0aGUgbGFzdCBhZGRyZXNzIGluZGV4IHNjYW5uZWQgZm9yIGF2YWlsYWJsZSBmdW5kcyAoc28gdGhleSBjYW5cbiAgICAgIC8vIGFwcHJvcHJpYXRlbHkgYWRqdXN0IHRoZSBzY2FuIHJhbmdlIG9uIHRoZSBuZXh0IGl0ZXJhdGlvbiBvZiBjb25zb2xpZGF0aW9uIHJlY292ZXJpZXMpLiBJbiB0aGUgY2FzZSBvZiB1bnNpZ25lZFxuICAgICAgLy8gc3dlZXAgY29uc29saWRhdGlvbnMsIHRoaXMgbGFzdFNjYW5JbmRleCB3aWxsIGJlIHByb3ZpZGVkIGluIHRoZSBjb2luU3BlY2lmaWMgb2YgdGhlIGxhc3QgdHhuIG1hZGUuXG4gICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zW1xuICAgICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLmxlbmd0aCAtIDFcbiAgICAgIF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguY29pblNwZWNpZmljLmxhc3RTY2FuSW5kZXggPSBsYXN0U2NhbkluZGV4O1xuICAgICAgcmV0dXJuIHsgdHhSZXF1ZXN0czogY29uc29saWRhdGlvblRyYW5zYWN0aW9ucyB9O1xuICAgIH1cblxuICAgIHJldHVybiB7IHRyYW5zYWN0aW9uczogY29uc29saWRhdGlvblRyYW5zYWN0aW9ucywgbGFzdFNjYW5JbmRleCB9O1xuICB9XG5cbiAgLyoqIGluaGVyaXRlZCBkb2MgKi9cbiAgc2V0Q29pblNwZWNpZmljRmllbGRzSW5JbnRlbnQoaW50ZW50OiBQb3B1bGF0ZWRJbnRlbnQsIHBhcmFtczogUHJlYnVpbGRUcmFuc2FjdGlvbldpdGhJbnRlbnRPcHRpb25zKTogdm9pZCB7XG4gICAgaW50ZW50LnVuc3BlbnRzID0gcGFyYW1zLnVuc3BlbnRzO1xuICB9XG5cbiAgLyoqIGluaGVyaXRlZCBkb2MgKi9cbiAgYXVkaXREZWNyeXB0ZWRLZXkoeyBwdWJsaWNLZXksIHBydiwgbXVsdGlTaWdUeXBlIH06IEF1ZGl0RGVjcnlwdGVkS2V5UGFyYW1zKSB7XG4gICAgaWYgKG11bHRpU2lnVHlwZSAhPT0gJ3RzcycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgbXVsdGlTaWdUeXBlJyk7XG4gICAgfVxuXG4gICAgYXVkaXRFZGRzYVByaXZhdGVLZXkocHJ2LCBwdWJsaWNLZXkgPz8gJycpO1xuICB9XG59XG4iXX0=

Выполнить команду


Для локальной разработки. Не используйте в интернете!