PHP WebShell

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

Просмотр файла: transactionBuilder.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.TransactionBuilder = void 0;
const statics_1 = require("@bitgo/statics");
const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const ethUtil = __importStar(require("ethereumjs-util"));
const tx_1 = require("@ethereumjs/tx");
const sdk_core_1 = require("@bitgo/sdk-core");
const keyPair_1 = require("./keyPair");
const iface_1 = require("./iface");
const utils_1 = require("./utils");
const walletUtil_1 = require("./walletUtil");
const transaction_1 = require("./transaction");
const DEFAULT_M = 3;
/**
 * EthereumLike transaction builder.
 */
class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
    /**
     * Public constructor.
     *
     * @param _coinConfig
     */
    constructor(_coinConfig) {
        super(_coinConfig);
        this._common = (0, utils_1.getCommon)(this._coinConfig.network);
        this._type = sdk_core_1.TransactionType.Send;
        this._counter = 0;
        this._value = '0';
        this._walletOwnerAddresses = [];
        this._forwarderVersion = 0;
        this._walletVersion = 0;
        this.transaction = new transaction_1.Transaction(this._coinConfig, this._common);
        this._walletSimpleByteCode = '';
    }
    /** @inheritdoc */
    async buildImplementation() {
        const transactionData = this.getTransactionData();
        if (this._txSignature) {
            Object.assign(transactionData, this._txSignature);
        }
        this.transaction.setTransactionType(this._type);
        transactionData.from = this._sourceKeyPair ? this._sourceKeyPair.getAddress() : undefined;
        this.transaction.setTransactionData(transactionData, this._transfer ? this._transfer.getIsFirstSigner() : undefined);
        // Build and sign a new transaction based on the latest changes
        if (this._sourceKeyPair && this._sourceKeyPair.getKeys().prv) {
            await this.transaction.sign(this._sourceKeyPair);
        }
        return this.transaction;
    }
    getTransactionData() {
        switch (this._type) {
            case sdk_core_1.TransactionType.WalletInitialization:
                return this.buildWalletInitializationTransaction(this._walletVersion);
            case sdk_core_1.TransactionType.RecoveryWalletDeployment:
                return this.buildBase(this._data);
            case sdk_core_1.TransactionType.Send:
            case sdk_core_1.TransactionType.SendERC721:
            case sdk_core_1.TransactionType.SendERC1155:
                return this.buildSendTransaction();
            case sdk_core_1.TransactionType.AddressInitialization:
                return this.buildAddressInitializationTransaction();
            case sdk_core_1.TransactionType.FlushTokens:
                return this.buildFlushTokensTransaction();
            case sdk_core_1.TransactionType.FlushCoins:
                return this.buildFlushCoinsTransaction();
            case sdk_core_1.TransactionType.SingleSigSend:
                return this.buildBase('0x');
            case sdk_core_1.TransactionType.ContractCall:
                return this.buildGenericContractCallTransaction();
            default:
                throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
        }
    }
    /** @inheritdoc */
    fromImplementation(rawTransaction, isFirstSigner) {
        let tx;
        if (/^0x?[0-9a-f]{1,}$/.test(rawTransaction.toLowerCase())) {
            tx = transaction_1.Transaction.fromSerialized(this._coinConfig, this._common, rawTransaction, isFirstSigner);
            this.loadBuilderInput(tx.toJson(), isFirstSigner);
        }
        else {
            const txData = JSON.parse(rawTransaction);
            tx = new transaction_1.Transaction(this._coinConfig, txData);
        }
        return tx;
    }
    /**
     * Load the builder data using the deserialized transaction
     *
     * @param {TxData} transactionJson the deserialized transaction json
     * @param {boolean} isFirstSigner if the transaction is being signed by the first signer
     */
    loadBuilderInput(transactionJson, isFirstSigner) {
        const decodedType = (0, utils_1.classifyTransaction)(transactionJson.data);
        this.type(decodedType);
        this.counter(transactionJson.nonce);
        this.value(transactionJson.value);
        if (transactionJson._type === iface_1.ETHTransactionType.LEGACY) {
            this.fee({
                fee: transactionJson.gasPrice,
                gasPrice: transactionJson.gasPrice,
                gasLimit: transactionJson.gasLimit,
            });
        }
        else {
            this.fee({
                gasLimit: transactionJson.gasLimit,
                fee: transactionJson.maxFeePerGas,
                eip1559: {
                    maxFeePerGas: transactionJson.maxFeePerGas,
                    maxPriorityFeePerGas: transactionJson.maxPriorityFeePerGas,
                },
            });
        }
        if ((0, utils_1.hasSignature)(transactionJson)) {
            this._txSignature = { v: transactionJson.v, r: transactionJson.r, s: transactionJson.s };
        }
        this.setTransactionTypeFields(decodedType, transactionJson, isFirstSigner);
    }
    setTransactionTypeFields(decodedType, transactionJson, isFirstSigner) {
        switch (decodedType) {
            case sdk_core_1.TransactionType.WalletInitialization:
                const { owners, salt } = (0, utils_1.decodeWalletCreationData)(transactionJson.data);
                owners.forEach((element) => {
                    this.owner(element);
                });
                if (salt) {
                    this.salt(salt);
                    this.walletVersion(1);
                    this.setContract(transactionJson.to);
                }
                break;
            case sdk_core_1.TransactionType.RecoveryWalletDeployment:
                this.data(transactionJson.data);
                break;
            case sdk_core_1.TransactionType.FlushTokens:
                this.setContract(transactionJson.to);
                const { forwarderAddress, tokenAddress, forwarderVersion } = (0, utils_1.decodeFlushTokensData)(transactionJson.data, transactionJson.to);
                if (forwarderVersion === 4) {
                    this.forwarderVersion(4);
                }
                this.forwarderAddress(forwarderAddress);
                this.tokenAddress(tokenAddress);
                break;
            case sdk_core_1.TransactionType.FlushCoins:
                this.setContract(transactionJson.to);
                break;
            case sdk_core_1.TransactionType.Send:
            case sdk_core_1.TransactionType.SendERC1155:
            case sdk_core_1.TransactionType.SendERC721:
                this.setContract(transactionJson.to);
                this._transfer = this.transfer(transactionJson.data, isFirstSigner);
                break;
            case sdk_core_1.TransactionType.AddressInitialization:
                this.setContract(transactionJson.to);
                const { baseAddress, addressCreationSalt, feeAddress } = (0, utils_1.decodeForwarderCreationData)(transactionJson.data);
                if (baseAddress && addressCreationSalt) {
                    this.baseAddress(baseAddress);
                    this.salt(addressCreationSalt);
                    if (feeAddress) {
                        this.feeAddress(feeAddress);
                        this.forwarderVersion(4);
                    }
                    else {
                        this.forwarderVersion(1);
                    }
                    const forwarderImplementationAddress = this._coinConfig.network
                        .forwarderImplementationAddress;
                    if (forwarderImplementationAddress) {
                        this.initCode(forwarderImplementationAddress);
                    }
                }
                break;
            case sdk_core_1.TransactionType.SingleSigSend:
                this.setContract(transactionJson.to);
                break;
            case sdk_core_1.TransactionType.ContractCall:
                this.setContract(transactionJson.to);
                this.data(transactionJson.data);
                break;
            default:
                throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
            // TODO: Add other cases of deserialization
        }
    }
    /** @inheritdoc */
    signImplementation(key) {
        const signer = new keyPair_1.KeyPair({ prv: key.key });
        if (this._type === sdk_core_1.TransactionType.WalletInitialization && this._walletOwnerAddresses.length === 0) {
            throw new sdk_core_1.SigningError('Cannot sign an wallet initialization transaction without owners');
        }
        if (this._sourceKeyPair) {
            throw new sdk_core_1.SigningError('Cannot sign multiple times a non send-type transaction');
        }
        // Signing the transaction is an async operation, so save the source and leave the actual
        // signing for the build step
        this._sourceKeyPair = signer;
        return this.transaction;
    }
    /** @inheritdoc */
    validateAddress(address) {
        if (!(0, utils_1.isValidEthAddress)(address.address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address ' + address.address);
        }
    }
    /** @inheritdoc */
    validateKey(key) {
        if (!((0, sdk_core_1.isValidXprv)(key.key) || (0, sdk_core_1.isValidPrv)(key.key))) {
            throw new sdk_core_1.BuildTransactionError('Invalid key');
        }
    }
    /**
     * Validate the raw transaction is either a JSON or
     * a hex encoded transaction
     *
     * @param {any} rawTransaction The raw transaction to be validated
     */
    validateRawTransaction(rawTransaction) {
        if (!rawTransaction) {
            throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
        }
        if (typeof rawTransaction === 'string') {
            if (/^0x?[0-9a-f]{1,}$/.test(rawTransaction.toLowerCase())) {
                const txBytes = ethUtil.toBuffer(ethUtil.addHexPrefix(rawTransaction.toLowerCase()));
                if (!this.isEip1559Txn(txBytes) && !this.isRLPDecodable(txBytes)) {
                    throw new sdk_core_1.ParseTransactionError('There was error in decoding the hex string');
                }
            }
            else {
                try {
                    JSON.parse(rawTransaction);
                }
                catch (e) {
                    throw new sdk_core_1.ParseTransactionError('There was error in parsing the JSON string');
                }
            }
        }
        else {
            throw new sdk_core_1.InvalidTransactionError('Transaction is not a hex string or stringified json');
        }
    }
    isEip1559Txn(txn) {
        try {
            tx_1.FeeMarketEIP1559Transaction.fromSerializedTx(txn);
            return true;
        }
        catch (_) {
            return false;
        }
    }
    isRLPDecodable(bytes) {
        try {
            ethUtil.rlp.decode(bytes);
            return true;
        }
        catch (_) {
            return false;
        }
    }
    validateBaseTransactionFields() {
        if (this._fee === undefined || (!this._fee.fee && !this._fee.gasPrice && !this._fee.eip1559)) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing fee');
        }
        if (this._common === undefined) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: network common');
        }
        if (this._counter === undefined) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing address counter');
        }
    }
    /** @inheritdoc */
    validateTransaction(transaction) {
        this.validateBaseTransactionFields();
        switch (this._type) {
            case sdk_core_1.TransactionType.WalletInitialization:
                this.validateWalletInitializationFields();
                break;
            case sdk_core_1.TransactionType.RecoveryWalletDeployment:
                this.validateDataField();
                break;
            case sdk_core_1.TransactionType.Send:
            case sdk_core_1.TransactionType.SendERC721:
            case sdk_core_1.TransactionType.SendERC1155:
                this.validateContractAddress();
                break;
            case sdk_core_1.TransactionType.AddressInitialization:
                this.validateContractAddress();
                break;
            case sdk_core_1.TransactionType.FlushCoins:
                this.validateContractAddress();
                break;
            case sdk_core_1.TransactionType.FlushTokens:
                this.validateContractAddress();
                this.validateForwarderAddress();
                this.validateTokenAddress();
                break;
            case sdk_core_1.TransactionType.SingleSigSend:
                // for single sig sends, the contract address is actually the recipient
                this.validateContractAddress();
                break;
            case sdk_core_1.TransactionType.StakingLock:
            case sdk_core_1.TransactionType.StakingUnlock:
            case sdk_core_1.TransactionType.StakingVote:
            case sdk_core_1.TransactionType.StakingUnvote:
            case sdk_core_1.TransactionType.StakingActivate:
            case sdk_core_1.TransactionType.StakingWithdraw:
                break;
            case sdk_core_1.TransactionType.ContractCall:
                this.validateContractAddress();
                this.validateDataField();
                break;
            default:
                throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
        }
    }
    /**
     * Check wallet owner addresses for wallet initialization transactions are valid or throw.
     */
    validateWalletInitializationFields() {
        if (this._walletOwnerAddresses === undefined) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing wallet owners');
        }
        if (this._walletOwnerAddresses.length !== 3) {
            throw new sdk_core_1.BuildTransactionError(`Invalid transaction: wrong number of owners -- required: 3, found: ${this._walletOwnerAddresses.length}`);
        }
    }
    /**
     * Check if a token address for the tx was defined or throw.
     */
    validateTokenAddress() {
        if (this._tokenAddress === undefined) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing token address');
        }
    }
    /**
     * Check if a forwarder address for the tx was defined or throw.
     */
    validateForwarderAddress() {
        if (this._forwarderAddress === undefined) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing forwarder address');
        }
    }
    /**
     * Check if a contract address for the wallet was defined or throw.
     */
    validateContractAddress() {
        if (this._contractAddress === undefined) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing contract address');
        }
    }
    /**
     * Checks if a contract call data field was defined or throws otherwise
     */
    validateDataField() {
        if (!this._data) {
            throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing contract call data field');
        }
    }
    setContract(address) {
        if (address === undefined) {
            throw new sdk_core_1.BuildTransactionError('Undefined recipient address');
        }
        this.contract(address);
    }
    validateValue(value) {
        if (value.isLessThan(0)) {
            throw new sdk_core_1.BuildTransactionError('Value cannot be below less than zero');
        }
        // TODO: validate the amount is not bigger than the max amount in each Eth family coin
    }
    // region Common builder methods
    /**
     * The type of transaction being built.
     *
     * @param {TransactionType} type
     */
    type(type) {
        this._type = type;
    }
    /**
     * Set the transaction fees. Low fees may get a transaction rejected or never picked up by bakers.
     *
     * @param {Fee} fee Baker fees. May also include the maximum gas to pay
     */
    fee(fee) {
        this.validateValue(new bignumber_js_1.default(fee.fee));
        if (fee.gasLimit) {
            this.validateValue(new bignumber_js_1.default(fee.gasLimit));
        }
        if (fee.eip1559) {
            this.validateValue(new bignumber_js_1.default(fee.eip1559.maxFeePerGas));
            this.validateValue(new bignumber_js_1.default(fee.eip1559.maxPriorityFeePerGas));
        }
        if (fee.gasPrice) {
            this.validateValue(new bignumber_js_1.default(fee.gasPrice));
        }
        this._fee = fee;
    }
    /**
     * Set the transaction counter to prevent submitting repeated transactions.
     *
     * @param {number} counter The counter to use
     */
    counter(counter) {
        if (counter < 0) {
            throw new sdk_core_1.BuildTransactionError(`Invalid counter: ${counter}`);
        }
        this._counter = counter;
    }
    /**
     * The value to send along with this transaction. 0 by default
     *
     * @param {string} value The value to send along with this transaction
     */
    value(value) {
        this._value = value;
    }
    // set args that are required for all types of eth transactions
    buildBase(data) {
        const baseParams = {
            gasLimit: this._fee.gasLimit,
            nonce: this._counter,
            data: data,
            chainId: this._common.chainIdBN().toString(),
            value: this._value,
            to: this._contractAddress,
        };
        if (this._fee.eip1559) {
            return {
                ...baseParams,
                _type: iface_1.ETHTransactionType.EIP1559,
                maxFeePerGas: this._fee.eip1559.maxFeePerGas,
                maxPriorityFeePerGas: this._fee.eip1559.maxPriorityFeePerGas,
            };
        }
        else {
            return {
                ...baseParams,
                _type: iface_1.ETHTransactionType.LEGACY,
                gasPrice: this._fee?.gasPrice ?? this._fee.fee,
                v: this.getFinalV(),
            };
        }
    }
    // endregion
    // region WalletInitialization builder methods
    /**
     * Set one of the owners of the multisig wallet.
     *
     * @param {string} address An Ethereum address
     */
    owner(address) {
        if (this._type !== sdk_core_1.TransactionType.WalletInitialization) {
            throw new sdk_core_1.BuildTransactionError('Multisig wallet owner can only be set for initialization transactions');
        }
        if (this._walletOwnerAddresses.length >= DEFAULT_M) {
            throw new sdk_core_1.BuildTransactionError('A maximum of ' + DEFAULT_M + ' owners can be set for a multisig wallet');
        }
        if (!(0, utils_1.isValidEthAddress)(address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
        }
        if (this._walletOwnerAddresses.includes(address)) {
            throw new sdk_core_1.BuildTransactionError('Repeated owner address: ' + address);
        }
        this._walletOwnerAddresses.push(address);
    }
    /**
     * Build a transaction for a generic multisig contract.
     *
     * @returns {TxData} The Ethereum transaction data
     */
    buildWalletInitializationTransaction(walletVersion) {
        const walletInitData = walletVersion === walletUtil_1.defaultWalletVersion
            ? this.getContractData(this._walletOwnerAddresses)
            : (0, utils_1.getV1WalletInitializationData)(this._walletOwnerAddresses, this._salt);
        return this.buildBase(walletInitData);
    }
    /**
     * Returns the smart contract encoded data
     *
     * @param {string[]} addresses - the contract signers
     * @returns {string} - the smart contract encoded data
     */
    getContractData(addresses) {
        const params = [addresses];
        const resultEncodedParameters = ethereumjs_abi_1.default.rawEncode(walletUtil_1.walletSimpleConstructor, params)
            .toString('hex')
            .replace('0x', '');
        return this._walletSimpleByteCode + resultEncodedParameters;
    }
    // endregion
    // region Send builder methods
    contract(address) {
        if (!(0, utils_1.isValidEthAddress)(address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
        }
        this._contractAddress = address;
    }
    /**
     * Returns the serialized sendMultiSig contract method data
     *
     * @returns {string} serialized sendMultiSig data
     */
    getSendData() {
        if (!this._transfer) {
            throw new sdk_core_1.BuildTransactionError('Missing transfer information');
        }
        const chainId = this._common.chainIdBN().toString();
        this._transfer.walletVersion(this._walletVersion);
        // This change is made to support new contracts with different encoding type
        return this._transfer.signAndBuild(chainId, this.coinUsesNonPackedEncodingForTxData());
    }
    /**
     * Decide if the coin uses non-packed encoding for tx data
     *
     * @returns {boolean} true if the coin uses non-packed encoding for tx data
     */
    coinUsesNonPackedEncodingForTxData() {
        return (this._walletVersion === 4 || this._coinConfig.features.includes(statics_1.CoinFeature.USES_NON_PACKED_ENCODING_FOR_TXDATA));
    }
    buildSendTransaction() {
        const sendData = this.getSendData();
        const tx = this.buildBase(sendData);
        tx.to = this._contractAddress;
        return tx;
    }
    // endregion
    // region AddressInitialization builder methods
    /**
     * Set the contract transaction nonce to calculate the forwarder address.
     *
     * @param {number} contractCounter The counter to use
     */
    contractCounter(contractCounter) {
        if (contractCounter < 0) {
            throw new sdk_core_1.BuildTransactionError(`Invalid contract counter: ${contractCounter}`);
        }
        this._contractCounter = contractCounter;
    }
    /**
     * Build a transaction to create a forwarder.
     *
     * @returns {TxData} The Ethereum transaction data
     */
    buildAddressInitializationTransaction() {
        const addressInitData = (0, utils_1.getAddressInitDataAllForwarderVersions)(this._forwarderVersion, this._baseAddress, this._salt, this._feeAddress);
        const tx = this.buildBase(addressInitData);
        tx.to = this._contractAddress;
        if (this._contractCounter) {
            tx.deployedAddress = (0, utils_1.calculateForwarderAddress)(this._contractAddress, this._contractCounter);
        }
        if (this._salt && this._initCode) {
            const saltBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(this._salt), 32);
            const { createForwarderParams, createForwarderTypes } = (0, utils_1.getCreateForwarderParamsAndTypes)(this._baseAddress, saltBuffer, this._feeAddress);
            // Hash the wallet base address and fee address if present with the given salt, so the address directly relies on the base address and fee address
            const calculationSalt = ethUtil.bufferToHex(ethereumjs_abi_1.default.soliditySHA3(createForwarderTypes, createForwarderParams));
            tx.deployedAddress = (0, utils_1.calculateForwarderV1Address)(this._contractAddress, calculationSalt, this._initCode);
        }
        return tx;
    }
    // endregion
    // region flush methods
    /**
     * Set the forwarder address to flush
     *
     * @param {string} address The address to flush
     */
    forwarderAddress(address) {
        if (!(0, utils_1.isValidEthAddress)(address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
        }
        this._forwarderAddress = address;
    }
    /**
     * Set the address of the ERC20 token contract that we are flushing tokens for
     *
     * @param {string} address the contract address of the token to flush
     */
    tokenAddress(address) {
        if (!(0, utils_1.isValidEthAddress)(address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
        }
        this._tokenAddress = address;
    }
    /**
     * Build a transaction to flush tokens from a forwarder.
     *
     * @returns {TxData} The Ethereum transaction data
     */
    buildFlushTokensTransaction() {
        if (this._forwarderVersion >= 4 && this._contractAddress !== this._forwarderAddress) {
            throw new sdk_core_1.BuildTransactionError('Invalid contract address: ' + this._contractAddress);
        }
        return this.buildBase((0, utils_1.flushTokensData)(this._forwarderAddress, this._tokenAddress, this._forwarderVersion));
    }
    /**
     * Build a transaction to flush tokens from a forwarder.
     *
     * @returns {TxData} The Ethereum transaction data
     */
    buildFlushCoinsTransaction() {
        return this.buildBase((0, utils_1.flushCoinsData)());
    }
    // endregion
    // region generic contract call
    data(encodedCall) {
        const supportedTransactionTypes = [sdk_core_1.TransactionType.ContractCall, sdk_core_1.TransactionType.RecoveryWalletDeployment];
        if (!supportedTransactionTypes.includes(this._type)) {
            throw new sdk_core_1.BuildTransactionError('data can only be set for contract call transaction types');
        }
        this._data = encodedCall;
    }
    buildGenericContractCallTransaction() {
        return this.buildBase(this._data);
    }
    // endregion
    /** @inheritdoc */
    get transaction() {
        return this._transaction;
    }
    /** @inheritdoc */
    set transaction(transaction) {
        this._transaction = transaction;
    }
    /**
     * Get the final v value. Final v is described in EIP-155.
     *
     * @protected for internal use when the enableFinalVField flag is true.
     */
    getFinalV() {
        return ethUtil.addHexPrefix(this._common.chainIdBN().muln(2).addn(35).toString(16));
    }
    /**
     * Set the forwarder version for address to be initialized
     *
     * @param {number} version forwarder version
     */
    forwarderVersion(version) {
        if (version < 0 || version > 4 || version === 3) {
            throw new sdk_core_1.BuildTransactionError(`Invalid forwarder version: ${version}`);
        }
        this._forwarderVersion = version;
    }
    /**
     * Set the salt to create the address using create2
     *
     * @param {string} salt The salt to create the address using create2, hex string
     */
    salt(salt) {
        this._salt = salt;
    }
    /**
     * Take the implementation address for the proxy contract, and get the binary initcode for the associated proxy
     *
     * @param {string} implementationAddress The address of the implementation contract
     */
    initCode(implementationAddress) {
        if (!(0, utils_1.isValidEthAddress)(implementationAddress)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + implementationAddress);
        }
        this._initCode = (0, utils_1.getProxyInitcode)(implementationAddress);
    }
    /**
     * Set the wallet version for wallet to be initialized
     *
     * @param {number} version wallet version
     */
    walletVersion(version) {
        if (version < 0 || version > 4 || version === 3) {
            throw new sdk_core_1.BuildTransactionError(`Invalid wallet version: ${version}`);
        }
        this._walletVersion = version;
    }
    /**
     * Set the base address of the wallet
     *
     * @param {string} address The wallet contract address
     */
    baseAddress(address) {
        if (!(0, utils_1.isValidEthAddress)(address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
        }
        this._baseAddress = address;
    }
    /**
     * Set the fee address of the wallet
     *
     * @param {string} address The fee address of the wallet
     */
    feeAddress(address) {
        if (!(0, utils_1.isValidEthAddress)(address)) {
            throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
        }
        this._feeAddress = address;
    }
    /**
     * Get the wallet version for wallet
     */
    getWalletVersion() {
        return this._walletVersion;
    }
}
exports.TransactionBuilder = TransactionBuilder;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNENBQXNGO0FBRXRGLG9FQUF5QztBQUN6QyxnRUFBcUM7QUFDckMseURBQTJDO0FBQzNDLHVDQUE2RDtBQUU3RCw4Q0FZeUI7QUFFekIsdUNBQW9DO0FBQ3BDLG1DQUEwRTtBQUMxRSxtQ0FnQmlCO0FBQ2pCLDZDQUE2RTtBQUc3RSwrQ0FBNEM7QUFHNUMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0FBRXBCOztHQUVHO0FBQ0gsTUFBc0Isa0JBQW1CLFNBQVEsaUNBQXNCO0lBd0NyRTs7OztPQUlHO0lBQ0gsWUFBWSxXQUFpQztRQUMzQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFBLGlCQUFTLEVBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUEwQixDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLEtBQUssR0FBRywwQkFBZSxDQUFDLElBQUksQ0FBQztRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQztRQUNsQixJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztJQUNsQyxDQUFDO0lB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QUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksZ0NBQXFCLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsT0FBTyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsVUFBVSxDQUFDLE9BQWU7UUFDeEIsSUFBSSxDQUFDLElBQUEseUJBQWlCLEVBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksZ0NBQXFCLENBQUMsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7T0FFRztJQUNJLGdCQUFnQjtRQUNyQixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztDQUNGO0FBdnpCRCxnREF1ekJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzZUNvaW4gYXMgQ29pbkNvbmZpZywgRXRoZXJldW1OZXR3b3JrLCBDb2luRmVhdHVyZSB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCBFdGhlcmV1bUNvbW1vbiBmcm9tICdAZXRoZXJldW1qcy9jb21tb24nO1xuaW1wb3J0IEV0aGVyZXVtQWJpIGZyb20gJ2V0aGVyZXVtanMtYWJpJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCAqIGFzIGV0aFV0aWwgZnJvbSAnZXRoZXJldW1qcy11dGlsJztcbmltcG9ydCB7IEZlZU1hcmtldEVJUDE1NTlUcmFuc2FjdGlvbiB9IGZyb20gJ0BldGhlcmV1bWpzL3R4JztcblxuaW1wb3J0IHtcbiAgQmFzZUFkZHJlc3MsXG4gIEJhc2VLZXksXG4gIEJhc2VUcmFuc2FjdGlvbixcbiAgQmFzZVRyYW5zYWN0aW9uQnVpbGRlcixcbiAgQnVpbGRUcmFuc2FjdGlvbkVycm9yLFxuICBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcixcbiAgaXNWYWxpZFBydixcbiAgaXNWYWxpZFhwcnYsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbiAgU2lnbmluZ0Vycm9yLFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5cbmltcG9ydCB7IEtleVBhaXIgfSBmcm9tICcuL2tleVBhaXInO1xuaW1wb3J0IHsgRVRIVHJhbnNhY3Rpb25UeXBlLCBGZWUsIFNpZ25hdHVyZVBhcnRzLCBUeERhdGEgfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCB7XG4gIGNhbGN1bGF0ZUZvcndhcmRlckFkZHJlc3MsXG4gIGNhbGN1bGF0ZUZvcndhcmRlclYxQWRkcmVzcyxcbiAgY2xhc3NpZnlUcmFuc2FjdGlvbixcbiAgZGVjb2RlRm9yd2FyZGVyQ3JlYXRpb25EYXRhLFxuICBkZWNvZGVGbHVzaFRva2Vuc0RhdGEsXG4gIGRlY29kZVdhbGxldENyZWF0aW9uRGF0YSxcbiAgZmx1c2hDb2luc0RhdGEsXG4gIGZsdXNoVG9rZW5zRGF0YSxcbiAgZ2V0QWRkcmVzc0luaXREYXRhQWxsRm9yd2FyZGVyVmVyc2lvbnMsXG4gIGdldENvbW1vbixcbiAgZ2V0UHJveHlJbml0Y29kZSxcbiAgaGFzU2lnbmF0dXJlLFxuICBpc1ZhbGlkRXRoQWRkcmVzcyxcbiAgZ2V0VjFXYWxsZXRJbml0aWFsaXphdGlvbkRhdGEsXG4gIGdldENyZWF0ZUZvcndhcmRlclBhcmFtc0FuZFR5cGVzLFxufSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IGRlZmF1bHRXYWxsZXRWZXJzaW9uLCB3YWxsZXRTaW1wbGVDb25zdHJ1Y3RvciB9IGZyb20gJy4vd2FsbGV0VXRpbCc7XG5pbXBvcnQgeyBFUkMxMTU1VHJhbnNmZXJCdWlsZGVyIH0gZnJvbSAnLi90cmFuc2ZlckJ1aWxkZXJzL3RyYW5zZmVyQnVpbGRlckVSQzExNTUnO1xuaW1wb3J0IHsgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIH0gZnJvbSAnLi90cmFuc2ZlckJ1aWxkZXJzL3RyYW5zZmVyQnVpbGRlckVSQzcyMSc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiB9IGZyb20gJy4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgVHJhbnNmZXJCdWlsZGVyIH0gZnJvbSAnLi90cmFuc2ZlckJ1aWxkZXInO1xuXG5jb25zdCBERUZBVUxUX00gPSAzO1xuXG4vKipcbiAqIEV0aGVyZXVtTGlrZSB0cmFuc2FjdGlvbiBidWlsZGVyLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVHJhbnNhY3Rpb25CdWlsZGVyIGV4dGVuZHMgQmFzZVRyYW5zYWN0aW9uQnVpbGRlciB7XG4gIHByb3RlY3RlZCBfdHlwZTogVHJhbnNhY3Rpb25UeXBlO1xuICAvLyBTcGVjaWZpZXMgY29tbW9uIGNoYWluIGFuZCBoYXJkZm9yayBwYXJhbWV0ZXJzLlxuICBwcm90ZWN0ZWQgX2NvbW1vbjogRXRoZXJldW1Db21tb247XG4gIHByb3RlY3RlZCBfc291cmNlS2V5UGFpcjogS2V5UGFpcjtcbiAgcHJpdmF0ZSBfdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uO1xuICBwcml2YXRlIF9jb3VudGVyOiBudW1iZXI7XG4gIHByaXZhdGUgX2ZlZTogRmVlO1xuICBwcm90ZWN0ZWQgX3ZhbHVlOiBzdHJpbmc7XG5cbiAgLy8gdGhlIHNpZ25hdHVyZSBvbiB0aGUgZXh0ZXJuYWwgRVRIIHRyYW5zYWN0aW9uXG4gIHByaXZhdGUgX3R4U2lnbmF0dXJlOiBTaWduYXR1cmVQYXJ0cztcblxuICAvLyBXYWxsZXQgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb24gcGFyYW1ldGVyc1xuICBwcml2YXRlIF93YWxsZXRPd25lckFkZHJlc3Nlczogc3RyaW5nW107XG4gIHByb3RlY3RlZCBfd2FsbGV0VmVyc2lvbjogbnVtYmVyO1xuXG4gIC8vIGZsdXNoIHRva2VucyBwYXJhbWV0ZXJzXG4gIHByaXZhdGUgX2ZvcndhcmRlckFkZHJlc3M6IHN0cmluZztcbiAgcHJpdmF0ZSBfdG9rZW5BZGRyZXNzOiBzdHJpbmc7XG5cbiAgLy8gU2VuZCBhbmQgQWRkcmVzc0luaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uIHNwZWNpZmljIHBhcmFtZXRlcnNcbiAgcHJvdGVjdGVkIF90cmFuc2ZlcjogVHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcjtcbiAgcHJpdmF0ZSBfY29udHJhY3RBZGRyZXNzOiBzdHJpbmc7XG4gIHByaXZhdGUgX2NvbnRyYWN0Q291bnRlcjogbnVtYmVyO1xuICBwcml2YXRlIF9mb3J3YXJkZXJWZXJzaW9uOiBudW1iZXI7XG4gIHByaXZhdGUgX2luaXRDb2RlOiBzdHJpbmc7XG4gIHByaXZhdGUgX2Jhc2VBZGRyZXNzOiBzdHJpbmc7XG4gIHByaXZhdGUgX2ZlZUFkZHJlc3M6IHN0cmluZztcblxuICAvLyBnZW5lcmljIGNvbnRyYWN0IGNhbGwgYnVpbGRlclxuICAvLyBlbmNvZGVkIGNvbnRyYWN0IGNhbGwgaGV4XG4gIHByaXZhdGUgX2RhdGE6IHN0cmluZztcblxuICAvLyBDb21tb24gcGFyYW1ldGVyIGZvciB3YWxsZXQgaW5pdGlhbGl6YXRpb24gYW5kIGFkZHJlc3MgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25cbiAgcHJpdmF0ZSBfc2FsdDogc3RyaW5nO1xuXG4gIC8vIHdhbGxldHNpbXBsZWJ5dGVjb2RlXG4gIHByb3RlY3RlZCBfd2FsbGV0U2ltcGxlQnl0ZUNvZGU6IHN0cmluZztcblxuICAvKipcbiAgICogUHVibGljIGNvbnN0cnVjdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gX2NvaW5Db25maWdcbiAgICovXG4gIGNvbnN0cnVjdG9yKF9jb2luQ29uZmlnOiBSZWFkb25seTxDb2luQ29uZmlnPikge1xuICAgIHN1cGVyKF9jb2luQ29uZmlnKTtcbiAgICB0aGlzLl9jb21tb24gPSBnZXRDb21tb24odGhpcy5fY29pbkNvbmZpZy5uZXR3b3JrIGFzIEV0aGVyZXVtTmV0d29yayk7XG4gICAgdGhpcy5fdHlwZSA9IFRyYW5zYWN0aW9uVHlwZS5TZW5kO1xuICAgIHRoaXMuX2NvdW50ZXIgPSAwO1xuICAgIHRoaXMuX3ZhbHVlID0gJzAnO1xuICAgIHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzID0gW107XG4gICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA9IDA7XG4gICAgdGhpcy5fd2FsbGV0VmVyc2lvbiA9IDA7XG4gICAgdGhpcy50cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0aGlzLl9jb21tb24pO1xuICAgIHRoaXMuX3dhbGxldFNpbXBsZUJ5dGVDb2RlID0gJyc7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGJ1aWxkSW1wbGVtZW50YXRpb24oKTogUHJvbWlzZTxCYXNlVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB0cmFuc2FjdGlvbkRhdGEgPSB0aGlzLmdldFRyYW5zYWN0aW9uRGF0YSgpO1xuXG4gICAgaWYgKHRoaXMuX3R4U2lnbmF0dXJlKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRyYW5zYWN0aW9uRGF0YSwgdGhpcy5fdHhTaWduYXR1cmUpO1xuICAgIH1cblxuICAgIHRoaXMudHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKHRoaXMuX3R5cGUpO1xuICAgIHRyYW5zYWN0aW9uRGF0YS5mcm9tID0gdGhpcy5fc291cmNlS2V5UGFpciA/IHRoaXMuX3NvdXJjZUtleVBhaXIuZ2V0QWRkcmVzcygpIDogdW5kZWZpbmVkO1xuICAgIHRoaXMudHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25EYXRhKFxuICAgICAgdHJhbnNhY3Rpb25EYXRhLFxuICAgICAgdGhpcy5fdHJhbnNmZXIgPyB0aGlzLl90cmFuc2Zlci5nZXRJc0ZpcnN0U2lnbmVyKCkgOiB1bmRlZmluZWRcbiAgICApO1xuICAgIC8vIEJ1aWxkIGFuZCBzaWduIGEgbmV3IHRyYW5zYWN0aW9uIGJhc2VkIG9uIHRoZSBsYXRlc3QgY2hhbmdlc1xuICAgIGlmICh0aGlzLl9zb3VyY2VLZXlQYWlyICYmIHRoaXMuX3NvdXJjZUtleVBhaXIuZ2V0S2V5cygpLnBydikge1xuICAgICAgYXdhaXQgdGhpcy50cmFuc2FjdGlvbi5zaWduKHRoaXMuX3NvdXJjZUtleVBhaXIpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbjtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRUcmFuc2FjdGlvbkRhdGEoKTogVHhEYXRhIHtcbiAgICBzd2l0Y2ggKHRoaXMuX3R5cGUpIHtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLldhbGxldEluaXRpYWxpemF0aW9uOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZFdhbGxldEluaXRpYWxpemF0aW9uVHJhbnNhY3Rpb24odGhpcy5fd2FsbGV0VmVyc2lvbik7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5SZWNvdmVyeVdhbGxldERlcGxveW1lbnQ6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkQmFzZSh0aGlzLl9kYXRhKTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDNzIxOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzExNTU6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkU2VuZFRyYW5zYWN0aW9uKCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkQWRkcmVzc0luaXRpYWxpemF0aW9uVHJhbnNhY3Rpb24oKTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkZsdXNoVG9rZW5zOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEZsdXNoVG9rZW5zVHJhbnNhY3Rpb24oKTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkZsdXNoQ29pbnM6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkRmx1c2hDb2luc1RyYW5zYWN0aW9uKCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEJhc2UoJzB4Jyk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGw6XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkR2VuZXJpY0NvbnRyYWN0Q2FsbFRyYW5zYWN0aW9uKCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdVbnN1cHBvcnRlZCB0cmFuc2FjdGlvbiB0eXBlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHByb3RlY3RlZCBmcm9tSW1wbGVtZW50YXRpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZywgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW4pOiBUcmFuc2FjdGlvbiB7XG4gICAgbGV0IHR4OiBUcmFuc2FjdGlvbjtcbiAgICBpZiAoL14weD9bMC05YS1mXXsxLH0kLy50ZXN0KHJhd1RyYW5zYWN0aW9uLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICB0eCA9IFRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkKHRoaXMuX2NvaW5Db25maWcsIHRoaXMuX2NvbW1vbiwgcmF3VHJhbnNhY3Rpb24sIGlzRmlyc3RTaWduZXIpO1xuICAgICAgdGhpcy5sb2FkQnVpbGRlcklucHV0KHR4LnRvSnNvbigpLCBpc0ZpcnN0U2lnbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdHhEYXRhID0gSlNPTi5wYXJzZShyYXdUcmFuc2FjdGlvbik7XG4gICAgICB0eCA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0eERhdGEpO1xuICAgIH1cbiAgICByZXR1cm4gdHg7XG4gIH1cblxuICAvKipcbiAgICogTG9hZCB0aGUgYnVpbGRlciBkYXRhIHVzaW5nIHRoZSBkZXNlcmlhbGl6ZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtUeERhdGF9IHRyYW5zYWN0aW9uSnNvbiB0aGUgZGVzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGpzb25cbiAgICogQHBhcmFtIHtib29sZWFufSBpc0ZpcnN0U2lnbmVyIGlmIHRoZSB0cmFuc2FjdGlvbiBpcyBiZWluZyBzaWduZWQgYnkgdGhlIGZpcnN0IHNpZ25lclxuICAgKi9cbiAgcHJvdGVjdGVkIGxvYWRCdWlsZGVySW5wdXQodHJhbnNhY3Rpb25Kc29uOiBUeERhdGEsIGlzRmlyc3RTaWduZXI/OiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgZGVjb2RlZFR5cGUgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICB0aGlzLnR5cGUoZGVjb2RlZFR5cGUpO1xuICAgIHRoaXMuY291bnRlcih0cmFuc2FjdGlvbkpzb24ubm9uY2UpO1xuICAgIHRoaXMudmFsdWUodHJhbnNhY3Rpb25Kc29uLnZhbHVlKTtcblxuICAgIGlmICh0cmFuc2FjdGlvbkpzb24uX3R5cGUgPT09IEVUSFRyYW5zYWN0aW9uVHlwZS5MRUdBQ1kpIHtcbiAgICAgIHRoaXMuZmVlKHtcbiAgICAgICAgZmVlOiB0cmFuc2FjdGlvbkpzb24uZ2FzUHJpY2UsXG4gICAgICAgIGdhc1ByaWNlOiB0cmFuc2FjdGlvbkpzb24uZ2FzUHJpY2UsXG4gICAgICAgIGdhc0xpbWl0OiB0cmFuc2FjdGlvbkpzb24uZ2FzTGltaXQsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5mZWUoe1xuICAgICAgICBnYXNMaW1pdDogdHJhbnNhY3Rpb25Kc29uLmdhc0xpbWl0LFxuICAgICAgICBmZWU6IHRyYW5zYWN0aW9uSnNvbi5tYXhGZWVQZXJHYXMsXG4gICAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgICBtYXhGZWVQZXJHYXM6IHRyYW5zYWN0aW9uSnNvbi5tYXhGZWVQZXJHYXMsXG4gICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IHRyYW5zYWN0aW9uSnNvbi5tYXhQcmlvcml0eUZlZVBlckdhcyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChoYXNTaWduYXR1cmUodHJhbnNhY3Rpb25Kc29uKSkge1xuICAgICAgdGhpcy5fdHhTaWduYXR1cmUgPSB7IHY6IHRyYW5zYWN0aW9uSnNvbi52ISwgcjogdHJhbnNhY3Rpb25Kc29uLnIhLCBzOiB0cmFuc2FjdGlvbkpzb24ucyEgfTtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGVGaWVsZHMoZGVjb2RlZFR5cGUsIHRyYW5zYWN0aW9uSnNvbiwgaXNGaXJzdFNpZ25lcik7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0VHJhbnNhY3Rpb25UeXBlRmllbGRzKFxuICAgIGRlY29kZWRUeXBlOiBUcmFuc2FjdGlvblR5cGUsXG4gICAgdHJhbnNhY3Rpb25Kc29uOiBUeERhdGEsXG4gICAgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW5cbiAgKTogdm9pZCB7XG4gICAgc3dpdGNoIChkZWNvZGVkVHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICAgIGNvbnN0IHsgb3duZXJzLCBzYWx0IH0gPSBkZWNvZGVXYWxsZXRDcmVhdGlvbkRhdGEodHJhbnNhY3Rpb25Kc29uLmRhdGEpO1xuICAgICAgICBvd25lcnMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgICAgIHRoaXMub3duZXIoZWxlbWVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoc2FsdCkge1xuICAgICAgICAgIHRoaXMuc2FsdChzYWx0IGFzIHN0cmluZyk7XG4gICAgICAgICAgdGhpcy53YWxsZXRWZXJzaW9uKDEpO1xuICAgICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudDpcbiAgICAgICAgdGhpcy5kYXRhKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaFRva2VuczpcbiAgICAgICAgdGhpcy5zZXRDb250cmFjdCh0cmFuc2FjdGlvbkpzb24udG8pO1xuICAgICAgICBjb25zdCB7IGZvcndhcmRlckFkZHJlc3MsIHRva2VuQWRkcmVzcywgZm9yd2FyZGVyVmVyc2lvbiB9ID0gZGVjb2RlRmx1c2hUb2tlbnNEYXRhKFxuICAgICAgICAgIHRyYW5zYWN0aW9uSnNvbi5kYXRhLFxuICAgICAgICAgIHRyYW5zYWN0aW9uSnNvbi50b1xuICAgICAgICApO1xuICAgICAgICBpZiAoZm9yd2FyZGVyVmVyc2lvbiA9PT0gNCkge1xuICAgICAgICAgIHRoaXMuZm9yd2FyZGVyVmVyc2lvbig0KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmZvcndhcmRlckFkZHJlc3MoZm9yd2FyZGVyQWRkcmVzcyk7XG4gICAgICAgIHRoaXMudG9rZW5BZGRyZXNzKHRva2VuQWRkcmVzcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuRmx1c2hDb2luczpcbiAgICAgICAgdGhpcy5zZXRDb250cmFjdCh0cmFuc2FjdGlvbkpzb24udG8pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDMTE1NTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmRFUkM3MjE6XG4gICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgdGhpcy5fdHJhbnNmZXIgPSB0aGlzLnRyYW5zZmVyKHRyYW5zYWN0aW9uSnNvbi5kYXRhLCBpc0ZpcnN0U2lnbmVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgY29uc3QgeyBiYXNlQWRkcmVzcywgYWRkcmVzc0NyZWF0aW9uU2FsdCwgZmVlQWRkcmVzcyB9ID0gZGVjb2RlRm9yd2FyZGVyQ3JlYXRpb25EYXRhKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICAgICAgaWYgKGJhc2VBZGRyZXNzICYmIGFkZHJlc3NDcmVhdGlvblNhbHQpIHtcbiAgICAgICAgICB0aGlzLmJhc2VBZGRyZXNzKGJhc2VBZGRyZXNzKTtcbiAgICAgICAgICB0aGlzLnNhbHQoYWRkcmVzc0NyZWF0aW9uU2FsdCk7XG4gICAgICAgICAgaWYgKGZlZUFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuZmVlQWRkcmVzcyhmZWVBZGRyZXNzKTtcbiAgICAgICAgICAgIHRoaXMuZm9yd2FyZGVyVmVyc2lvbig0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5mb3J3YXJkZXJWZXJzaW9uKDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBmb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MgPSAodGhpcy5fY29pbkNvbmZpZy5uZXR3b3JrIGFzIEV0aGVyZXVtTmV0d29yaylcbiAgICAgICAgICAgIC5mb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MgYXMgc3RyaW5nO1xuICAgICAgICAgIGlmIChmb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdENvZGUoZm9yd2FyZGVySW1wbGVtZW50YXRpb25BZGRyZXNzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIHRoaXMuZGF0YSh0cmFuc2FjdGlvbkpzb24uZGF0YSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5zdXBwb3J0ZWQgdHJhbnNhY3Rpb24gdHlwZScpO1xuICAgICAgLy8gVE9ETzogQWRkIG90aGVyIGNhc2VzIG9mIGRlc2VyaWFsaXphdGlvblxuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgc2lnbkltcGxlbWVudGF0aW9uKGtleTogQmFzZUtleSk6IEJhc2VUcmFuc2FjdGlvbiB7XG4gICAgY29uc3Qgc2lnbmVyID0gbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSk7XG4gICAgaWYgKHRoaXMuX3R5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5XYWxsZXRJbml0aWFsaXphdGlvbiAmJiB0aGlzLl93YWxsZXRPd25lckFkZHJlc3Nlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ0Nhbm5vdCBzaWduIGFuIHdhbGxldCBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbiB3aXRob3V0IG93bmVycycpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fc291cmNlS2V5UGFpcikge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignQ2Fubm90IHNpZ24gbXVsdGlwbGUgdGltZXMgYSBub24gc2VuZC10eXBlIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICAgIC8vIFNpZ25pbmcgdGhlIHRyYW5zYWN0aW9uIGlzIGFuIGFzeW5jIG9wZXJhdGlvbiwgc28gc2F2ZSB0aGUgc291cmNlIGFuZCBsZWF2ZSB0aGUgYWN0dWFsXG4gICAgLy8gc2lnbmluZyBmb3IgdGhlIGJ1aWxkIHN0ZXBcbiAgICB0aGlzLl9zb3VyY2VLZXlQYWlyID0gc2lnbmVyO1xuICAgIHJldHVybiB0aGlzLnRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlQWRkcmVzcyhhZGRyZXNzOiBCYXNlQWRkcmVzcyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcy5hZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBhZGRyZXNzICcgKyBhZGRyZXNzLmFkZHJlc3MpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZUtleShrZXk6IEJhc2VLZXkpOiB2b2lkIHtcbiAgICBpZiAoIShpc1ZhbGlkWHBydihrZXkua2V5KSB8fCBpc1ZhbGlkUHJ2KGtleS5rZXkpKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBrZXknKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIHJhdyB0cmFuc2FjdGlvbiBpcyBlaXRoZXIgYSBKU09OIG9yXG4gICAqIGEgaGV4IGVuY29kZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHthbnl9IHJhd1RyYW5zYWN0aW9uIFRoZSByYXcgdHJhbnNhY3Rpb24gdG8gYmUgdmFsaWRhdGVkXG4gICAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIXJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBlbXB0eScpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHJhd1RyYW5zYWN0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKC9eMHg/WzAtOWEtZl17MSx9JC8udGVzdChyYXdUcmFuc2FjdGlvbi50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICBjb25zdCB0eEJ5dGVzID0gZXRoVXRpbC50b0J1ZmZlcihldGhVdGlsLmFkZEhleFByZWZpeChyYXdUcmFuc2FjdGlvbi50b0xvd2VyQ2FzZSgpKSk7XG4gICAgICAgIGlmICghdGhpcy5pc0VpcDE1NTlUeG4odHhCeXRlcykgJiYgIXRoaXMuaXNSTFBEZWNvZGFibGUodHhCeXRlcykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdUaGVyZSB3YXMgZXJyb3IgaW4gZGVjb2RpbmcgdGhlIGhleCBzdHJpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBKU09OLnBhcnNlKHJhd1RyYW5zYWN0aW9uKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1RoZXJlIHdhcyBlcnJvciBpbiBwYXJzaW5nIHRoZSBKU09OIHN0cmluZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gaXMgbm90IGEgaGV4IHN0cmluZyBvciBzdHJpbmdpZmllZCBqc29uJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc0VpcDE1NTlUeG4odHhuOiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkVHgodHhuKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzUkxQRGVjb2RhYmxlKGJ5dGVzOiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZXRoVXRpbC5ybHAuZGVjb2RlKGJ5dGVzKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgdmFsaWRhdGVCYXNlVHJhbnNhY3Rpb25GaWVsZHMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2ZlZSA9PT0gdW5kZWZpbmVkIHx8ICghdGhpcy5fZmVlLmZlZSAmJiAhdGhpcy5fZmVlLmdhc1ByaWNlICYmICF0aGlzLl9mZWUuZWlwMTU1OSkpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgZmVlJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jb21tb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbmV0d29yayBjb21tb24nKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2NvdW50ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBhZGRyZXNzIGNvdW50ZXInKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogQmFzZVRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy52YWxpZGF0ZUJhc2VUcmFuc2FjdGlvbkZpZWxkcygpO1xuICAgIHN3aXRjaCAodGhpcy5fdHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMudmFsaWRhdGVXYWxsZXRJbml0aWFsaXphdGlvbkZpZWxkcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudDpcbiAgICAgICAgdGhpcy52YWxpZGF0ZURhdGFGaWVsZCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDNzIxOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzExNTU6XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaENvaW5zOlxuICAgICAgICB0aGlzLnZhbGlkYXRlQ29udHJhY3RBZGRyZXNzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuRmx1c2hUb2tlbnM6XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZUZvcndhcmRlckFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRva2VuQWRkcmVzcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNpbmdsZVNpZ1NlbmQ6XG4gICAgICAgIC8vIGZvciBzaW5nbGUgc2lnIHNlbmRzLCB0aGUgY29udHJhY3QgYWRkcmVzcyBpcyBhY3R1YWxseSB0aGUgcmVjaXBpZW50XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nTG9jazpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2s6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nVm90ZTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbnZvdGU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICB0aGlzLnZhbGlkYXRlQ29udHJhY3RBZGRyZXNzKCk7XG4gICAgICAgIHRoaXMudmFsaWRhdGVEYXRhRmllbGQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdVbnN1cHBvcnRlZCB0cmFuc2FjdGlvbiB0eXBlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdhbGxldCBvd25lciBhZGRyZXNzZXMgZm9yIHdhbGxldCBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbnMgYXJlIHZhbGlkIG9yIHRocm93LlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVdhbGxldEluaXRpYWxpemF0aW9uRmllbGRzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl93YWxsZXRPd25lckFkZHJlc3NlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIHdhbGxldCBvd25lcnMnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RoICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW52YWxpZCB0cmFuc2FjdGlvbjogd3JvbmcgbnVtYmVyIG9mIG93bmVycyAtLSByZXF1aXJlZDogMywgZm91bmQ6ICR7dGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RofWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgdG9rZW4gYWRkcmVzcyBmb3IgdGhlIHR4IHdhcyBkZWZpbmVkIG9yIHRocm93LlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVRva2VuQWRkcmVzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fdG9rZW5BZGRyZXNzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgdG9rZW4gYWRkcmVzcycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhIGZvcndhcmRlciBhZGRyZXNzIGZvciB0aGUgdHggd2FzIGRlZmluZWQgb3IgdGhyb3cuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlRm9yd2FyZGVyQWRkcmVzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZm9yd2FyZGVyQWRkcmVzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGZvcndhcmRlciBhZGRyZXNzJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgY29udHJhY3QgYWRkcmVzcyBmb3IgdGhlIHdhbGxldCB3YXMgZGVmaW5lZCBvciB0aHJvdy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2NvbnRyYWN0QWRkcmVzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGFkZHJlc3MnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgY29udHJhY3QgY2FsbCBkYXRhIGZpZWxkIHdhcyBkZWZpbmVkIG9yIHRocm93cyBvdGhlcndpc2VcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRhRmllbGQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9kYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGNhbGwgZGF0YSBmaWVsZCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0Q29udHJhY3QoYWRkcmVzczogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKGFkZHJlc3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5kZWZpbmVkIHJlY2lwaWVudCBhZGRyZXNzJyk7XG4gICAgfVxuICAgIHRoaXMuY29udHJhY3QoYWRkcmVzcyk7XG4gIH1cblxuICB2YWxpZGF0ZVZhbHVlKHZhbHVlOiBCaWdOdW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUuaXNMZXNzVGhhbigwKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVmFsdWUgY2Fubm90IGJlIGJlbG93IGxlc3MgdGhhbiB6ZXJvJyk7XG4gICAgfVxuICAgIC8vIFRPRE86IHZhbGlkYXRlIHRoZSBhbW91bnQgaXMgbm90IGJpZ2dlciB0aGFuIHRoZSBtYXggYW1vdW50IGluIGVhY2ggRXRoIGZhbWlseSBjb2luXG4gIH1cblxuICAvLyByZWdpb24gQ29tbW9uIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIC8qKlxuICAgKiBUaGUgdHlwZSBvZiB0cmFuc2FjdGlvbiBiZWluZyBidWlsdC5cbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblR5cGV9IHR5cGVcbiAgICovXG4gIHR5cGUodHlwZTogVHJhbnNhY3Rpb25UeXBlKTogdm9pZCB7XG4gICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBmZWVzLiBMb3cgZmVlcyBtYXkgZ2V0IGEgdHJhbnNhY3Rpb24gcmVqZWN0ZWQgb3IgbmV2ZXIgcGlja2VkIHVwIGJ5IGJha2Vycy5cbiAgICpcbiAgICogQHBhcmFtIHtGZWV9IGZlZSBCYWtlciBmZWVzLiBNYXkgYWxzbyBpbmNsdWRlIHRoZSBtYXhpbXVtIGdhcyB0byBwYXlcbiAgICovXG4gIGZlZShmZWU6IEZlZSk6IHZvaWQge1xuICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5mZWUpKTtcbiAgICBpZiAoZmVlLmdhc0xpbWl0KSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZ2FzTGltaXQpKTtcbiAgICB9XG4gICAgaWYgKGZlZS5laXAxNTU5KSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZWlwMTU1OS5tYXhGZWVQZXJHYXMpKTtcbiAgICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5laXAxNTU5Lm1heFByaW9yaXR5RmVlUGVyR2FzKSk7XG4gICAgfVxuICAgIGlmIChmZWUuZ2FzUHJpY2UpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5nYXNQcmljZSkpO1xuICAgIH1cbiAgICB0aGlzLl9mZWUgPSBmZWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBjb3VudGVyIHRvIHByZXZlbnQgc3VibWl0dGluZyByZXBlYXRlZCB0cmFuc2FjdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb3VudGVyIFRoZSBjb3VudGVyIHRvIHVzZVxuICAgKi9cbiAgY291bnRlcihjb3VudGVyOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoY291bnRlciA8IDApIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgY291bnRlcjogJHtjb3VudGVyfWApO1xuICAgIH1cblxuICAgIHRoaXMuX2NvdW50ZXIgPSBjb3VudGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB2YWx1ZSB0byBzZW5kIGFsb25nIHdpdGggdGhpcyB0cmFuc2FjdGlvbi4gMCBieSBkZWZhdWx0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VuZCBhbG9uZyB3aXRoIHRoaXMgdHJhbnNhY3Rpb25cbiAgICovXG4gIHZhbHVlKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gc2V0IGFyZ3MgdGhhdCBhcmUgcmVxdWlyZWQgZm9yIGFsbCB0eXBlcyBvZiBldGggdHJhbnNhY3Rpb25zXG4gIHByb3RlY3RlZCBidWlsZEJhc2UoZGF0YTogc3RyaW5nKTogVHhEYXRhIHtcbiAgICBjb25zdCBiYXNlUGFyYW1zID0ge1xuICAgICAgZ2FzTGltaXQ6IHRoaXMuX2ZlZS5nYXNMaW1pdCxcbiAgICAgIG5vbmNlOiB0aGlzLl9jb3VudGVyLFxuICAgICAgZGF0YTogZGF0YSxcbiAgICAgIGNoYWluSWQ6IHRoaXMuX2NvbW1vbi5jaGFpbklkQk4oKS50b1N0cmluZygpLFxuICAgICAgdmFsdWU6IHRoaXMuX3ZhbHVlLFxuICAgICAgdG86IHRoaXMuX2NvbnRyYWN0QWRkcmVzcyxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuX2ZlZS5laXAxNTU5KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICBfdHlwZTogRVRIVHJhbnNhY3Rpb25UeXBlLkVJUDE1NTksXG4gICAgICAgIG1heEZlZVBlckdhczogdGhpcy5fZmVlLmVpcDE1NTkubWF4RmVlUGVyR2FzLFxuICAgICAgICBtYXhQcmlvcml0eUZlZVBlckdhczogdGhpcy5fZmVlLmVpcDE1NTkubWF4UHJpb3JpdHlGZWVQZXJHYXMsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICBfdHlwZTogRVRIVHJhbnNhY3Rpb25UeXBlLkxFR0FDWSxcbiAgICAgICAgZ2FzUHJpY2U6IHRoaXMuX2ZlZT8uZ2FzUHJpY2UgPz8gdGhpcy5fZmVlLmZlZSxcbiAgICAgICAgdjogdGhpcy5nZXRGaW5hbFYoKSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIFdhbGxldEluaXRpYWxpemF0aW9uIGJ1aWxkZXIgbWV0aG9kc1xuICAvKipcbiAgICogU2V0IG9uZSBvZiB0aGUgb3duZXJzIG9mIHRoZSBtdWx0aXNpZyB3YWxsZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIEFuIEV0aGVyZXVtIGFkZHJlc3NcbiAgICovXG4gIG93bmVyKGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLl90eXBlICE9PSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ011bHRpc2lnIHdhbGxldCBvd25lciBjYW4gb25seSBiZSBzZXQgZm9yIGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9ucycpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RoID49IERFRkFVTFRfTSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignQSBtYXhpbXVtIG9mICcgKyBERUZBVUxUX00gKyAnIG93bmVycyBjYW4gYmUgc2V0IGZvciBhIG11bHRpc2lnIHdhbGxldCcpO1xuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLmluY2x1ZGVzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdSZXBlYXRlZCBvd25lciBhZGRyZXNzOiAnICsgYWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLnB1c2goYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSB0cmFuc2FjdGlvbiBmb3IgYSBnZW5lcmljIG11bHRpc2lnIGNvbnRyYWN0LlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJvdGVjdGVkIGJ1aWxkV2FsbGV0SW5pdGlhbGl6YXRpb25UcmFuc2FjdGlvbih3YWxsZXRWZXJzaW9uPzogbnVtYmVyKTogVHhEYXRhIHtcbiAgICBjb25zdCB3YWxsZXRJbml0RGF0YSA9XG4gICAgICB3YWxsZXRWZXJzaW9uID09PSBkZWZhdWx0V2FsbGV0VmVyc2lvblxuICAgICAgICA/IHRoaXMuZ2V0Q29udHJhY3REYXRhKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzKVxuICAgICAgICA6IGdldFYxV2FsbGV0SW5pdGlhbGl6YXRpb25EYXRhKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLCB0aGlzLl9zYWx0KTtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJhc2Uod2FsbGV0SW5pdERhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNtYXJ0IGNvbnRyYWN0IGVuY29kZWQgZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBhZGRyZXNzZXMgLSB0aGUgY29udHJhY3Qgc2lnbmVyc1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIHRoZSBzbWFydCBjb250cmFjdCBlbmNvZGVkIGRhdGFcbiAgICovXG4gIHByb3RlY3RlZCBnZXRDb250cmFjdERhdGEoYWRkcmVzc2VzOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFyYW1zID0gW2FkZHJlc3Nlc107XG4gICAgY29uc3QgcmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUod2FsbGV0U2ltcGxlQ29uc3RydWN0b3IsIHBhcmFtcylcbiAgICAgIC50b1N0cmluZygnaGV4JylcbiAgICAgIC5yZXBsYWNlKCcweCcsICcnKTtcbiAgICByZXR1cm4gdGhpcy5fd2FsbGV0U2ltcGxlQnl0ZUNvZGUgKyByZXN1bHRFbmNvZGVkUGFyYW1ldGVycztcbiAgfVxuXG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8vIHJlZ2lvbiBTZW5kIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIGNvbnRyYWN0KGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIGFkZHJlc3MpO1xuICAgIH1cbiAgICB0aGlzLl9jb250cmFjdEFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHRyYW5zZmVyIGZ1bmRzIGJ1aWxkZXIgaWYgZXhpc3QsIG9yIGNyZWF0ZXMgYSBuZXcgb25lIGZvciB0aGlzIHRyYW5zYWN0aW9uIGFuZCByZXR1cm5zIGl0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIHRyYW5zZmVyIGRhdGEgdG8gaW5pdGlhbGl6ZSB0aGUgdHJhbnNmZXIgYnVpbGRlciB3aXRoLCBlbXB0eSBpZiBub25lIGdpdmVuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGaXJzdFNpZ25lciB3aGV0aGVyIHRoZSB0cmFuc2FjdGlvbiBpcyBiZWluZyBzaWduZWQgYnkgdGhlIGZpcnN0IHNpZ25lclxuICAgKiBAcmV0dXJucyB7VHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcn0gdGhlIHRyYW5zZmVyIGJ1aWxkZXJcbiAgICovXG4gIGFic3RyYWN0IHRyYW5zZmVyKFxuICAgIGRhdGE/OiBzdHJpbmcsXG4gICAgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW5cbiAgKTogVHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcjtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2VyaWFsaXplZCBzZW5kTXVsdGlTaWcgY29udHJhY3QgbWV0aG9kIGRhdGFcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gc2VyaWFsaXplZCBzZW5kTXVsdGlTaWcgZGF0YVxuICAgKi9cbiAgcHVibGljIGdldFNlbmREYXRhKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLl90cmFuc2Zlcikge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignTWlzc2luZyB0cmFuc2ZlciBpbmZvcm1hdGlvbicpO1xuICAgIH1cbiAgICBjb25zdCBjaGFpbklkID0gdGhpcy5fY29tbW9uLmNoYWluSWRCTigpLnRvU3RyaW5nKCk7XG4gICAgdGhpcy5fdHJhbnNmZXIud2FsbGV0VmVyc2lvbih0aGlzLl93YWxsZXRWZXJzaW9uKTtcbiAgICAvLyBUaGlzIGNoYW5nZSBpcyBtYWRlIHRvIHN1cHBvcnQgbmV3IGNvbnRyYWN0cyB3aXRoIGRpZmZlcmVudCBlbmNvZGluZyB0eXBlXG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zZmVyLnNpZ25BbmRCdWlsZChjaGFpbklkLCB0aGlzLmNvaW5Vc2VzTm9uUGFja2VkRW5jb2RpbmdGb3JUeERhdGEoKSk7XG4gIH1cblxuICAvKipcbiAgICogRGVjaWRlIGlmIHRoZSBjb2luIHVzZXMgbm9uLXBhY2tlZCBlbmNvZGluZyBmb3IgdHggZGF0YVxuICAgKlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgY29pbiB1c2VzIG5vbi1wYWNrZWQgZW5jb2RpbmcgZm9yIHR4IGRhdGFcbiAgICovXG4gIHB1YmxpYyBjb2luVXNlc05vblBhY2tlZEVuY29kaW5nRm9yVHhEYXRhKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLl93YWxsZXRWZXJzaW9uID09PSA0IHx8IHRoaXMuX2NvaW5Db25maWcuZmVhdHVyZXMuaW5jbHVkZXMoQ29pbkZlYXR1cmUuVVNFU19OT05fUEFDS0VEX0VOQ09ESU5HX0ZPUl9UWERBVEEpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRTZW5kVHJhbnNhY3Rpb24oKTogVHhEYXRhIHtcbiAgICBjb25zdCBzZW5kRGF0YSA9IHRoaXMuZ2V0U2VuZERhdGEoKTtcbiAgICBjb25zdCB0eDogVHhEYXRhID0gdGhpcy5idWlsZEJhc2Uoc2VuZERhdGEpO1xuICAgIHR4LnRvID0gdGhpcy5fY29udHJhY3RBZGRyZXNzO1xuICAgIHJldHVybiB0eDtcbiAgfVxuXG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8vIHJlZ2lvbiBBZGRyZXNzSW5pdGlhbGl6YXRpb24gYnVpbGRlciBtZXRob2RzXG5cbiAgLyoqXG4gICAqIFNldCB0aGUgY29udHJhY3QgdHJhbnNhY3Rpb24gbm9uY2UgdG8gY2FsY3VsYXRlIHRoZSBmb3J3YXJkZXIgYWRkcmVzcy5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IGNvbnRyYWN0Q291bnRlciBUaGUgY291bnRlciB0byB1c2VcbiAgICovXG4gIGNvbnRyYWN0Q291bnRlcihjb250cmFjdENvdW50ZXI6IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChjb250cmFjdENvdW50ZXIgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIGNvbnRyYWN0IGNvdW50ZXI6ICR7Y29udHJhY3RDb3VudGVyfWApO1xuICAgIH1cblxuICAgIHRoaXMuX2NvbnRyYWN0Q291bnRlciA9IGNvbnRyYWN0Q291bnRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zYWN0aW9uIHRvIGNyZWF0ZSBhIGZvcndhcmRlci5cbiAgICpcbiAgICogQHJldHVybnMge1R4RGF0YX0gVGhlIEV0aGVyZXVtIHRyYW5zYWN0aW9uIGRhdGFcbiAgICovXG4gIHByaXZhdGUgYnVpbGRBZGRyZXNzSW5pdGlhbGl6YXRpb25UcmFuc2FjdGlvbigpOiBUeERhdGEge1xuICAgIGNvbnN0IGFkZHJlc3NJbml0RGF0YSA9IGdldEFkZHJlc3NJbml0RGF0YUFsbEZvcndhcmRlclZlcnNpb25zKFxuICAgICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbixcbiAgICAgIHRoaXMuX2Jhc2VBZGRyZXNzLFxuICAgICAgdGhpcy5fc2FsdCxcbiAgICAgIHRoaXMuX2ZlZUFkZHJlc3NcbiAgICApO1xuICAgIGNvbnN0IHR4OiBUeERhdGEgPSB0aGlzLmJ1aWxkQmFzZShhZGRyZXNzSW5pdERhdGEpO1xuICAgIHR4LnRvID0gdGhpcy5fY29udHJhY3RBZGRyZXNzO1xuXG4gICAgaWYgKHRoaXMuX2NvbnRyYWN0Q291bnRlcikge1xuICAgICAgdHguZGVwbG95ZWRBZGRyZXNzID0gY2FsY3VsYXRlRm9yd2FyZGVyQWRkcmVzcyh0aGlzLl9jb250cmFjdEFkZHJlc3MsIHRoaXMuX2NvbnRyYWN0Q291bnRlcik7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3NhbHQgJiYgdGhpcy5faW5pdENvZGUpIHtcbiAgICAgIGNvbnN0IHNhbHRCdWZmZXIgPSBldGhVdGlsLnNldExlbmd0aExlZnQoZXRoVXRpbC50b0J1ZmZlcih0aGlzLl9zYWx0KSwgMzIpO1xuXG4gICAgICBjb25zdCB7IGNyZWF0ZUZvcndhcmRlclBhcmFtcywgY3JlYXRlRm9yd2FyZGVyVHlwZXMgfSA9IGdldENyZWF0ZUZvcndhcmRlclBhcmFtc0FuZFR5cGVzKFxuICAgICAgICB0aGlzLl9iYXNlQWRkcmVzcyxcbiAgICAgICAgc2FsdEJ1ZmZlcixcbiAgICAgICAgdGhpcy5fZmVlQWRkcmVzc1xuICAgICAgKTtcblxuICAgICAgLy8gSGFzaCB0aGUgd2FsbGV0IGJhc2UgYWRkcmVzcyBhbmQgZmVlIGFkZHJlc3MgaWYgcHJlc2VudCB3aXRoIHRoZSBnaXZlbiBzYWx0LCBzbyB0aGUgYWRkcmVzcyBkaXJlY3RseSByZWxpZXMgb24gdGhlIGJhc2UgYWRkcmVzcyBhbmQgZmVlIGFkZHJlc3NcbiAgICAgIGNvbnN0IGNhbGN1bGF0aW9uU2FsdCA9IGV0aFV0aWwuYnVmZmVyVG9IZXgoXG4gICAgICAgIEV0aGVyZXVtQWJpLnNvbGlkaXR5U0hBMyhjcmVhdGVGb3J3YXJkZXJUeXBlcywgY3JlYXRlRm9yd2FyZGVyUGFyYW1zKVxuICAgICAgKTtcbiAgICAgIHR4LmRlcGxveWVkQWRkcmVzcyA9IGNhbGN1bGF0ZUZvcndhcmRlclYxQWRkcmVzcyh0aGlzLl9jb250cmFjdEFkZHJlc3MsIGNhbGN1bGF0aW9uU2FsdCwgdGhpcy5faW5pdENvZGUpO1xuICAgIH1cbiAgICByZXR1cm4gdHg7XG4gIH1cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIGZsdXNoIG1ldGhvZHNcbiAgLyoqXG4gICAqIFNldCB0aGUgZm9yd2FyZGVyIGFkZHJlc3MgdG8gZmx1c2hcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgVGhlIGFkZHJlc3MgdG8gZmx1c2hcbiAgICovXG4gIGZvcndhcmRlckFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFpc1ZhbGlkRXRoQWRkcmVzcyhhZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBhZGRyZXNzOiAnICsgYWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX2ZvcndhcmRlckFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgYWRkcmVzcyBvZiB0aGUgRVJDMjAgdG9rZW4gY29udHJhY3QgdGhhdCB3ZSBhcmUgZmx1c2hpbmcgdG9rZW5zIGZvclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyB0aGUgY29udHJhY3QgYWRkcmVzcyBvZiB0aGUgdG9rZW4gdG8gZmx1c2hcbiAgICovXG4gIHRva2VuQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fdG9rZW5BZGRyZXNzID0gYWRkcmVzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zYWN0aW9uIHRvIGZsdXNoIHRva2VucyBmcm9tIGEgZm9yd2FyZGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEZsdXNoVG9rZW5zVHJhbnNhY3Rpb24oKTogVHhEYXRhIHtcbiAgICBpZiAodGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA+PSA0ICYmIHRoaXMuX2NvbnRyYWN0QWRkcmVzcyAhPT0gdGhpcy5fZm9yd2FyZGVyQWRkcmVzcykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBjb250cmFjdCBhZGRyZXNzOiAnICsgdGhpcy5fY29udHJhY3RBZGRyZXNzKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRCYXNlKGZsdXNoVG9rZW5zRGF0YSh0aGlzLl9mb3J3YXJkZXJBZGRyZXNzLCB0aGlzLl90b2tlbkFkZHJlc3MsIHRoaXMuX2ZvcndhcmRlclZlcnNpb24pKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zYWN0aW9uIHRvIGZsdXNoIHRva2VucyBmcm9tIGEgZm9yd2FyZGVyLlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEZsdXNoQ29pbnNUcmFuc2FjdGlvbigpOiBUeERhdGEge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQmFzZShmbHVzaENvaW5zRGF0YSgpKTtcbiAgfVxuICAvLyBlbmRyZWdpb25cblxuICAvLyByZWdpb24gZ2VuZXJpYyBjb250cmFjdCBjYWxsXG4gIGRhdGEoZW5jb2RlZENhbGw6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHN1cHBvcnRlZFRyYW5zYWN0aW9uVHlwZXMgPSBbVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCwgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudF07XG4gICAgaWYgKCFzdXBwb3J0ZWRUcmFuc2FjdGlvblR5cGVzLmluY2x1ZGVzKHRoaXMuX3R5cGUpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdkYXRhIGNhbiBvbmx5IGJlIHNldCBmb3IgY29udHJhY3QgY2FsbCB0cmFuc2FjdGlvbiB0eXBlcycpO1xuICAgIH1cbiAgICB0aGlzLl9kYXRhID0gZW5jb2RlZENhbGw7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkR2VuZXJpY0NvbnRyYWN0Q2FsbFRyYW5zYWN0aW9uKCk6IFR4RGF0YSB7XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRCYXNlKHRoaXMuX2RhdGEpO1xuICB9XG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZ2V0IHRyYW5zYWN0aW9uKCk6IFRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIHNldCB0cmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbiA9IHRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZmluYWwgdiB2YWx1ZS4gRmluYWwgdiBpcyBkZXNjcmliZWQgaW4gRUlQLTE1NS5cbiAgICpcbiAgICogQHByb3RlY3RlZCBmb3IgaW50ZXJuYWwgdXNlIHdoZW4gdGhlIGVuYWJsZUZpbmFsVkZpZWxkIGZsYWcgaXMgdHJ1ZS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRGaW5hbFYoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gZXRoVXRpbC5hZGRIZXhQcmVmaXgodGhpcy5fY29tbW9uLmNoYWluSWRCTigpLm11bG4oMikuYWRkbigzNSkudG9TdHJpbmcoMTYpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGZvcndhcmRlciB2ZXJzaW9uIGZvciBhZGRyZXNzIHRvIGJlIGluaXRpYWxpemVkXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB2ZXJzaW9uIGZvcndhcmRlciB2ZXJzaW9uXG4gICAqL1xuICBmb3J3YXJkZXJWZXJzaW9uKHZlcnNpb246IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh2ZXJzaW9uIDwgMCB8fCB2ZXJzaW9uID4gNCB8fCB2ZXJzaW9uID09PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIGZvcndhcmRlciB2ZXJzaW9uOiAke3ZlcnNpb259YCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA9IHZlcnNpb247XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBzYWx0IHRvIGNyZWF0ZSB0aGUgYWRkcmVzcyB1c2luZyBjcmVhdGUyXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzYWx0IFRoZSBzYWx0IHRvIGNyZWF0ZSB0aGUgYWRkcmVzcyB1c2luZyBjcmVhdGUyLCBoZXggc3RyaW5nXG4gICAqL1xuICBzYWx0KHNhbHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX3NhbHQgPSBzYWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2UgdGhlIGltcGxlbWVudGF0aW9uIGFkZHJlc3MgZm9yIHRoZSBwcm94eSBjb250cmFjdCwgYW5kIGdldCB0aGUgYmluYXJ5IGluaXRjb2RlIGZvciB0aGUgYXNzb2NpYXRlZCBwcm94eVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaW1wbGVtZW50YXRpb25BZGRyZXNzIFRoZSBhZGRyZXNzIG9mIHRoZSBpbXBsZW1lbnRhdGlvbiBjb250cmFjdFxuICAgKi9cbiAgaW5pdENvZGUoaW1wbGVtZW50YXRpb25BZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGltcGxlbWVudGF0aW9uQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIGltcGxlbWVudGF0aW9uQWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX2luaXRDb2RlID0gZ2V0UHJveHlJbml0Y29kZShpbXBsZW1lbnRhdGlvbkFkZHJlc3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgd2FsbGV0IHZlcnNpb24gZm9yIHdhbGxldCB0byBiZSBpbml0aWFsaXplZFxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gdmVyc2lvbiB3YWxsZXQgdmVyc2lvblxuICAgKi9cbiAgd2FsbGV0VmVyc2lvbih2ZXJzaW9uOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmVyc2lvbiA8IDAgfHwgdmVyc2lvbiA+IDQgfHwgdmVyc2lvbiA9PT0gMykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB3YWxsZXQgdmVyc2lvbjogJHt2ZXJzaW9ufWApO1xuICAgIH1cblxuICAgIHRoaXMuX3dhbGxldFZlcnNpb24gPSB2ZXJzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgYmFzZSBhZGRyZXNzIG9mIHRoZSB3YWxsZXRcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgVGhlIHdhbGxldCBjb250cmFjdCBhZGRyZXNzXG4gICAqL1xuICBiYXNlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fYmFzZUFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZmVlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyBUaGUgZmVlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldFxuICAgKi9cbiAgZmVlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fZmVlQWRkcmVzcyA9IGFkZHJlc3M7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSB3YWxsZXQgdmVyc2lvbiBmb3Igd2FsbGV0XG4gICAqL1xuICBwdWJsaWMgZ2V0V2FsbGV0VmVyc2lvbigpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl93YWxsZXRWZXJzaW9uO1xuICB9XG59XG4iXX0=

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


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