UNPKG

metaapi.cloud-sdk

Version:

SDK for MetaApi, a professional cloud forex API which includes MetaTrader REST API and MetaTrader websocket API. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). CopyFactory copy trading API included. (https://metaapi.cloud)

665 lines 91.2 kB
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "default", {
    enumerable: true,
    get: function() {
        return MetatraderAccountClient;
    }
});
const _metaApiclient = /*#__PURE__*/ _interop_require_default(require("../metaApi.client"));
const _randomstring = /*#__PURE__*/ _interop_require_default(require("randomstring"));
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
let MetatraderAccountClient = class MetatraderAccountClient extends _metaApiclient.default {
    /**
   * Metatrader account replica model
   * @typedef {Object} MetatraderAccountReplicaDto
   * @property {string} _id Unique account replica id
   * @property {State} state Current account replica state
   * @property {number} magic Magic value the trades should be performed using
   * @property {ConnectionStatus} connectionStatus Connection status of the MetaTrader terminal to the application
   * @property {string} quoteStreamingIntervalInSeconds Quote streaming interval in seconds. Set to 0 in order to 
   * receive quotes on each tick. Intervals less than 2.5 seconds are supported only for G2
   * @property {string} [symbol] Any symbol provided by broker (required for G1 only)
   * @property {Reliability} reliability Used to increase the reliability of the account replica. High is a recommended value
   * for production environment
   * @property {Array<string>} tags User-defined account replica tags
   * @property {Object} [metadata] Extra information which can be stored together with your account replica. 
   * Total length of this field after serializing it to JSON is limited to 1024 characters
   * @property {number} resourceSlots Number of resource slots to allocate to account replica. Allocating extra resource slots
   * results in better account performance under load which is useful for some applications. E.g. if you have many
   * accounts copying the same strategy via CooyFactory API, then you can increase resourceSlots to get a lower trade
   * copying latency. Please note that allocating extra resource slots is a paid option. Please note that high
   * reliability accounts use redundant infrastructure, so that each resource slot for a high reliability account
   * is billed as 2 standard resource slots.
   * @property {number} copyFactoryResourceSlots Number of CopyFactory 2 resource slots to allocate to account replica.
   * Allocating extra resource slots results in lower trade copying latency. Please note that allocating extra resource
   * slots is a paid option. Please also note that CopyFactory 2 uses redundant infrastructure so that
   * each CopyFactory resource slot is billed as 2 standard resource slots. You will be billed for CopyFactory 2
   * resource slots only if you have added your account to CopyFactory 2 by specifying copyFactoryRoles field.
   * @property {string} region Region id to deploy account replica at. One of returned by the /users/current/regions endpoint
   * @property {string} createdAt The time account replica was created at, in ISO format
   * @property {MetatraderAccountDto} primaryAccount Primary account
   */ /**
   * MetaTrader account model
   * @typedef {Object} MetatraderAccountDto
   * @property {string} _id Unique account id
   * @property {State} state Current account state
   * @property {number} magic Magic value the trades should be performed using
   * @property {ConnectionStatus} connectionStatus Connection status of the MetaTrader terminal to the application
   * @property {string} quoteStreamingIntervalInSeconds Quote streaming interval in seconds. Set to 0 in order to 
   * receive quotes on each tick. Intervals less than 2.5 seconds are supported only for G2
   * @property {string} [symbol] Any symbol provided by broker (required for G1 only)
   * @property {Reliability} reliability Used to increase the reliability of the account. High is a recommended value
   * for production environment
   * @property {Array<string>} tags User-defined account tags
   * @property {Object} [metadata] Extra information which can be stored together with your account. 
   * Total length of this field after serializing it to JSON is limited to 1024 characters
   * @property {number} resourceSlots Number of resource slots to allocate to account. Allocating extra resource slots
   * results in better account performance under load which is useful for some applications. E.g. if you have many
   * accounts copying the same strategy via CooyFactory API, then you can increase resourceSlots to get a lower trade
   * copying latency. Please note that allocating extra resource slots is a paid option. Please note that high
   * reliability accounts use redundant infrastructure, so that each resource slot for a high reliability account
   * is billed as 2 standard resource slots.
   * @property {number} copyFactoryResourceSlots Number of CopyFactory 2 resource slots to allocate to account.
   * Allocating extra resource slots results in lower trade copying latency. Please note that allocating extra resource
   * slots is a paid option. Please also note that CopyFactory 2 uses redundant infrastructure so that
   * each CopyFactory resource slot is billed as 2 standard resource slots. You will be billed for CopyFactory 2
   * resource slots only if you have added your account to CopyFactory 2 by specifying copyFactoryRoles field.
   * @property {string} region Region id to deploy account at. One of returned by the /users/current/regions endpoint
   * @property {string} createdAt The time account was created at, in ISO format
   * @property {string} name Human-readable account name
   * @property {boolean} manualTrades Flag indicating if trades should be placed as manual trades. Supported on G2 only
   * @property {number} [slippage] Default trade slippage in points. Should be greater or equal to zero. If not
   * specified, system internal setting will be used which we believe is reasonable for most cases
   * @property {string} [provisioningProfileId] Id of the provisioning profile that was used as the basis for 
   * creating this account
   * @property {string} [login] MetaTrader account login
   * @property {string} server MetaTrader server name to connect to 
   * @property {Type} type Account type. Executing accounts as cloud-g2 is faster and cheaper
   * @property {Version} version MetaTrader version
   * @property {number} hash Hash-code of the account
   * @property {string} baseCurrency 3-character ISO currency code of the account base currency.
   * The setting is to be used for copy trading accounts which use national currencies only, such as some Brazilian
   * brokers. You should not alter this setting unless you understand what you are doing.
   * @property {Array<CopyFactoryRoles>} copyFactoryRoles Account roles for CopyFactory2 application
   * @property {boolean} riskManagementApiEnabled Flag indicating that risk management API is enabled on
   * account
   * @property {boolean} metastatsApiEnabled Flag indicating that MetaStats API is enabled on account
   * @property {Array<AccountConnection>} connections Active account connections
   * @property {boolean} primaryReplica Flag indicating that account is primary
   * @property {string} userId User id
   * @property {string} [primaryAccountId] Primary account id. Only replicas can have this field
   * @property {Array<MetatraderAccountReplicaDto>} accountReplicas MetaTrader account replicas
   */ /**
   * MetaTrader account list model
   * @typedef {Object} MetatraderAccountListDto
   * @property {number} count MetaTrader accounts count
   * @property {Array<MetatraderAccountDto>} items MetaTrader accounts list
   */ /**
   * Account connection
   * @typedef {Object} AccountConnection
   * @property {string} region Region the account is connected at
   * @property {string} zone Availability zone the account is connected at
   * @property {string} application Application the account is connected to, one of `MetaApi`, `CopyFactory subscriber`,
   * `CopyFactory provider`, `CopyFactory history import`, `Risk management`
   */ /**
   * MT version
   * @typedef {4 | 5} Version
   */ /**
   * MT platform
   * @typedef {'mt4' | 'mt5'} Platform
   */ /**
   * Account type
   * @typedef {'cloud-g1' | 'cloud-g2'} Type
   */ /**
   * Account state
   * @typedef {'CREATED' | 'DEPLOYING' | 'DEPLOYED' | 'DEPLOY_FAILED' | 'UNDEPLOYING' | 'UNDEPLOYED' |
   * 'UNDEPLOY_FAILED' | 'DELETING' | 'DELETE_FAILED' | 'REDEPLOY_FAILED' | 'DRAFT'} State
   */ /**
   * Account connection status
   * @typedef {'CONNECTED' | 'DISCONNECTED' | 'DISCONNECTED_FROM_BROKER'} ConnectionStatus
   */ /**
   * Account reliability
   * @typedef {'high' | 'regular'} Reliability
   */ /**
   * CopyFactory roles
   * @typedef {'SUBSCRIBER' | 'PROVIDER'} CopyFactoryRoles
   */ /**
   * Sort order
   * @typedef {'asc' | 'desc'} SortOrder
   */ /**
   * Get accounts api version
   * @typedef {'1' | '2'} GetAccountsApiVersion
   */ /**
   * @typedef {Object} AccountsFilter
   * @property {number} [offset] Search offset (defaults to 0) (must be greater or equal to 0)
   * @property {number} [limit] Search limit (defaults to 1000) 
   * (must be greater or equal to 1 and less or equal to 1000)
   * @property {Array<Version> | Version} [version] MT version
   * @property {Array<Type> | Type} [type] Account type
   * @property {Array<State> | State} [state] Account state
   * @property {Array<ConnectionStatus> | ConnectionStatus} [connectionStatus] Connection status
   * @property {string} [query] Searches over _id, name, server and login to match query
   * @property {string} [provisioningProfileId] Provisioning profile id
   * @property {SortOrder} [sortOrder] Sort order for stateChangedAt field, default is no order
   * @property {Array<string> | string} [region] Available region
   * @property {Array<CopyFactoryRoles> | CopyFactoryRoles} [copyFactoryRoles] Account roles for CopyFactory2 API
   */ /**
   * Returns trading accounts belonging to the current user (see https://metaapi.cloud/docs/provisioning/api/account/readAccounts/)
   * Method is accessible only with API access token
   * @param {AccountsFilter} [accountsFilter] optional filter
   * @param {GetAccountsApiVersion} [apiVersion] api version to use
   * @return {Promise<Array<MetatraderAccountDto> | MetatraderAccountListDto>} promise resolving with MetaTrader accounts found
   */ getAccounts(accountsFilter = {}, apiVersion) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("getAccounts");
        }
        const opts = {
            url: `${this._host}/users/current/accounts`,
            method: "GET",
            params: accountsFilter,
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        if (apiVersion) {
            opts.headers["api-version"] = apiVersion;
        }
        return this._httpClient.request(opts, "getAccounts");
    }
    /**
   * Returns trading account by id (see https://metaapi.cloud/docs/provisioning/api/account/readAccount/)
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise<MetatraderAccountDto>} promise resolving with MetaTrader account found
   */ getAccount(id) {
        const opts = {
            url: `${this._host}/users/current/accounts/${id}`,
            method: "GET",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "getAccount");
    }
    /**
   * Returns trading account replica by trading account id and replica id (see 
   * https://metaapi.cloud/docs/provisioning/api/accountReplica/readAccountReplica/)
   * Method is accessible only with API access token
   * @param {string} accountId MetaTrader primary account id
   * @param {string} replicaId MetaTrader account replica id
   * @return {Promise<MetatraderAccountReplicaDto>} promise resolving with MetaTrader account replica found
   */ getAccountReplica(accountId, replicaId) {
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas/${replicaId}`,
            method: "GET",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "getAccountReplica");
    }
    /**
   * Returns replicas for a trading account (see 
   * https://metaapi.cloud/docs/provisioning/api/accountReplica/readAccountReplicas/)
   * Method is accessible only with API access token
   * @param {string} accountId Primary account id
   * @return {Promise<Array<MetatraderAccountReplicaDto>>} promise resolving with MetaTrader account replicas found
   */ getAccountReplicas(accountId) {
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas`,
            method: "GET",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "getAccountReplicas");
    }
    /**
   * MetaTrader account id model
   * @typedef {Object} MetatraderAccountIdDto
   * @property {string} id MetaTrader account unique identifier
   * @property {string} state State of the account. Possible values are 'UNDEPLOYED', 'DEPLOYED', 'DRAFT'
   */ /**
   * Adds a trading account and starts a cloud API server for the trading account (see 
   * https://metaapi.cloud/docs/provisioning/api/account/createAccount/).
   * It can take some time for the API server and trading terminal to start and connect to broker.
   * You can use the `connectionStatus` replica field to monitor the current status of the trading account.
   * Method is accessible only with API access token
   * @param {NewMetatraderAccountDto} account MetaTrader account data
   * @return {Promise<MetatraderAccountIdDto>} promise resolving with an id and state of the MetaTrader account created
   */ createAccount(account) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("createAccount");
        }
        const opts = {
            url: `${this._host}/users/current/accounts`,
            method: "POST",
            headers: {
                "auth-token": this._token,
                "transaction-id": _randomstring.default.generate(32)
            },
            json: true,
            data: account
        };
        return this._httpClient.request(opts, "createAccount");
    }
    /**
   * New MetaTrader account replica model
   * @typedef {Object} NewMetaTraderAccountReplicaDto
   * @property {string} [symbol] Any MetaTrader symbol your broker provides historical market data for. 
   * This value should be specified for G1 accounts only and only in case your MT account fails to connect to broker.
   * @property {number} magic Magic value the trades should be performed using.
   * When manualTrades field is set to true, magic value must be 0
   * @property {string} [quoteStreamingIntervalInSeconds] Quote streaming interval in seconds. Set to 0 in order to 
   * receive quotes on each tick. Default value is 2.5 seconds. Intervals less than 2.5 seconds are supported only for G2
   * @property {Array<string>} [tags] User-defined account replica tags
   * @property {Object} [metadata] Extra information which can be stored together with your account replica. 
   * Total length of this field after serializing it to JSON is limited to 1024 characters
   * @property {Reliability} [reliability] Used to increase the reliability of the account replica. High is a recommended value 
   * for production environment. Default value is high
   * @property {number} [resourceSlots] Number of resource slots to allocate to account replica. Allocating extra resource slots
   * results in better account performance under load which is useful for some applications. E.g. if you have many
   * accounts copying the same strategy via CooyFactory API, then you can increase resourceSlots to get a lower trade
   * copying latency. Please note that allocating extra resource slots is a paid option. Please note that high
   * reliability accounts use redundant infrastructure, so that each resource slot for a high reliability account
   * is billed as 2 standard resource slots. Default is 1.
   * @property {number} [copyFactoryResourceSlots] Number of CopyFactory 2 resource slots to allocate to account replica.
   * Allocating extra resource slots results in lower trade copying latency. Please note that allocating extra resource
   * slots is a paid option. Please also note that CopyFactory 2 uses redundant infrastructure so that
   * each CopyFactory resource slot is billed as 2 standard resource slots. You will be billed for CopyFactory 2
   * resource slots only if you have added your account to CopyFactory 2 by specifying copyFactoryRoles field.
   * Default is 1.
   * @property {string} region Region id to deploy account replica at. One of returned by the /users/current/regions endpoint
   */ /**
   * Creates a trading account replica in a region different from trading account region and starts a cloud API server for it
   * (see https://metaapi.cloud/docs/provisioning/api/accountReplica/createAccountReplica/).
   * It can take some time for the API server and trading terminal to start and connect to broker.
   * You can use the `connectionStatus` replica field to monitor the current status of the replica.
   * Method is accessible only with API access token
   * @param {string} accountId primary account id
   * @param {NewMetaTraderAccountReplicaDto} account MetaTrader account data
   * @return {Promise<MetatraderAccountIdDto>} promise resolving with an id and state of the MetaTrader account replica created
   */ createAccountReplica(accountId, account) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("createAccountReplica");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas`,
            method: "POST",
            headers: {
                "auth-token": this._token,
                "transaction-id": _randomstring.default.generate(32)
            },
            json: true,
            data: account
        };
        return this._httpClient.request(opts, "createAccountReplica");
    }
    /**
   * Starts API server and trading terminal for trading account.
   * This request will be ignored if the account is already deployed.
   * (see https://metaapi.cloud/docs/provisioning/api/account/deployAccount/)
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise} promise resolving when MetaTrader account is scheduled for deployment
   */ deployAccount(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("deployAccount");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/deploy`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "deployAccount");
    }
    /**
   * Starts API server and trading terminal for trading account replica.
   * This request will be ignored if the replica is already deployed
   * (see https://metaapi.cloud/docs/provisioning/api/accountReplica/deployAccountReplica/)
   * Method is accessible only with API access token
   * @param {string} accountId MetaTrader account id
   * @param {string} replicaId MetaTrader account replica id
   * @return {Promise} promise resolving when MetaTrader account replica is scheduled for deployment
   */ deployAccountReplica(accountId, replicaId) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("deployAccountReplica");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas/${replicaId}/deploy`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "deployAccountReplica");
    }
    /**
   * Stops API server and trading terminal for trading account.
   * This request will be ignored if trading account is already undeployed
   * (see https://metaapi.cloud/docs/provisioning/api/account/undeployAccount/)
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise} promise resolving when MetaTrader account is scheduled for undeployment
   */ undeployAccount(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("undeployAccount");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/undeploy`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "undeployAccount");
    }
    /**
   * Stops API server and trading terminal for trading account replica.
   * The request will be ignored if trading account replica is already undeployed
   * (see https://metaapi.cloud/docs/provisioning/api/accountReplica/undeployAccountReplica/)
   * Method is accessible only with API access token
   * @param {string} accountId MetaTrader primary account id
   * @param {string} replicaId MetaTrader account replica id
   * @return {Promise} promise resolving when MetaTrader account replica is scheduled for undeployment
   */ undeployAccountReplica(accountId, replicaId) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("undeployAccountReplica");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas/${replicaId}/undeploy`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "undeployAccountReplica");
    }
    /**
   * Redeploys trading account. This is equivalent to undeploy immediately followed by deploy
   * (see https://metaapi.cloud/docs/provisioning/api/account/redeployAccount/)
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise} promise resolving when MetaTrader account is scheduled for redeployment
   */ redeployAccount(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("redeployAccount");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/redeploy`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "redeployAccount");
    }
    /**
   * Redeploys trading account replica. This is equivalent to undeploy immediately followed by deploy.
   * (see https://metaapi.cloud/docs/provisioning/api/account/redeployAccountReplica/)
   * Method is accessible only with API access token
   * @param {string} accountId MetaTrader primary account id
   * @param {string} replicaId MetaTrader account replica id
   * @return {Promise} promise resolving when MetaTrader account replica is scheduled for redeployment
   */ redeployAccountReplica(accountId, replicaId) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("redeployAccountReplica");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas/${replicaId}/redeploy`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "redeployAccountReplica");
    }
    /**
   * Removes a trading account and stops the API server serving the account.
   * The account state such as downloaded market data history will be removed as well when you remove the account.
   * (see https://metaapi.cloud/docs/provisioning/api/account/deleteAccount/).
   * Method is accessible only with API access token
   * @param {string} id Id of the account to be deleted
   * @return {Promise} promise resolving when MetaTrader account is scheduled for deletion
   */ deleteAccount(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("deleteAccount");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}`,
            method: "DELETE",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "deleteAccount");
    }
    /**
   * Removes a trading account replica and stops the API server serving the replica
   * (see https://metaapi.cloud/docs/provisioning/api/account/deleteAccountReplica/).
   * Method is accessible only with API access token
   * @param {string} accountId primary account id
   * @param {string} replicaId Id of the account replica to be deleted
   * @return {Promise} promise resolving when MetaTrader account replica is scheduled for deletion
   */ deleteAccountReplica(accountId, replicaId) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("deleteAccountReplica");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas/${replicaId}`,
            method: "DELETE",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "deleteAccountReplica");
    }
    /**
   * Updates trading account. 
   * Please redeploy the trading account in order for updated settings to take effect
   * (see https://metaapi.cloud/docs/provisioning/api/account/updateAccount/).
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @param {MetatraderAccountUpdateDto} account updated account information
   * @return {Promise} promise resolving when MetaTrader account is updated
   */ updateAccount(id, account) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("updateAccount");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}`,
            method: "PUT",
            headers: {
                "auth-token": this._token
            },
            json: true,
            data: account
        };
        return this._httpClient.request(opts, "updateAccount");
    }
    /**
   * Updated MetaTrader account replica data
   * @typedef {Object} UpdatedMetatraderAccountReplicaDto
   * @property {number} [magic] Magic value the trades should be performed using.
   * When manualTrades field is set to true, magic value must be 0
   * @property {number} [quoteStreamingIntervalInSeconds] Quote streaming interval in seconds. Set to 0 in order to
   * receive quotes on each tick. Default value is 2.5 seconds. Intervals less than 2.5 seconds are supported
   * only for G2
   * @property {Array<string>} [tags] MetaTrader account tags
   * @property {Object} [metadata] extra information which can be stored together with your account
   * @property {number} [resourceSlots] Number of resource slots to allocate to account. Allocating extra resource slots
   * results in better account performance under load which is useful for some applications. E.g. if you have many
   * accounts copying the same strategy via CooyFactory API, then you can increase resourceSlots to get a lower trade
   * copying latency. Please note that allocating extra resource slots is a paid option. Default is 1
   * @property {number} [copyFactoryResourceSlots] Number of CopyFactory 2 resource slots to allocate to account.
   * Allocating extra resource slots results in lower trade copying latency. Please note that allocating extra resource
   * slots is a paid option. Please also note that CopyFactory 2 uses redundant infrastructure so that
   * each CopyFactory resource slot is billed as 2 standard resource slots. You will be billed for CopyFactory 2
   * resource slots only if you have added your account to CopyFactory 2 by specifying copyFactoryRoles field.
   * Default is 1.
   */ /**
   * Updates trading account replica (see
   * https://metaapi.cloud/docs/provisioning/api/account/updateAccountReplica/).
   * Method is accessible only with API access token
   * @param {string} accountId MetaTrader primary account id
   * @param {string} replicaId MetaTrader account replica id
   * @param {UpdatedMetatraderAccountReplicaDto} metatraderAccount updated account replica information
   * @return {Promise} promise resolving when MetaTrader account replica is updated
   */ updateAccountReplica(accountId, replicaId, metatraderAccount) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("updateAccountReplica");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/replicas/${replicaId}`,
            method: "PUT",
            headers: {
                "auth-token": this._token
            },
            json: true,
            data: metatraderAccount
        };
        return this._httpClient.request(opts, "updateAccountReplica");
    }
    /**
   * Increases trading account reliability in order to increase the expected account uptime.
   * The account will be temporary stopped to perform this action.
   * Note that increasing reliability is a paid option (see
   * https://metaapi.cloud/docs/provisioning/api/account/increaseReliability/).
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise} promise resolving when MetaTrader account reliability is increased
   */ increaseReliability(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("increaseReliability");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/increase-reliability`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "increaseReliability");
    }
    /**
   * Enables risk management API for trading account.
   * The account will be temporary stopped to perform this action.
   * Note that risk management API is a paid option (see
   * https://metaapi.cloud/docs/provisioning/api/account/enableRiskManagementApi/).
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise} promise resolving when account risk management is enabled
   */ enableRiskManagementApi(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("enableRiskManagementApi");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/enable-risk-management-api`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "enableRiskManagementApi");
    }
    /**
   * Enables copy factory API for trading account.
   * The account will be temporary stopped to perform this action.
   * Note that copy factory API is a paid option (see
   * https://metaapi.cloud/docs/provisioning/api/account/enableCopyFactoryApi/).
   * @param {string} id MetaTrader account id
   * @param {Array<CopyFactoryRoles>} copyFactoryRoles Copy factory roles
   * @param {number} copyFactoryResourceSlots Copy factory resource slots
   * @return {Promise} promise resolving when account copy factory is enabled
   */ enableCopyFactoryApi(id, copyFactoryRoles, copyFactoryResourceSlots) {
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/enable-copy-factory-api`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true,
            data: {
                copyFactoryRoles,
                copyFactoryResourceSlots
            }
        };
        return this._httpClient.request(opts, "enableCopyFactoryApi");
    }
    /**
   * Enables MetaStats API for trading account.
   * The account will be temporary stopped to perform this action.
   * Note that this is a paid option (see
   * https://metaapi.cloud/docs/provisioning/api/account/enableMetaStatsApi/).
   * Method is accessible only with API access token
   * @param {string} id MetaTrader account id
   * @return {Promise} promise resolving when account MetaStats API is enabled
   */ enableMetaStatsApi(id) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("enableMetaStatsApi");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${id}/enable-metastats-api`,
            method: "POST",
            headers: {
                "auth-token": this._token
            },
            json: true
        };
        return this._httpClient.request(opts, "enableMetaStatsApi");
    }
    /**
   * Configuration link
   * @typedef {Object} ConfigurationLink
   * @property {string} configurationLink Secure link to allow end user to configure account directly
   */ /**
   * Generates trading account configuration link by account id.
   * (see https://metaapi.cloud/docs/provisioning/api/account/createConfigurationLink/)
   * This link can be used by the end user to enter trading account login and password or change the password.
   * Method is accessible only with API access token
   * @param {string} accountId Trading account id
   * @param {number} [ttlInDays] Lifetime of the link in days. Default is 7.
   * @return {Promise<ConfigurationLink>} promise resolving with configuration link
   */ createConfigurationLink(accountId, ttlInDays) {
        if (this._isNotJwtToken()) {
            return this._handleNoAccessError("createConfigurationLink");
        }
        const opts = {
            url: `${this._host}/users/current/accounts/${accountId}/configuration-link`,
            method: "PUT",
            headers: {
                "auth-token": this._token
            },
            params: {
                ttlInDays: ttlInDays
            },
            json: true
        };
        return this._httpClient.request(opts, "createConfigurationLink");
    }
};

//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7TmV3TWV0YXRyYWRlckFjY291bnREdG8sIE1ldGF0cmFkZXJBY2NvdW50VXBkYXRlRHRvfSBmcm9tICcuL21ldGF0cmFkZXJBY2NvdW50LmNsaWVudCc7XG5pbXBvcnQgTWV0YUFwaUNsaWVudCBmcm9tICcuLi9tZXRhQXBpLmNsaWVudCc7XG5pbXBvcnQgcmFuZG9tc3RyaW5nIGZyb20gJ3JhbmRvbXN0cmluZyc7XG5cbi8qKlxuICogbWV0YWFwaS5jbG91ZCBNZXRhVHJhZGVyIGFjY291bnQgQVBJIGNsaWVudCAoc2VlIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Byb3Zpc2lvbmluZy8pXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1ldGF0cmFkZXJBY2NvdW50Q2xpZW50IGV4dGVuZHMgTWV0YUFwaUNsaWVudCB7XG5cbiAgLyoqXG4gICAqIE1ldGF0cmFkZXIgYWNjb3VudCByZXBsaWNhIG1vZGVsXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IE1ldGF0cmFkZXJBY2NvdW50UmVwbGljYUR0b1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gX2lkIFVuaXF1ZSBhY2NvdW50IHJlcGxpY2EgaWRcbiAgICogQHByb3BlcnR5IHtTdGF0ZX0gc3RhdGUgQ3VycmVudCBhY2NvdW50IHJlcGxpY2Egc3RhdGVcbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IG1hZ2ljIE1hZ2ljIHZhbHVlIHRoZSB0cmFkZXMgc2hvdWxkIGJlIHBlcmZvcm1lZCB1c2luZ1xuICAgKiBAcHJvcGVydHkge0Nvbm5lY3Rpb25TdGF0dXN9IGNvbm5lY3Rpb25TdGF0dXMgQ29ubmVjdGlvbiBzdGF0dXMgb2YgdGhlIE1ldGFUcmFkZXIgdGVybWluYWwgdG8gdGhlIGFwcGxpY2F0aW9uXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBxdW90ZVN0cmVhbWluZ0ludGVydmFsSW5TZWNvbmRzIFF1b3RlIHN0cmVhbWluZyBpbnRlcnZhbCBpbiBzZWNvbmRzLiBTZXQgdG8gMCBpbiBvcmRlciB0byBcbiAgICogcmVjZWl2ZSBxdW90ZXMgb24gZWFjaCB0aWNrLiBJbnRlcnZhbHMgbGVzcyB0aGFuIDIuNSBzZWNvbmRzIGFyZSBzdXBwb3J0ZWQgb25seSBmb3IgRzJcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IFtzeW1ib2xdIEFueSBzeW1ib2wgcHJvdmlkZWQgYnkgYnJva2VyIChyZXF1aXJlZCBmb3IgRzEgb25seSlcbiAgICogQHByb3BlcnR5IHtSZWxpYWJpbGl0eX0gcmVsaWFiaWxpdHkgVXNlZCB0byBpbmNyZWFzZSB0aGUgcmVsaWFiaWxpdHkgb2YgdGhlIGFjY291bnQgcmVwbGljYS4gSGlnaCBpcyBhIHJlY29tbWVuZGVkIHZhbHVlXG4gICAqIGZvciBwcm9kdWN0aW9uIGVudmlyb25tZW50XG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8c3RyaW5nPn0gdGFncyBVc2VyLWRlZmluZWQgYWNjb3VudCByZXBsaWNhIHRhZ3NcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IFttZXRhZGF0YV0gRXh0cmEgaW5mb3JtYXRpb24gd2hpY2ggY2FuIGJlIHN0b3JlZCB0b2dldGhlciB3aXRoIHlvdXIgYWNjb3VudCByZXBsaWNhLiBcbiAgICogVG90YWwgbGVuZ3RoIG9mIHRoaXMgZmllbGQgYWZ0ZXIgc2VyaWFsaXppbmcgaXQgdG8gSlNPTiBpcyBsaW1pdGVkIHRvIDEwMjQgY2hhcmFjdGVyc1xuICAgKiBAcHJvcGVydHkge251bWJlcn0gcmVzb3VyY2VTbG90cyBOdW1iZXIgb2YgcmVzb3VyY2Ugc2xvdHMgdG8gYWxsb2NhdGUgdG8gYWNjb3VudCByZXBsaWNhLiBBbGxvY2F0aW5nIGV4dHJhIHJlc291cmNlIHNsb3RzXG4gICAqIHJlc3VsdHMgaW4gYmV0dGVyIGFjY291bnQgcGVyZm9ybWFuY2UgdW5kZXIgbG9hZCB3aGljaCBpcyB1c2VmdWwgZm9yIHNvbWUgYXBwbGljYXRpb25zLiBFLmcuIGlmIHlvdSBoYXZlIG1hbnlcbiAgICogYWNjb3VudHMgY29weWluZyB0aGUgc2FtZSBzdHJhdGVneSB2aWEgQ29veUZhY3RvcnkgQVBJLCB0aGVuIHlvdSBjYW4gaW5jcmVhc2UgcmVzb3VyY2VTbG90cyB0byBnZXQgYSBsb3dlciB0cmFkZVxuICAgKiBjb3B5aW5nIGxhdGVuY3kuIFBsZWFzZSBub3RlIHRoYXQgYWxsb2NhdGluZyBleHRyYSByZXNvdXJjZSBzbG90cyBpcyBhIHBhaWQgb3B0aW9uLiBQbGVhc2Ugbm90ZSB0aGF0IGhpZ2hcbiAgICogcmVsaWFiaWxpdHkgYWNjb3VudHMgdXNlIHJlZHVuZGFudCBpbmZyYXN0cnVjdHVyZSwgc28gdGhhdCBlYWNoIHJlc291cmNlIHNsb3QgZm9yIGEgaGlnaCByZWxpYWJpbGl0eSBhY2NvdW50XG4gICAqIGlzIGJpbGxlZCBhcyAyIHN0YW5kYXJkIHJlc291cmNlIHNsb3RzLlxuICAgKiBAcHJvcGVydHkge251bWJlcn0gY29weUZhY3RvcnlSZXNvdXJjZVNsb3RzIE51bWJlciBvZiBDb3B5RmFjdG9yeSAyIHJlc291cmNlIHNsb3RzIHRvIGFsbG9jYXRlIHRvIGFjY291bnQgcmVwbGljYS5cbiAgICogQWxsb2NhdGluZyBleHRyYSByZXNvdXJjZSBzbG90cyByZXN1bHRzIGluIGxvd2VyIHRyYWRlIGNvcHlpbmcgbGF0ZW5jeS4gUGxlYXNlIG5vdGUgdGhhdCBhbGxvY2F0aW5nIGV4dHJhIHJlc291cmNlXG4gICAqIHNsb3RzIGlzIGEgcGFpZCBvcHRpb24uIFBsZWFzZSBhbHNvIG5vdGUgdGhhdCBDb3B5RmFjdG9yeSAyIHVzZXMgcmVkdW5kYW50IGluZnJhc3RydWN0dXJlIHNvIHRoYXRcbiAgICogZWFjaCBDb3B5RmFjdG9yeSByZXNvdXJjZSBzbG90IGlzIGJpbGxlZCBhcyAyIHN0YW5kYXJkIHJlc291cmNlIHNsb3RzLiBZb3Ugd2lsbCBiZSBiaWxsZWQgZm9yIENvcHlGYWN0b3J5IDJcbiAgICogcmVzb3VyY2Ugc2xvdHMgb25seSBpZiB5b3UgaGF2ZSBhZGRlZCB5b3VyIGFjY291bnQgdG8gQ29weUZhY3RvcnkgMiBieSBzcGVjaWZ5aW5nIGNvcHlGYWN0b3J5Um9sZXMgZmllbGQuXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSByZWdpb24gUmVnaW9uIGlkIHRvIGRlcGxveSBhY2NvdW50IHJlcGxpY2EgYXQuIE9uZSBvZiByZXR1cm5lZCBieSB0aGUgL3VzZXJzL2N1cnJlbnQvcmVnaW9ucyBlbmRwb2ludFxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gY3JlYXRlZEF0IFRoZSB0aW1lIGFjY291bnQgcmVwbGljYSB3YXMgY3JlYXRlZCBhdCwgaW4gSVNPIGZvcm1hdFxuICAgKiBAcHJvcGVydHkge01ldGF0cmFkZXJBY2NvdW50RHRvfSBwcmltYXJ5QWNjb3VudCBQcmltYXJ5IGFjY291bnRcbiAgICovXG5cbiAgLyoqXG4gICAqIE1ldGFUcmFkZXIgYWNjb3VudCBtb2RlbFxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBNZXRhdHJhZGVyQWNjb3VudER0b1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gX2lkIFVuaXF1ZSBhY2NvdW50IGlkXG4gICAqIEBwcm9wZXJ0eSB7U3RhdGV9IHN0YXRlIEN1cnJlbnQgYWNjb3VudCBzdGF0ZVxuICAgKiBAcHJvcGVydHkge251bWJlcn0gbWFnaWMgTWFnaWMgdmFsdWUgdGhlIHRyYWRlcyBzaG91bGQgYmUgcGVyZm9ybWVkIHVzaW5nXG4gICAqIEBwcm9wZXJ0eSB7Q29ubmVjdGlvblN0YXR1c30gY29ubmVjdGlvblN0YXR1cyBDb25uZWN0aW9uIHN0YXR1cyBvZiB0aGUgTWV0YVRyYWRlciB0ZXJtaW5hbCB0byB0aGUgYXBwbGljYXRpb25cbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHF1b3RlU3RyZWFtaW5nSW50ZXJ2YWxJblNlY29uZHMgUXVvdGUgc3RyZWFtaW5nIGludGVydmFsIGluIHNlY29uZHMuIFNldCB0byAwIGluIG9yZGVyIHRvIFxuICAgKiByZWNlaXZlIHF1b3RlcyBvbiBlYWNoIHRpY2suIEludGVydmFscyBsZXNzIHRoYW4gMi41IHNlY29uZHMgYXJlIHN1cHBvcnRlZCBvbmx5IGZvciBHMlxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gW3N5bWJvbF0gQW55IHN5bWJvbCBwcm92aWRlZCBieSBicm9rZXIgKHJlcXVpcmVkIGZvciBHMSBvbmx5KVxuICAgKiBAcHJvcGVydHkge1JlbGlhYmlsaXR5fSByZWxpYWJpbGl0eSBVc2VkIHRvIGluY3JlYXNlIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgYWNjb3VudC4gSGlnaCBpcyBhIHJlY29tbWVuZGVkIHZhbHVlXG4gICAqIGZvciBwcm9kdWN0aW9uIGVudmlyb25tZW50XG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8c3RyaW5nPn0gdGFncyBVc2VyLWRlZmluZWQgYWNjb3VudCB0YWdzXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBbbWV0YWRhdGFdIEV4dHJhIGluZm9ybWF0aW9uIHdoaWNoIGNhbiBiZSBzdG9yZWQgdG9nZXRoZXIgd2l0aCB5b3VyIGFjY291bnQuIFxuICAgKiBUb3RhbCBsZW5ndGggb2YgdGhpcyBmaWVsZCBhZnRlciBzZXJpYWxpemluZyBpdCB0byBKU09OIGlzIGxpbWl0ZWQgdG8gMTAyNCBjaGFyYWN0ZXJzXG4gICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSByZXNvdXJjZVNsb3RzIE51bWJlciBvZiByZXNvdXJjZSBzbG90cyB0byBhbGxvY2F0ZSB0byBhY2NvdW50LiBBbGxvY2F0aW5nIGV4dHJhIHJlc291cmNlIHNsb3RzXG4gICAqIHJlc3VsdHMgaW4gYmV0dGVyIGFjY291bnQgcGVyZm9ybWFuY2UgdW5kZXIgbG9hZCB3aGljaCBpcyB1c2VmdWwgZm9yIHNvbWUgYXBwbGljYXRpb25zLiBFLmcuIGlmIHlvdSBoYXZlIG1hbnlcbiAgICogYWNjb3VudHMgY29weWluZyB0aGUgc2FtZSBzdHJhdGVneSB2aWEgQ29veUZhY3RvcnkgQVBJLCB0aGVuIHlvdSBjYW4gaW5jcmVhc2UgcmVzb3VyY2VTbG90cyB0byBnZXQgYSBsb3dlciB0cmFkZVxuICAgKiBjb3B5aW5nIGxhdGVuY3kuIFBsZWFzZSBub3RlIHRoYXQgYWxsb2NhdGluZyBleHRyYSByZXNvdXJjZSBzbG90cyBpcyBhIHBhaWQgb3B0aW9uLiBQbGVhc2Ugbm90ZSB0aGF0IGhpZ2hcbiAgICogcmVsaWFiaWxpdHkgYWNjb3VudHMgdXNlIHJlZHVuZGFudCBpbmZyYXN0cnVjdHVyZSwgc28gdGhhdCBlYWNoIHJlc291cmNlIHNsb3QgZm9yIGEgaGlnaCByZWxpYWJpbGl0eSBhY2NvdW50XG4gICAqIGlzIGJpbGxlZCBhcyAyIHN0YW5kYXJkIHJlc291cmNlIHNsb3RzLlxuICAgKiBAcHJvcGVydHkge251bWJlcn0gY29weUZhY3RvcnlSZXNvdXJjZVNsb3RzIE51bWJlciBvZiBDb3B5RmFjdG9yeSAyIHJlc291cmNlIHNsb3RzIHRvIGFsbG9jYXRlIHRvIGFjY291bnQuXG4gICAqIEFsbG9jYXRpbmcgZXh0cmEgcmVzb3VyY2Ugc2xvdHMgcmVzdWx0cyBpbiBsb3dlciB0cmFkZSBjb3B5aW5nIGxhdGVuY3kuIFBsZWFzZSBub3RlIHRoYXQgYWxsb2NhdGluZyBleHRyYSByZXNvdXJjZVxuICAgKiBzbG90cyBpcyBhIHBhaWQgb3B0aW9uLiBQbGVhc2UgYWxzbyBub3RlIHRoYXQgQ29weUZhY3RvcnkgMiB1c2VzIHJlZHVuZGFudCBpbmZyYXN0cnVjdHVyZSBzbyB0aGF0XG4gICAqIGVhY2ggQ29weUZhY3RvcnkgcmVzb3VyY2Ugc2xvdCBpcyBiaWxsZWQgYXMgMiBzdGFuZGFyZCByZXNvdXJjZSBzbG90cy4gWW91IHdpbGwgYmUgYmlsbGVkIGZvciBDb3B5RmFjdG9yeSAyXG4gICAqIHJlc291cmNlIHNsb3RzIG9ubHkgaWYgeW91IGhhdmUgYWRkZWQgeW91ciBhY2NvdW50IHRvIENvcHlGYWN0b3J5IDIgYnkgc3BlY2lmeWluZyBjb3B5RmFjdG9yeVJvbGVzIGZpZWxkLlxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gcmVnaW9uIFJlZ2lvbiBpZCB0byBkZXBsb3kgYWNjb3VudCBhdC4gT25lIG9mIHJldHVybmVkIGJ5IHRoZSAvdXNlcnMvY3VycmVudC9yZWdpb25zIGVuZHBvaW50XG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBjcmVhdGVkQXQgVGhlIHRpbWUgYWNjb3VudCB3YXMgY3JlYXRlZCBhdCwgaW4gSVNPIGZvcm1hdFxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gbmFtZSBIdW1hbi1yZWFkYWJsZSBhY2NvdW50IG5hbWVcbiAgICogQHByb3BlcnR5IHtib29sZWFufSBtYW51YWxUcmFkZXMgRmxhZyBpbmRpY2F0aW5nIGlmIHRyYWRlcyBzaG91bGQgYmUgcGxhY2VkIGFzIG1hbnVhbCB0cmFkZXMuIFN1cHBvcnRlZCBvbiBHMiBvbmx5XG4gICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbc2xpcHBhZ2VdIERlZmF1bHQgdHJhZGUgc2xpcHBhZ2UgaW4gcG9pbnRzLiBTaG91bGQgYmUgZ3JlYXRlciBvciBlcXVhbCB0byB6ZXJvLiBJZiBub3RcbiAgICogc3BlY2lmaWVkLCBzeXN0ZW0gaW50ZXJuYWwgc2V0dGluZyB3aWxsIGJlIHVzZWQgd2hpY2ggd2UgYmVsaWV2ZSBpcyByZWFzb25hYmxlIGZvciBtb3N0IGNhc2VzXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcHJvdmlzaW9uaW5nUHJvZmlsZUlkXSBJZCBvZiB0aGUgcHJvdmlzaW9uaW5nIHByb2ZpbGUgdGhhdCB3YXMgdXNlZCBhcyB0aGUgYmFzaXMgZm9yIFxuICAgKiBjcmVhdGluZyB0aGlzIGFjY291bnRcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IFtsb2dpbl0gTWV0YVRyYWRlciBhY2NvdW50IGxvZ2luXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzZXJ2ZXIgTWV0YVRyYWRlciBzZXJ2ZXIgbmFtZSB0byBjb25uZWN0IHRvIFxuICAgKiBAcHJvcGVydHkge1R5cGV9IHR5cGUgQWNjb3VudCB0eXBlLiBFeGVjdXRpbmcgYWNjb3VudHMgYXMgY2xvdWQtZzIgaXMgZmFzdGVyIGFuZCBjaGVhcGVyXG4gICAqIEBwcm9wZXJ0eSB7VmVyc2lvbn0gdmVyc2lvbiBNZXRhVHJhZGVyIHZlcnNpb25cbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IGhhc2ggSGFzaC1jb2RlIG9mIHRoZSBhY2NvdW50XG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBiYXNlQ3VycmVuY3kgMy1jaGFyYWN0ZXIgSVNPIGN1cnJlbmN5IGNvZGUgb2YgdGhlIGFjY291bnQgYmFzZSBjdXJyZW5jeS5cbiAgICogVGhlIHNldHRpbmcgaXMgdG8gYmUgdXNlZCBmb3IgY29weSB0cmFkaW5nIGFjY291bnRzIHdoaWNoIHVzZSBuYXRpb25hbCBjdXJyZW5jaWVzIG9ubHksIHN1Y2ggYXMgc29tZSBCcmF6aWxpYW5cbiAgICogYnJva2Vycy4gWW91IHNob3VsZCBub3QgYWx0ZXIgdGhpcyBzZXR0aW5nIHVubGVzcyB5b3UgdW5kZXJzdGFuZCB3aGF0IHlvdSBhcmUgZG9pbmcuXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8Q29weUZhY3RvcnlSb2xlcz59IGNvcHlGYWN0b3J5Um9sZXMgQWNjb3VudCByb2xlcyBmb3IgQ29weUZhY3RvcnkyIGFwcGxpY2F0aW9uXG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gcmlza01hbmFnZW1lbnRBcGlFbmFibGVkIEZsYWcgaW5kaWNhdGluZyB0aGF0IHJpc2sgbWFuYWdlbWVudCBBUEkgaXMgZW5hYmxlZCBvblxuICAgKiBhY2NvdW50XG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gbWV0YXN0YXRzQXBpRW5hYmxlZCBGbGFnIGluZGljYXRpbmcgdGhhdCBNZXRhU3RhdHMgQVBJIGlzIGVuYWJsZWQgb24gYWNjb3VudFxuICAgKiBAcHJvcGVydHkge0FycmF5PEFjY291bnRDb25uZWN0aW9uPn0gY29ubmVjdGlvbnMgQWN0aXZlIGFjY291bnQgY29ubmVjdGlvbnNcbiAgICogQHByb3BlcnR5IHtib29sZWFufSBwcmltYXJ5UmVwbGljYSBGbGFnIGluZGljYXRpbmcgdGhhdCBhY2NvdW50IGlzIHByaW1hcnlcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHVzZXJJZCBVc2VyIGlkXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcHJpbWFyeUFjY291bnRJZF0gUHJpbWFyeSBhY2NvdW50IGlkLiBPbmx5IHJlcGxpY2FzIGNhbiBoYXZlIHRoaXMgZmllbGRcbiAgICogQHByb3BlcnR5IHtBcnJheTxNZXRhdHJhZGVyQWNjb3VudFJlcGxpY2FEdG8+fSBhY2NvdW50UmVwbGljYXMgTWV0YVRyYWRlciBhY2NvdW50IHJlcGxpY2FzXG4gICAqL1xuXG5cbiAgLyoqXG4gICAqIE1ldGFUcmFkZXIgYWNjb3VudCBsaXN0IG1vZGVsXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IE1ldGF0cmFkZXJBY2NvdW50TGlzdER0b1xuICAgKiBAcHJvcGVydHkge251bWJlcn0gY291bnQgTWV0YVRyYWRlciBhY2NvdW50cyBjb3VudFxuICAgKiBAcHJvcGVydHkge0FycmF5PE1ldGF0cmFkZXJBY2NvdW50RHRvPn0gaXRlbXMgTWV0YVRyYWRlciBhY2NvdW50cyBsaXN0XG4gICAqL1xuXG4gIC8qKlxuICAgKiBBY2NvdW50IGNvbm5lY3Rpb25cbiAgICogQHR5cGVkZWYge09iamVjdH0gQWNjb3VudENvbm5lY3Rpb25cbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHJlZ2lvbiBSZWdpb24gdGhlIGFjY291bnQgaXMgY29ubmVjdGVkIGF0XG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB6b25lIEF2YWlsYWJpbGl0eSB6b25lIHRoZSBhY2NvdW50IGlzIGNvbm5lY3RlZCBhdFxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gYXBwbGljYXRpb24gQXBwbGljYXRpb24gdGhlIGFjY291bnQgaXMgY29ubmVjdGVkIHRvLCBvbmUgb2YgYE1ldGFBcGlgLCBgQ29weUZhY3Rvcnkgc3Vic2NyaWJlcmAsXG4gICAqIGBDb3B5RmFjdG9yeSBwcm92aWRlcmAsIGBDb3B5RmFjdG9yeSBoaXN0b3J5IGltcG9ydGAsIGBSaXNrIG1hbmFnZW1lbnRgXG4gICAqL1xuXG4gIC8qKlxuICAgKiBNVCB2ZXJzaW9uXG4gICAqIEB0eXBlZGVmIHs0IHwgNX0gVmVyc2lvblxuICAgKi9cblxuICAvKipcbiAgICogTVQgcGxhdGZvcm1cbiAgICogQHR5cGVkZWYgeydtdDQnIHwgJ210NSd9IFBsYXRmb3JtXG4gICAqL1xuXG4gIC8qKlxuICAgKiBBY2NvdW50IHR5cGVcbiAgICogQHR5cGVkZWYgeydjbG91ZC1nMScgfCAnY2xvdWQtZzInfSBUeXBlXG4gICAqL1xuXG4gIC8qKlxuICAgKiBBY2NvdW50IHN0YXRlXG4gICAqIEB0eXBlZGVmIHsnQ1JFQVRFRCcgfCAnREVQTE9ZSU5HJyB8ICdERVBMT1lFRCcgfCAnREVQTE9ZX0ZBSUxFRCcgfCAnVU5ERVBMT1lJTkcnIHwgJ1VOREVQTE9ZRUQnIHxcbiAgICogJ1VOREVQTE9ZX0ZBSUxFRCcgfCAnREVMRVRJTkcnIHwgJ0RFTEVURV9GQUlMRUQnIHwgJ1JFREVQTE9ZX0ZBSUxFRCcgfCAnRFJBRlQnfSBTdGF0ZVxuICAgKi9cblxuICAvKipcbiAgICogQWNjb3VudCBjb25uZWN0aW9uIHN0YXR1c1xuICAgKiBAdHlwZWRlZiB7J0NPTk5FQ1RFRCcgfCAnRElTQ09OTkVDVEVEJyB8ICdESVNDT05ORUNURURfRlJPTV9CUk9LRVInfSBDb25uZWN0aW9uU3RhdHVzXG4gICAqL1xuXG4gIC8qKlxuICAgKiBBY2NvdW50IHJlbGlhYmlsaXR5XG4gICAqIEB0eXBlZGVmIHsnaGlnaCcgfCAncmVndWxhcid9IFJlbGlhYmlsaXR5XG4gICAqL1xuXG4gIC8qKlxuICAgKiBDb3B5RmFjdG9yeSByb2xlc1xuICAgKiBAdHlwZWRlZiB7J1NVQlNDUklCRVInIHwgJ1BST1ZJREVSJ30gQ29weUZhY3RvcnlSb2xlc1xuICAgKi9cblxuICAvKipcbiAgICogU29ydCBvcmRlclxuICAgKiBAdHlwZWRlZiB7J2FzYycgfCAnZGVzYyd9IFNvcnRPcmRlclxuICAgKi9cblxuICAvKipcbiAgICogR2V0IGFjY291bnRzIGFwaSB2ZXJzaW9uXG4gICAqIEB0eXBlZGVmIHsnMScgfCAnMid9IEdldEFjY291bnRzQXBpVmVyc2lvblxuICAgKi9cblxuICAvKipcbiAgICogQHR5cGVkZWYge09iamVjdH0gQWNjb3VudHNGaWx0ZXJcbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IFtvZmZzZXRdIFNlYXJjaCBvZmZzZXQgKGRlZmF1bHRzIHRvIDApIChtdXN0IGJlIGdyZWF0ZXIgb3IgZXF1YWwgdG8gMClcbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IFtsaW1pdF0gU2VhcmNoIGxpbWl0IChkZWZhdWx0cyB0byAxMDAwKSBcbiAgICogKG11c3QgYmUgZ3JlYXRlciBvciBlcXVhbCB0byAxIGFuZCBsZXNzIG9yIGVxdWFsIHRvIDEwMDApXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8VmVyc2lvbj4gfCBWZXJzaW9ufSBbdmVyc2lvbl0gTVQgdmVyc2lvblxuICAgKiBAcHJvcGVydHkge0FycmF5PFR5cGU+IHwgVHlwZX0gW3R5cGVdIEFjY291bnQgdHlwZVxuICAgKiBAcHJvcGVydHkge0FycmF5PFN0YXRlPiB8IFN0YXRlfSBbc3RhdGVdIEFjY291bnQgc3RhdGVcbiAgICogQHByb3BlcnR5IHtBcnJheTxDb25uZWN0aW9uU3RhdHVzPiB8IENvbm5lY3Rpb25TdGF0dXN9IFtjb25uZWN0aW9uU3RhdHVzXSBDb25uZWN0aW9uIHN0YXR1c1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gW3F1ZXJ5XSBTZWFyY2hlcyBvdmVyIF9pZCwgbmFtZSwgc2VydmVyIGFuZCBsb2dpbiB0byBtYXRjaCBxdWVyeVxuICAgKiBAcHJvcGVydHkge3N0cmluZ30gW3Byb3Zpc2lvbmluZ1Byb2ZpbGVJZF0gUHJvdmlzaW9uaW5nIHByb2ZpbGUgaWRcbiAgICogQHByb3BlcnR5IHtTb3J0T3JkZXJ9IFtzb3J0T3JkZXJdIFNvcnQgb3JkZXIgZm9yIHN0YXRlQ2hhbmdlZEF0IGZpZWxkLCBkZWZhdWx0IGlzIG5vIG9yZGVyXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8c3RyaW5nPiB8IHN0cmluZ30gW3JlZ2lvbl0gQXZhaWxhYmxlIHJlZ2lvblxuICAgKiBAcHJvcGVydHkge0FycmF5PENvcHlGYWN0b3J5Um9sZXM+IHwgQ29weUZhY3RvcnlSb2xlc30gW2NvcHlGYWN0b3J5Um9sZXNdIEFjY291bnQgcm9sZXMgZm9yIENvcHlGYWN0b3J5MiBBUElcbiAgICovXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJhZGluZyBhY2NvdW50cyBiZWxvbmdpbmcgdG8gdGhlIGN1cnJlbnQgdXNlciAoc2VlIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Byb3Zpc2lvbmluZy9hcGkvYWNjb3VudC9yZWFkQWNjb3VudHMvKVxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge0FjY291bnRzRmlsdGVyfSBbYWNjb3VudHNGaWx0ZXJdIG9wdGlvbmFsIGZpbHRlclxuICAgKiBAcGFyYW0ge0dldEFjY291bnRzQXBpVmVyc2lvbn0gW2FwaVZlcnNpb25dIGFwaSB2ZXJzaW9uIHRvIHVzZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEFycmF5PE1ldGF0cmFkZXJBY2NvdW50RHRvPiB8IE1ldGF0cmFkZXJBY2NvdW50TGlzdER0bz59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggTWV0YVRyYWRlciBhY2NvdW50cyBmb3VuZFxuICAgKi9cbiAgZ2V0QWNjb3VudHMoYWNjb3VudHNGaWx0ZXIgPSB7fSwgYXBpVmVyc2lvbikge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCdnZXRBY2NvdW50cycpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzYCxcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBwYXJhbXM6IGFjY291bnRzRmlsdGVyLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMuX3Rva2VuLFxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWVcbiAgICB9O1xuICAgIGlmIChhcGlWZXJzaW9uKSB7XG4gICAgICBvcHRzLmhlYWRlcnNbJ2FwaS12ZXJzaW9uJ10gPSBhcGlWZXJzaW9uO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdnZXRBY2NvdW50cycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJhZGluZyBhY2NvdW50IGJ5IGlkIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L3JlYWRBY2NvdW50LylcbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIE1ldGFUcmFkZXIgYWNjb3VudCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1ldGF0cmFkZXJBY2NvdW50RHRvPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBNZXRhVHJhZGVyIGFjY291bnQgZm91bmRcbiAgICovXG4gIGdldEFjY291bnQoaWQpIHtcbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7aWR9YCxcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdnZXRBY2NvdW50Jyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cmFkaW5nIGFjY291bnQgcmVwbGljYSBieSB0cmFkaW5nIGFjY291bnQgaWQgYW5kIHJlcGxpY2EgaWQgKHNlZSBcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50UmVwbGljYS9yZWFkQWNjb3VudFJlcGxpY2EvKVxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWNjb3VudElkIE1ldGFUcmFkZXIgcHJpbWFyeSBhY2NvdW50IGlkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZXBsaWNhSWQgTWV0YVRyYWRlciBhY2NvdW50IHJlcGxpY2EgaWRcbiAgICogQHJldHVybiB7UHJvbWlzZTxNZXRhdHJhZGVyQWNjb3VudFJlcGxpY2FEdG8+fSBwcm9taXNlIHJlc29sdmluZyB3aXRoIE1ldGFUcmFkZXIgYWNjb3VudCByZXBsaWNhIGZvdW5kXG4gICAqL1xuICBnZXRBY2NvdW50UmVwbGljYShhY2NvdW50SWQsIHJlcGxpY2FJZCkge1xuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHthY2NvdW50SWR9L3JlcGxpY2FzLyR7cmVwbGljYUlkfWAsXG4gICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMuX3Rva2VuXG4gICAgICB9LFxuICAgICAganNvbjogdHJ1ZVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzLCAnZ2V0QWNjb3VudFJlcGxpY2EnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlcGxpY2FzIGZvciBhIHRyYWRpbmcgYWNjb3VudCAoc2VlIFxuICAgKiBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnRSZXBsaWNhL3JlYWRBY2NvdW50UmVwbGljYXMvKVxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWNjb3VudElkIFByaW1hcnkgYWNjb3VudCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEFycmF5PE1ldGF0cmFkZXJBY2NvdW50UmVwbGljYUR0bz4+fSBwcm9taXNlIHJlc29sdmluZyB3aXRoIE1ldGFUcmFkZXIgYWNjb3VudCByZXBsaWNhcyBmb3VuZFxuICAgKi9cbiAgZ2V0QWNjb3VudFJlcGxpY2FzKGFjY291bnRJZCkge1xuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHthY2NvdW50SWR9L3JlcGxpY2FzYCxcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdnZXRBY2NvdW50UmVwbGljYXMnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRhVHJhZGVyIGFjY291bnQgaWQgbW9kZWxcbiAgICogQHR5cGVkZWYge09iamVjdH0gTWV0YXRyYWRlckFjY291bnRJZER0b1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gaWQgTWV0YVRyYWRlciBhY2NvdW50IHVuaXF1ZSBpZGVudGlmaWVyXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBzdGF0ZSBTdGF0ZSBvZiB0aGUgYWNjb3VudC4gUG9zc2libGUgdmFsdWVzIGFyZSAnVU5ERVBMT1lFRCcsICdERVBMT1lFRCcsICdEUkFGVCdcbiAgICovXG5cbiAgLyoqXG4gICAqIEFkZHMgYSB0cmFkaW5nIGFjY291bnQgYW5kIHN0YXJ0cyBhIGNsb3VkIEFQSSBzZXJ2ZXIgZm9yIHRoZSB0cmFkaW5nIGFjY291bnQgKHNlZSBcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L2NyZWF0ZUFjY291bnQvKS5cbiAgICogSXQgY2FuIHRha2Ugc29tZSB0aW1lIGZvciB0aGUgQVBJIHNlcnZlciBhbmQgdHJhZGluZyB0ZXJtaW5hbCB0byBzdGFydCBhbmQgY29ubmVjdCB0byBicm9rZXIuXG4gICAqIFlvdSBjYW4gdXNlIHRoZSBgY29ubmVjdGlvblN0YXR1c2AgcmVwbGljYSBmaWVsZCB0byBtb25pdG9yIHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgdHJhZGluZyBhY2NvdW50LlxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge05ld01ldGF0cmFkZXJBY2NvdW50RHRvfSBhY2NvdW50IE1ldGFUcmFkZXIgYWNjb3VudCBkYXRhXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TWV0YXRyYWRlckFjY291bnRJZER0bz59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggYW4gaWQgYW5kIHN0YXRlIG9mIHRoZSBNZXRhVHJhZGVyIGFjY291bnQgY3JlYXRlZFxuICAgKi9cbiAgY3JlYXRlQWNjb3VudChhY2NvdW50KSB7XG4gICAgaWYgKHRoaXMuX2lzTm90Snd0VG9rZW4oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZU5vQWNjZXNzRXJyb3IoJ2NyZWF0ZUFjY291bnQnKTtcbiAgICB9XG4gICAgY29uc3Qgb3B0cyA9IHtcbiAgICAgIHVybDogYCR7dGhpcy5faG9zdH0vdXNlcnMvY3VycmVudC9hY2NvdW50c2AsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlbixcbiAgICAgICAgJ3RyYW5zYWN0aW9uLWlkJzogcmFuZG9tc3RyaW5nLmdlbmVyYXRlKDMyKVxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBkYXRhOiBhY2NvdW50XG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdjcmVhdGVBY2NvdW50Jyk7XG4gIH1cblxuICAvKipcbiAgICogTmV3IE1ldGFUcmFkZXIgYWNjb3VudCByZXBsaWNhIG1vZGVsXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IE5ld01ldGFUcmFkZXJBY2NvdW50UmVwbGljYUR0b1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gW3N5bWJvbF0gQW55IE1ldGFUcmFkZXIgc3ltYm9sIHlvdXIgYnJva2VyIHByb3ZpZGVzIGhpc3RvcmljYWwgbWFya2V0IGRhdGEgZm9yLiBcbiAgICogVGhpcyB2YWx1ZSBzaG91bGQgYmUgc3BlY2lmaWVkIGZvciBHMSBhY2NvdW50cyBvbmx5IGFuZCBvbmx5IGluIGNhc2UgeW91ciBNVCBhY2NvdW50IGZhaWxzIHRvIGNvbm5lY3QgdG8gYnJva2VyLlxuICAgKiBAcHJvcGVydHkge251bWJlcn0gbWFnaWMgTWFnaWMgdmFsdWUgdGhlIHRyYWRlcyBzaG91bGQgYmUgcGVyZm9ybWVkIHVzaW5nLlxuICAgKiBXaGVuIG1hbnVhbFRyYWRlcyBmaWVsZCBpcyBzZXQgdG8gdHJ1ZSwgbWFnaWMgdmFsdWUgbXVzdCBiZSAwXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcXVvdGVTdHJlYW1pbmdJbnRlcnZhbEluU2Vjb25kc10gUXVvdGUgc3RyZWFtaW5nIGludGVydmFsIGluIHNlY29uZHMuIFNldCB0byAwIGluIG9yZGVyIHRvIFxuICAgKiByZWNlaXZlIHF1b3RlcyBvbiBlYWNoIHRpY2suIERlZmF1bHQgdmFsdWUgaXMgMi41IHNlY29uZHMuIEludGVydmFscyBsZXNzIHRoYW4gMi41IHNlY29uZHMgYXJlIHN1cHBvcnRlZCBvbmx5IGZvciBHMlxuICAgKiBAcHJvcGVydHkge0FycmF5PHN0cmluZz59IFt0YWdzXSBVc2VyLWRlZmluZWQgYWNjb3VudCByZXBsaWNhIHRhZ3NcbiAgICogQHByb3BlcnR5IHtPYmplY3R9IFttZXRhZGF0YV0gRXh0cmEgaW5mb3JtYXRpb24gd2hpY2ggY2FuIGJlIHN0b3JlZCB0b2dldGhlciB3aXRoIHlvdXIgYWNjb3VudCByZXBsaWNhLiBcbiAgICogVG90YWwgbGVuZ3RoIG9mIHRoaXMgZmllbGQgYWZ0ZXIgc2VyaWFsaXppbmcgaXQgdG8gSlNPTiBpcyBsaW1pdGVkIHRvIDEwMjQgY2hhcmFjdGVyc1xuICAgKiBAcHJvcGVydHkge1JlbGlhYmlsaXR5fSBbcmVsaWFiaWxpdHldIFVzZWQgdG8gaW5jcmVhc2UgdGhlIHJlbGlhYmlsaXR5IG9mIHRoZSBhY2NvdW50IHJlcGxpY2EuIEhpZ2ggaXMgYSByZWNvbW1lbmRlZCB2YWx1ZSBcbiAgICogZm9yIHByb2R1Y3Rpb24gZW52aXJvbm1lbnQuIERlZmF1bHQgdmFsdWUgaXMgaGlnaFxuICAgKiBAcHJvcGVydHkge251bWJlcn0gW3Jlc291cmNlU2xvdHNdIE51bWJlciBvZiByZXNvdXJjZSBzbG90cyB0byBhbGxvY2F0ZSB0byBhY2NvdW50IHJlcGxpY2EuIEFsbG9jYXRpbmcgZXh0cmEgcmVzb3VyY2Ugc2xvdHNcbiAgICogcmVzdWx0cyBpbiBiZXR0ZXIgYWNjb3VudCBwZXJmb3JtYW5jZSB1bmRlciBsb2FkIHdoaWNoIGlzIHVzZWZ1bCBmb3Igc29tZSBhcHBsaWNhdGlvbnMuIEUuZy4gaWYgeW91IGhhdmUgbWFueVxuICAgKiBhY2NvdW50cyBjb3B5aW5nIHRoZSBzYW1lIHN0cmF0ZWd5IHZpYSBDb295RmFjdG9yeSBBUEksIHRoZW4geW91IGNhbiBpbmNyZWFzZSByZXNvdXJjZVNsb3RzIHRvIGdldCBhIGxvd2VyIHRyYWRlXG4gICAqIGNvcHlpbmcgbGF0ZW5jeS4gUGxlYXNlIG5vdGUgdGhhdCBhbGxvY2F0aW5nIGV4dHJhIHJlc291cmNlIHNsb3RzIGlzIGEgcGFpZCBvcHRpb24uIFBsZWFzZSBub3RlIHRoYXQgaGlnaFxuICAgKiByZWxpYWJpbGl0eSBhY2NvdW50cyB1c2UgcmVkdW5kYW50IGluZnJhc3RydWN0dXJlLCBzbyB0aGF0IGVhY2ggcmVzb3VyY2Ugc2xvdCBmb3IgYSBoaWdoIHJlbGlhYmlsaXR5IGFjY291bnRcbiAgICogaXMgYmlsbGVkIGFzIDIgc3RhbmRhcmQgcmVzb3VyY2Ugc2xvdHMuIERlZmF1bHQgaXMgMS5cbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IFtjb3B5RmFjdG9yeVJlc291cmNlU2xvdHNdIE51bWJlciBvZiBDb3B5RmFjdG9yeSAyIHJlc291cmNlIHNsb3RzIHRvIGFsbG9jYXRlIHRvIGFjY291bnQgcmVwbGljYS5cbiAgICogQWxsb2NhdGluZyBleHRyYSByZXNvdXJjZSBzbG90cyByZXN1bHRzIGluIGxvd2VyIHRyYWRlIGNvcHlpbmcgbGF0ZW5jeS4gUGxlYXNlIG5vdGUgdGhhdCBhbGxvY2F0aW5nIGV4dHJhIHJlc291cmNlXG4gICAqIHNsb3RzIGlzIGEgcGFpZCBvcHRpb24uIFBsZWFzZSBhbHNvIG5vdGUgdGhhdCBDb3B5RmFjdG9yeSAyIHVzZXMgcmVkdW5kYW50IGluZnJhc3RydWN0dXJlIHNvIHRoYXRcbiAgICogZWFjaCBDb3B5RmFjdG9yeSByZXNvdXJjZSBzbG90IGlzIGJpbGxlZCBhcyAyIHN0YW5kYXJkIHJlc291cmNlIHNsb3RzLiBZb3Ugd2lsbCBiZSBiaWxsZWQgZm9yIENvcHlGYWN0b3J5IDJcbiAgICogcmVzb3VyY2Ugc2xvdHMgb25seSBpZiB5b3UgaGF2ZSBhZGRlZCB5b3VyIGFjY291bnQgdG8gQ29weUZhY3RvcnkgMiBieSBzcGVjaWZ5aW5nIGNvcHlGYWN0b3J5Um9sZXMgZmllbGQuXG4gICAqIERlZmF1bHQgaXMgMS5cbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IHJlZ2lvbiBSZWdpb24gaWQgdG8gZGVwbG95IGFjY291bnQgcmVwbGljYSBhdC4gT25lIG9mIHJldHVybmVkIGJ5IHRoZSAvdXNlcnMvY3VycmVudC9yZWdpb25zIGVuZHBvaW50XG4gICAqL1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgdHJhZGluZyBhY2NvdW50IHJlcGxpY2EgaW4gYSByZWdpb24gZGlmZmVyZW50IGZyb20gdHJhZGluZyBhY2NvdW50IHJlZ2lvbiBhbmQgc3RhcnRzIGEgY2xvdWQgQVBJIHNlcnZlciBmb3IgaXRcbiAgICogKHNlZSBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnRSZXBsaWNhL2NyZWF0ZUFjY291bnRSZXBsaWNhLykuXG4gICAqIEl0IGNhbiB0YWtlIHNvbWUgdGltZSBmb3IgdGhlIEFQSSBzZXJ2ZXIgYW5kIHRyYWRpbmcgdGVybWluYWwgdG8gc3RhcnQgYW5kIGNvbm5lY3QgdG8gYnJva2VyLlxuICAgKiBZb3UgY2FuIHVzZSB0aGUgYGNvbm5lY3Rpb25TdGF0dXNgIHJlcGxpY2EgZmllbGQgdG8gbW9uaXRvciB0aGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIHJlcGxpY2EuXG4gICAqIE1ldGhvZCBpcyBhY2Nlc3NpYmxlIG9ubHkgd2l0aCBBUEkgYWNjZXNzIHRva2VuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhY2NvdW50SWQgcHJpbWFyeSBhY2NvdW50IGlkXG4gICAqIEBwYXJhbSB7TmV3TWV0YVRyYWRlckFjY291bnRSZXBsaWNhRHRvfSBhY2NvdW50IE1ldGFUcmFkZXIgYWNjb3VudCBkYXRhXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TWV0YXRyYWRlckFjY291bnRJZER0bz59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggYW4gaWQgYW5kIHN0YXRlIG9mIHRoZSBNZXRhVHJhZGVyIGFjY291bnQgcmVwbGljYSBjcmVhdGVkXG4gICAqL1xuICBjcmVhdGVBY2NvdW50UmVwbGljYShhY2NvdW50SWQsIGFjY291bnQpIHtcbiAgICBpZiAodGhpcy5faXNOb3RKd3RUb2tlbigpKSB7XG4gICAgICByZXR1cm4gdGhpcy5faGFuZGxlTm9BY2Nlc3NFcnJvcignY3JlYXRlQWNjb3VudFJlcGxpY2EnKTtcbiAgICB9XG4gICAgY29uc3Qgb3B0cyA9IHtcbiAgICAgIHVybDogYCR7dGhpcy5faG9zdH0vdXNlcnMvY3VycmVudC9hY2NvdW50cy8ke2FjY291bnRJZH0vcmVwbGljYXNgLFxuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW4sXG4gICAgICAgICd0cmFuc2FjdGlvbi1pZCc6IHJhbmRvbXN0cmluZy5nZW5lcmF0ZSgzMilcbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlLFxuICAgICAgZGF0YTogYWNjb3VudFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzLCAnY3JlYXRlQWNjb3VudFJlcGxpY2EnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydHMgQVBJIHNlcnZlciBhbmQgdHJhZGluZyB0ZXJtaW5hbCBmb3IgdHJhZGluZyBhY2NvdW50LlxuICAgKiBUaGlzIHJlcXVlc3Qgd2lsbCBiZSBpZ25vcmVkIGlmIHRoZSBhY2NvdW50IGlzIGFscmVhZHkgZGVwbG95ZWQuXG4gICAqIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L2RlcGxveUFjY291bnQvKVxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgTWV0YVRyYWRlciBhY2NvdW50IGlkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgcmVzb2x2aW5nIHdoZW4gTWV0YVRyYWRlciBhY2NvdW50IGlzIHNjaGVkdWxlZCBmb3IgZGVwbG95bWVudFxuICAgKi9cbiAgZGVwbG95QWNjb3VudChpZCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCdkZXBsb3lBY2NvdW50Jyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHtpZH0vZGVwbG95YCxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMuX3Rva2VuXG4gICAgICB9LFxuICAgICAganNvbjogdHJ1ZVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzLCAnZGVwbG95QWNjb3VudCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0cyBBUEkgc2VydmVyIGFuZCB0cmFkaW5nIHRlcm1pbmFsIGZvciB0cmFkaW5nIGFjY291bnQgcmVwbGljYS5cbiAgICogVGhpcyByZXF1ZXN0IHdpbGwgYmUgaWdub3JlZCBpZiB0aGUgcmVwbGljYSBpcyBhbHJlYWR5IGRlcGxveWVkXG4gICAqIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50UmVwbGljYS9kZXBsb3lBY2NvdW50UmVwbGljYS8pXG4gICAqIE1ldGhvZCBpcyBhY2Nlc3NpYmxlIG9ubHkgd2l0aCBBUEkgYWNjZXNzIHRva2VuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhY2NvdW50SWQgTWV0YVRyYWRlciBhY2NvdW50IGlkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZXBsaWNhSWQgTWV0YVRyYWRlciBhY2NvdW50IHJlcGxpY2EgaWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgcmVwbGljYSBpcyBzY2hlZHVsZWQgZm9yIGRlcGxveW1lbnRcbiAgICovXG4gIGRlcGxveUFjY291bnRSZXBsaWNhKGFjY291bnRJZCwgcmVwbGljYUlkKSB7XG4gICAgaWYgKHRoaXMuX2lzTm90Snd0VG9rZW4oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZU5vQWNjZXNzRXJyb3IoJ2RlcGxveUFjY291bnRSZXBsaWNhJyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHthY2NvdW50SWR9L3JlcGxpY2FzLyR7cmVwbGljYUlkfS9kZXBsb3lgLFxuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdkZXBsb3lBY2NvdW50UmVwbGljYScpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3BzIEFQSSBzZXJ2ZXIgYW5kIHRyYWRpbmcgdGVybWluYWwgZm9yIHRyYWRpbmcgYWNjb3VudC5cbiAgICogVGhpcyByZXF1ZXN0IHdpbGwgYmUgaWdub3JlZCBpZiB0cmFkaW5nIGFjY291bnQgaXMgYWxyZWFkeSB1bmRlcGxveWVkXG4gICAqIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L3VuZGVwbG95QWNjb3VudC8pXG4gICAqIE1ldGhvZCBpcyBhY2Nlc3NpYmxlIG9ubHkgd2l0aCBBUEkgYWNjZXNzIHRva2VuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBNZXRhVHJhZGVyIGFjY291bnQgaWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgaXMgc2NoZWR1bGVkIGZvciB1bmRlcGxveW1lbnRcbiAgICovXG4gIHVuZGVwbG95QWNjb3VudChpZCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCd1bmRlcGxveUFjY291bnQnKTtcbiAgICB9XG4gICAgY29uc3Qgb3B0cyA9IHtcbiAgICAgIHVybDogYCR7dGhpcy5faG9zdH0vdXNlcnMvY3VycmVudC9hY2NvdW50cy8ke2lkfS91bmRlcGxveWAsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWVcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qob3B0cywgJ3VuZGVwbG95QWNjb3VudCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3BzIEFQSSBzZXJ2ZXIgYW5kIHRyYWRpbmcgdGVybWluYWwgZm9yIHRyYWRpbmcgYWNjb3VudCByZXBsaWNhLlxuICAgKiBUaGUgcmVxdWVzdCB3aWxsIGJlIGlnbm9yZWQgaWYgdHJhZGluZyBhY2NvdW50IHJlcGxpY2EgaXMgYWxyZWFkeSB1bmRlcGxveWVkXG4gICAqIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50UmVwbGljYS91bmRlcGxveUFjY291bnRSZXBsaWNhLylcbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFjY291bnRJZCBNZXRhVHJhZGVyIHByaW1hcnkgYWNjb3VudCBpZFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcmVwbGljYUlkIE1ldGFUcmFkZXIgYWNjb3VudCByZXBsaWNhIGlkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgcmVzb2x2aW5nIHdoZW4gTWV0YVRyYWRlciBhY2NvdW50IHJlcGxpY2EgaXMgc2NoZWR1bGVkIGZvciB1bmRlcGxveW1lbnRcbiAgICovXG4gIHVuZGVwbG95QWNjb3VudFJlcGxpY2EoYWNjb3VudElkLCByZXBsaWNhSWQpIHtcbiAgICBpZiAodGhpcy5faXNOb3RKd3RUb2tlbigpKSB7XG4gICAgICByZXR1cm4gdGhpcy5faGFuZGxlTm9BY2Nlc3NFcnJvcigndW5kZXBsb3lBY2NvdW50UmVwbGljYScpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS9yZXBsaWNhcy8ke3JlcGxpY2FJZH0vdW5kZXBsb3lgLFxuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICd1bmRlcGxveUFjY291bnRSZXBsaWNhJyk7XG4gIH1cblxuICAvKipcbiAgICogUmVkZXBsb3lzIHRyYWRpbmcgYWNjb3VudC4gVGhpcyBpcyBlcXVpdmFsZW50IHRvIHVuZGVwbG95IGltbWVkaWF0ZWx5IGZvbGxvd2VkIGJ5IGRlcGxveVxuICAgKiAoc2VlIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Byb3Zpc2lvbmluZy9hcGkvYWNjb3VudC9yZWRlcGxveUFjY291bnQvKVxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgTWV0YVRyYWRlciBhY2NvdW50IGlkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgcmVzb2x2aW5nIHdoZW4gTWV0YVRyYWRlciBhY2NvdW50IGlzIHNjaGVkdWxlZCBmb3IgcmVkZXBsb3ltZW50XG4gICAqL1xuICByZWRlcGxveUFjY291bnQoaWQpIHtcbiAgICBpZiAodGhpcy5faXNOb3RKd3RUb2tlbigpKSB7XG4gICAgICByZXR1cm4gdGhpcy5faGFuZGxlTm9BY2Nlc3NFcnJvcigncmVkZXBsb3lBY2NvdW50Jyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHtpZH0vcmVkZXBsb3lgLFxuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdyZWRlcGxveUFjY291bnQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRlcGxveXMgdHJhZGluZyBhY2NvdW50IHJlcGxpY2EuIFRoaXMgaXMgZXF1aXZhbGVudCB0byB1bmRlcGxveSBpbW1lZGlhdGVseSBmb2xsb3dlZCBieSBkZXBsb3kuXG4gICAqIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L3JlZGVwbG95QWNjb3VudFJlcGxpY2EvKVxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWNjb3VudElkIE1ldGFUcmFkZXIgcHJpbWFyeSBhY2NvdW50IGlkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZXBsaWNhSWQgTWV0YVRyYWRlciBhY2NvdW50IHJlcGxpY2EgaWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgcmVwbGljYSBpcyBzY2hlZHVsZWQgZm9yIHJlZGVwbG95bWVudFxuICAgKi9cbiAgcmVkZXBsb3lBY2NvdW50UmVwbGljYShhY2NvdW50SWQsIHJlcGxpY2FJZCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCdyZWRlcGxveUFjY291bnRSZXBsaWNhJyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHthY2NvdW50SWR9L3JlcGxpY2FzLyR7cmVwbGljYUlkfS9yZWRlcGxveWAsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWVcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qob3B0cywgJ3JlZGVwbG95QWNjb3VudFJlcGxpY2EnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgdHJhZGluZyBhY2NvdW50IGFuZCBzdG9wcyB0aGUgQVBJIHNlcnZlciBzZXJ2aW5nIHRoZSBhY2NvdW50LlxuICAgKiBUaGUgYWNjb3VudCBzdGF0ZSBzdWNoIGFzIGRvd25sb2FkZWQgbWFya2V0IGRhdGEgaGlzdG9yeSB3aWxsIGJlIHJlbW92ZWQgYXMgd2VsbCB3aGVuIHlvdSByZW1vdmUgdGhlIGFjY291bnQuXG4gICAqIChzZWUgaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L2RlbGV0ZUFjY291bnQvKS5cbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIElkIG9mIHRoZSBhY2NvdW50IHRvIGJlIGRlbGV0ZWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgaXMgc2NoZWR1bGVkIGZvciBkZWxldGlvblxuICAgKi9cbiAgZGVsZXRlQWNjb3VudChpZCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCdkZWxldGVBY2NvdW50Jyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHtpZH1gLFxuICAgICAgbWV0aG9kOiAnREVMRVRFJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWVcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qob3B0cywgJ2RlbGV0ZUFjY291bnQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgdHJhZGluZyBhY2NvdW50IHJlcGxpY2EgYW5kIHN0b3BzIHRoZSBBUEkgc2VydmVyIHNlcnZpbmcgdGhlIHJlcGxpY2FcbiAgICogKHNlZSBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnQvZGVsZXRlQWNjb3VudFJlcGxpY2EvKS5cbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFjY291bnRJZCBwcmltYXJ5IGFjY291bnQgaWRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJlcGxpY2FJZCBJZCBvZiB0aGUgYWNjb3VudCByZXBsaWNhIHRvIGJlIGRlbGV0ZWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgcmVwbGljYSBpcyBzY2hlZHVsZWQgZm9yIGRlbGV0aW9uXG4gICAqL1xuICBkZWxldGVBY2NvdW50UmVwbGljYShhY2NvdW50SWQsIHJlcGxpY2FJZCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCdkZWxldGVBY2NvdW50UmVwbGljYScpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS9yZXBsaWNhcy8ke3JlcGxpY2FJZH1gLFxuICAgICAgbWV0aG9kOiAnREVMRVRFJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWVcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qob3B0cywgJ2RlbGV0ZUFjY291bnRSZXBsaWNhJyk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0cmFkaW5nIGFjY291bnQuIFxuICAgKiBQbGVhc2UgcmVkZXBsb3kgdGhlIHRyYWRpbmcgYWNjb3VudCBpbiBvcmRlciBmb3IgdXBkYXRlZCBzZXR0aW5ncyB0byB0YWtlIGVmZmVjdFxuICAgKiAoc2VlIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Byb3Zpc2lvbmluZy9hcGkvYWNjb3VudC91cGRhdGVBY2NvdW50LykuXG4gICAqIE1ldGhvZCBpcyBhY2Nlc3NpYmxlIG9ubHkgd2l0aCBBUEkgYWNjZXNzIHRva2VuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBNZXRhVHJhZGVyIGFjY291bnQgaWRcbiAgICogQHBhcmFtIHtNZXRhdHJhZGVyQWNjb3VudFVwZGF0ZUR0b30gYWNjb3VudCB1cGRhdGVkIGFjY291bnQgaW5mb3JtYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgaXMgdXBkYXRlZFxuICAgKi9cbiAgdXBkYXRlQWNjb3VudChpZCwgYWNjb3VudCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCd1cGRhdGVBY2NvdW50Jyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHtpZH1gLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBkYXRhOiBhY2NvdW50XG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICd1cGRhdGVBY2NvdW50Jyk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlZCBNZXRhVHJhZGVyIGFjY291bnQgcmVwbGljYSBkYXRhXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IFVwZGF0ZWRNZXRhdHJhZGVyQWNjb3VudFJlcGxpY2FEdG9cbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IFttYWdpY10gTWFnaWMgdmFsdWUgdGhlIHRyYWRlcyBzaG91bGQgYmUgcGVyZm9ybWVkIHVzaW5nLlxuICAgKiBXaGVuIG1hbnVhbFRyYWRlcyBmaWVsZCBpcyBzZXQgdG8gdHJ1ZSwgbWFnaWMgdmFsdWUgbXVzdCBiZSAwXG4gICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcXVvdGVTdHJlYW1pbmdJbnRlcnZhbEluU2Vjb25kc10gUXVvdGUgc3RyZWFtaW5nIGludGVydmFsIGluIHNlY29uZHMuIFNldCB0byAwIGluIG9yZGVyIHRvXG4gICAqIHJlY2VpdmUgcXVvdGVzIG9uIGVhY2ggdGljay4gRGVmYXVsdCB2YWx1ZSBpcyAyLjUgc2Vjb25kcy4gSW50ZXJ2YWxzIGxlc3MgdGhhbiAyLjUgc2Vjb25kcyBhcmUgc3VwcG9ydGVkXG4gICAqIG9ubHkgZm9yIEcyXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8c3RyaW5nPn0gW3RhZ3NdIE1ldGFUcmFkZXIgYWNjb3VudCB0YWdzXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBbbWV0YWRhdGFdIGV4dHJhIGluZm9ybWF0aW9uIHdoaWNoIGNhbiBiZSBzdG9yZWQgdG9nZXRoZXIgd2l0aCB5b3VyIGFjY291bnRcbiAgICogQHByb3BlcnR5IHtudW1iZXJ9IFtyZXNvdXJjZVNsb3RzXSBOdW1iZXIgb2YgcmVzb3VyY2Ugc2xvdHMgdG8gYWxsb2NhdGUgdG8gYWNjb3VudC4gQWxsb2NhdGluZyBleHRyYSByZXNvdXJjZSBzbG90c1xuICAgKiByZXN1bHRzIGluIGJldHRlciBhY2NvdW50IHBlcmZvcm1hbmNlIHVuZGVyIGxvYWQgd2hpY2ggaXMgdXNlZnVsIGZvciBzb21lIGFwcGxpY2F0aW9ucy4gRS5nLiBpZiB5b3UgaGF2ZSBtYW55XG4gICAqIGFjY291bnRzIGNvcHlpbmcgdGhlIHNhbWUgc3RyYXRlZ3kgdmlhIENvb3lGYWN0b3J5IEFQSSwgdGhlbiB5b3UgY2FuIGluY3JlYXNlIHJlc291cmNlU2xvdHMgdG8gZ2V0IGEgbG93ZXIgdHJhZGVcbiAgICogY29weWluZyBsYXRlbmN5LiBQbGVhc2Ugbm90ZSB0aGF0IGFsbG9jYXRpbmcgZXh0cmEgcmVzb3VyY2Ugc2xvdHMgaXMgYSBwYWlkIG9wdGlvbi4gRGVmYXVsdCBpcyAxXG4gICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbY29weUZhY3RvcnlSZXNvdXJjZVNsb3RzXSBOdW1iZXIgb2YgQ29weUZhY3RvcnkgMiByZXNvdXJjZSBzbG90cyB0byBhbGxvY2F0ZSB0byBhY2NvdW50LlxuICAgKiBBbGxvY2F0aW5nIGV4dHJhIHJlc291cmNlIHNsb3RzIHJlc3VsdHMgaW4gbG93ZXIgdHJhZGUgY29weWluZyBsYXRlbmN5LiBQbGVhc2Ugbm90ZSB0aGF0IGFsbG9jYXRpbmcgZXh0cmEgcmVzb3VyY2VcbiAgICogc2xvdHMgaXMgYSBwYWlkIG9wdGlvbi4gUGxlYXNlIGFsc28gbm90ZSB0aGF0IENvcHlGYWN0b3J5IDIgdXNlcyByZWR1bmRhbnQgaW5mcmFzdHJ1Y3R1cmUgc28gdGhhdFxuICAgKiBlYWNoIENvcHlGYWN0b3J5IHJlc291cmNlIHNsb3QgaXMgYmlsbGVkIGFzIDIgc3RhbmRhcmQgcmVzb3VyY2Ugc2xvdHMuIFlvdSB3aWxsIGJlIGJpbGxlZCBmb3IgQ29weUZhY3RvcnkgMlxuICAgKiByZXNvdXJjZSBzbG90cyBvbmx5IGlmIHlvdSBoYXZlIGFkZGVkIHlvdXIgYWNjb3VudCB0byBDb3B5RmFjdG9yeSAyIGJ5IHNwZWNpZnlpbmcgY29weUZhY3RvcnlSb2xlcyBmaWVsZC5cbiAgICogRGVmYXVsdCBpcyAxLlxuICAgKi9cblxuICAvKipcbiAgICogVXBkYXRlcyB0cmFkaW5nIGFjY291bnQgcmVwbGljYSAoc2VlXG4gICAqIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Byb3Zpc2lvbmluZy9hcGkvYWNjb3VudC91cGRhdGVBY2NvdW50UmVwbGljYS8pLlxuICAgKiBNZXRob2QgaXMgYWNjZXNzaWJsZSBvbmx5IHdpdGggQVBJIGFjY2VzcyB0b2tlblxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWNjb3VudElkIE1ldGFUcmFkZXIgcHJpbWFyeSBhY2NvdW50IGlkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZXBsaWNhSWQgTWV0YVRyYWRlciBhY2NvdW50IHJlcGxpY2EgaWRcbiAgICogQHBhcmFtIHtVcGRhdGVkTWV0YXRyYWRlckFjY291bnRSZXBsaWNhRHRvfSBtZXRhdHJhZGVyQWNjb3VudCB1cGRhdGVkIGFjY291bnQgcmVwbGljYSBpbmZvcm1hdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIE1ldGFUcmFkZXIgYWNjb3VudCByZXBsaWNhIGlzIHVwZGF0ZWRcbiAgICovXG4gIHVwZGF0ZUFjY291bnRSZXBsaWNhKGFjY291bnRJZCwgcmVwbGljYUlkLCBtZXRhdHJhZGVyQWNjb3VudCkge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCd1cGRhdGVBY2NvdW50UmVwbGljYScpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS9yZXBsaWNhcy8ke3JlcGxpY2FJZH1gLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBkYXRhOiBtZXRhdHJhZGVyQWNjb3VudFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzLCAndXBkYXRlQWNjb3VudFJlcGxpY2EnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmNyZWFzZXMgdHJhZGluZyBhY2NvdW50IHJlbGlhYmlsaXR5IGluIG9yZGVyIHRvIGluY3JlYXNlIHRoZSBleHBlY3RlZCBhY2NvdW50IHVwdGltZS5cbiAgICogVGhlIGFjY291bnQgd2lsbCBiZSB0ZW1wb3Jhcnkgc3RvcHBlZCB0byBwZXJmb3JtIHRoaXMgYWN0aW9uLlxuICAgKiBOb3RlIHRoYXQgaW5jcmVhc2luZyByZWxpYWJpbGl0eSBpcyBhIHBhaWQgb3B0aW9uIChzZWVcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3MvcHJvdmlzaW9uaW5nL2FwaS9hY2NvdW50L2luY3JlYXNlUmVsaWFiaWxpdHkvKS5cbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIE1ldGFUcmFkZXIgYWNjb3VudCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIE1ldGFUcmFkZXIgYWNjb3VudCByZWxpYWJpbGl0eSBpcyBpbmNyZWFzZWRcbiAgICovXG4gIGluY3JlYXNlUmVsaWFiaWxpdHkoaWQpIHtcbiAgICBpZiAodGhpcy5faXNOb3RKd3RUb2tlbigpKSB7XG4gICAgICByZXR1cm4gdGhpcy5faGFuZGxlTm9BY2Nlc3NFcnJvcignaW5jcmVhc2VSZWxpYWJpbGl0eScpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7aWR9L2luY3JlYXNlLXJlbGlhYmlsaXR5YCxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMuX3Rva2VuXG4gICAgICB9LFxuICAgICAganNvbjogdHJ1ZVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzLCAnaW5jcmVhc2VSZWxpYWJpbGl0eScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgcmlzayBtYW5hZ2VtZW50IEFQSSBmb3IgdHJhZGluZyBhY2NvdW50LlxuICAgKiBUaGUgYWNjb3VudCB3aWxsIGJlIHRlbXBvcmFyeSBzdG9wcGVkIHRvIHBlcmZvcm0gdGhpcyBhY3Rpb24uXG4gICAqIE5vdGUgdGhhdCByaXNrIG1hbmFnZW1lbnQgQVBJIGlzIGEgcGFpZCBvcHRpb24gKHNlZVxuICAgKiBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnQvZW5hYmxlUmlza01hbmFnZW1lbnRBcGkvKS5cbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIE1ldGFUcmFkZXIgYWNjb3VudCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIGFjY291bnQgcmlzayBtYW5hZ2VtZW50IGlzIGVuYWJsZWRcbiAgICovXG4gIGVuYWJsZVJpc2tNYW5hZ2VtZW50QXBpKGlkKSB7XG4gICAgaWYgKHRoaXMuX2lzTm90Snd0VG9rZW4oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZU5vQWNjZXNzRXJyb3IoJ2VuYWJsZVJpc2tNYW5hZ2VtZW50QXBpJyk7XG4gICAgfVxuICAgIGNvbnN0IG9wdHMgPSB7XG4gICAgICB1cmw6IGAke3RoaXMuX2hvc3R9L3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHtpZH0vZW5hYmxlLXJpc2stbWFuYWdlbWVudC1hcGlgLFxuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgICdhdXRoLXRva2VuJzogdGhpcy5fdG9rZW5cbiAgICAgIH0sXG4gICAgICBqc29uOiB0cnVlXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdlbmFibGVSaXNrTWFuYWdlbWVudEFwaScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgY29weSBmYWN0b3J5IEFQSSBmb3IgdHJhZGluZyBhY2NvdW50LlxuICAgKiBUaGUgYWNjb3VudCB3aWxsIGJlIHRlbXBvcmFyeSBzdG9wcGVkIHRvIHBlcmZvcm0gdGhpcyBhY3Rpb24uXG4gICAqIE5vdGUgdGhhdCBjb3B5IGZhY3RvcnkgQVBJIGlzIGEgcGFpZCBvcHRpb24gKHNlZVxuICAgKiBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnQvZW5hYmxlQ29weUZhY3RvcnlBcGkvKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIE1ldGFUcmFkZXIgYWNjb3VudCBpZFxuICAgKiBAcGFyYW0ge0FycmF5PENvcHlGYWN0b3J5Um9sZXM+fSBjb3B5RmFjdG9yeVJvbGVzIENvcHkgZmFjdG9yeSByb2xlc1xuICAgKiBAcGFyYW0ge251bWJlcn0gY29weUZhY3RvcnlSZXNvdXJjZVNsb3RzIENvcHkgZmFjdG9yeSByZXNvdXJjZSBzbG90c1xuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIGFjY291bnQgY29weSBmYWN0b3J5IGlzIGVuYWJsZWRcbiAgICovXG4gIGVuYWJsZUNvcHlGYWN0b3J5QXBpKGlkLCBjb3B5RmFjdG9yeVJvbGVzLCBjb3B5RmFjdG9yeVJlc291cmNlU2xvdHMpIHtcbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7aWR9L2VuYWJsZS1jb3B5LWZhY3RvcnktYXBpYCxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMuX3Rva2VuXG4gICAgICB9LFxuICAgICAganNvbjogdHJ1ZSxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgY29weUZhY3RvcnlSb2xlcyxcbiAgICAgICAgY29weUZhY3RvcnlSZXNvdXJjZVNsb3RzXG4gICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5faHR0cENsaWVudC5yZXF1ZXN0KG9wdHMsICdlbmFibGVDb3B5RmFjdG9yeUFwaScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgTWV0YVN0YXRzIEFQSSBmb3IgdHJhZGluZyBhY2NvdW50LlxuICAgKiBUaGUgYWNjb3VudCB3aWxsIGJlIHRlbXBvcmFyeSBzdG9wcGVkIHRvIHBlcmZvcm0gdGhpcyBhY3Rpb24uXG4gICAqIE5vdGUgdGhhdCB0aGlzIGlzIGEgcGFpZCBvcHRpb24gKHNlZVxuICAgKiBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnQvZW5hYmxlTWV0YVN0YXRzQXBpLykuXG4gICAqIE1ldGhvZCBpcyBhY2Nlc3NpYmxlIG9ubHkgd2l0aCBBUEkgYWNjZXNzIHRva2VuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZCBNZXRhVHJhZGVyIGFjY291bnQgaWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBhY2NvdW50IE1ldGFTdGF0cyBBUEkgaXMgZW5hYmxlZFxuICAgKi9cbiAgZW5hYmxlTWV0YVN0YXRzQXBpKGlkKSB7XG4gICAgaWYgKHRoaXMuX2lzTm90Snd0VG9rZW4oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2hhbmRsZU5vQWNjZXNzRXJyb3IoJ2VuYWJsZU1ldGFTdGF0c0FwaScpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7aWR9L2VuYWJsZS1tZXRhc3RhdHMtYXBpYCxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnYXV0aC10b2tlbic6IHRoaXMuX3Rva2VuXG4gICAgICB9LFxuICAgICAganNvbjogdHJ1ZVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2h0dHBDbGllbnQucmVxdWVzdChvcHRzLCAnZW5hYmxlTWV0YVN0YXRzQXBpJyk7XG4gIH1cblxuICAvKipcbiAgICogQ29uZmlndXJhdGlvbiBsaW5rXG4gICAqIEB0eXBlZGVmIHtPYmplY3R9IENvbmZpZ3VyYXRpb25MaW5rXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBjb25maWd1cmF0aW9uTGluayBTZWN1cmUgbGluayB0byBhbGxvdyBlbmQgdXNlciB0byBjb25maWd1cmUgYWNjb3VudCBkaXJlY3RseVxuICAgKi9cblxuICAvKipcbiAgICogR2VuZXJhdGVzIHRyYWRpbmcgYWNjb3VudCBjb25maWd1cmF0aW9uIGxpbmsgYnkgYWNjb3VudCBpZC5cbiAgICogKHNlZSBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9wcm92aXNpb25pbmcvYXBpL2FjY291bnQvY3JlYXRlQ29uZmlndXJhdGlvbkxpbmsvKVxuICAgKiBUaGlzIGxpbmsgY2FuIGJlIHVzZWQgYnkgdGhlIGVuZCB1c2VyIHRvIGVudGVyIHRyYWRpbmcgYWNjb3VudCBsb2dpbiBhbmQgcGFzc3dvcmQgb3IgY2hhbmdlIHRoZSBwYXNzd29yZC5cbiAgICogTWV0aG9kIGlzIGFjY2Vzc2libGUgb25seSB3aXRoIEFQSSBhY2Nlc3MgdG9rZW5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFjY291bnRJZCBUcmFkaW5nIGFjY291bnQgaWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IFt0dGxJbkRheXNdIExpZmV0aW1lIG9mIHRoZSBsaW5rIGluIGRheXMuIERlZmF1bHQgaXMgNy5cbiAgICogQHJldHVybiB7UHJvbWlzZTxDb25maWd1cmF0aW9uTGluaz59IHByb21pc2UgcmVzb2x2aW5nIHdpdGggY29uZmlndXJhdGlvbiBsaW5rXG4gICAqL1xuICBjcmVhdGVDb25maWd1cmF0aW9uTGluayhhY2NvdW50SWQsIHR0bEluRGF5cykge1xuICAgIGlmICh0aGlzLl9pc05vdEp3dFRva2VuKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9oYW5kbGVOb0FjY2Vzc0Vycm9yKCdjcmVhdGVDb25maWd1cmF0aW9uTGluaycpO1xuICAgIH1cbiAgICBjb25zdCBvcHRzID0ge1xuICAgICAgdXJsOiBgJHt0aGlzLl9ob3N0fS91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS9jb25maWd1cmF0aW9uLWxpbmtgLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ2F1dGgtdG9rZW4nOiB0aGlzLl90b2tlblxuICAgICAgfSxcbiAgICAgIHBhcmFtczoge1xuICAgICAgICB0dGxJbkRheXM6IHR0bEluRGF5c1xuICAgICAgfSxcbiAgICAgIGpzb246IHRydWVcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9odHRwQ2xpZW50LnJlcXVlc3Qob3B0cywgJ2NyZWF0ZUNvbmZpZ3VyYXRpb25MaW5rJyk7XG4gIH1cblxufVxuIl0sIm5hbWVzIjpbIk1ldGF0cmFkZXJBY2NvdW50Q2xpZW50IiwiTWV0YUFwaUNsaWVudCIsImdldEFjY291bnRzIiwiYWNjb3VudHNGaWx0ZXIiLCJhcGlWZXJzaW9uIiwiX2lzTm90Snd0VG9rZW4iLCJfaGFuZGxlTm9BY2Nlc3NFcnJvciIsIm9wdHMiLCJ1cmwiLCJfaG9zdCIsIm1ldGhvZCIsInBhcmFtcyIsImhlYWRlcnMiLCJfdG9rZW4iLCJqc29uIiwiX2h0dHBDbGllbnQiLCJyZXF1ZXN0IiwiZ2V0QWNjb3VudCIsImlkIiwiZ2V0QWNjb3VudFJlcGxpY2EiLCJhY2NvdW50SWQiLCJyZXBsaWNhSWQiLCJnZXRBY2NvdW50UmVwbGljYXMiLCJjcmVhdGVBY2NvdW50IiwiYWNjb3VudCIsInJhbmRvbXN0cmluZyIsImdlbmVyYXRlIiwiZGF0YSIsImNyZWF0ZUFjY291bnRSZXBsaWNhIiwiZGVwbG95QWNjb3VudCIsImRlcGxveUFjY291bnRSZXBsaWNhIiwidW5kZXBsb3lBY2NvdW50IiwidW5kZXBsb3lBY2NvdW50UmVwbGljYSIsInJlZGVwbG95QWNjb3VudCIsInJlZGVwbG95QWNjb3VudFJlcGxpY2EiLCJkZWxldGVBY2NvdW50IiwiZGVsZXRlQWNjb3VudFJlcGxpY2EiLCJ1cGRhdGVBY2NvdW50IiwidXBkYXRlQWNjb3VudFJlcGxpY2EiLCJtZXRhdHJhZGVyQWNjb3VudCIsImluY3JlYXNlUmVsaWFiaWxpdHkiLCJlbmFibGVSaXNrTWFuYWdlbWVudEFwaSIsImVuYWJsZUNvcHlGYWN0b3J5QXBpIiwiY29weUZhY3RvcnlSb2xlcyIsImNvcHlGYWN0b3J5UmVzb3VyY2VTbG90cyIsImVuYWJsZU1ldGFTdGF0c0FwaSIsImNyZWF0ZUNvbmZpZ3VyYXRpb25MaW5rIiwidHRsSW5EYXlzIl0sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7OztlQVNxQkE7OztzRUFOSztxRUFDRDs7Ozs7O0FBS1YsSUFBQSxBQUFNQSwwQkFBTixNQUFNQSxnQ0FBZ0NDLHNCQUFhO0lBRWhFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCQyxHQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtREMsR0FHRDs7Ozs7R0FLQyxHQUVEOzs7Ozs7O0dBT0MsR0FFRDs7O0dBR0MsR0FFRDs7O0dBR0MsR0FFRDs7O0dBR0MsR0FFRDs7OztHQUlDLEdBRUQ7OztHQUdDLEdBRUQ7OztHQUdDLEdBRUQ7OztHQUdDLEdBRUQ7OztHQUdDLEdBRUQ7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