bitgo
Version:
BitGo JavaScript SDK
390 lines • 58.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @prettier
*/
require("should");
const nock = require("nock");
const sinon = require("sinon");
const sdk_test_1 = require("@bitgo/sdk-test");
const src_1 = require("../../../src");
const sdk_core_1 = require("@bitgo/sdk-core");
describe('Pending Approvals:', () => {
let sandbox;
let bitgo;
let basecoin;
let wallet;
let bgUrl;
const coin = 'tbtc';
const walletId = 'wallet_id';
const attestation = {
signature: 'signature',
credentialId: 'credential-id',
clientDataJSON: 'client-data-json',
authenticatorData: 'authenticator-data',
};
const pendingApprovalData = {
id: 'pa0',
info: {
type: sdk_core_1.Type.TRANSACTION_REQUEST,
transactionRequest: {
coinSpecific: {
[coin]: {},
},
recipients: [],
buildParams: {
type: 'consolidate',
},
sourceWallet: walletId,
},
},
state: sdk_core_1.State.PENDING,
creator: 'test',
};
const walletData = {
id: walletId,
coin,
pendingApprovals: [pendingApprovalData],
};
beforeEach(function () {
sandbox = sinon.createSandbox();
nock.disableNetConnect();
});
afterEach(function () {
sandbox.restore();
});
before(async () => {
// create wallet
bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
bitgo.initializeTestVars();
basecoin = bitgo.coin(coin);
wallet = new sdk_core_1.Wallet(bitgo, basecoin, walletData);
bgUrl = sdk_core_1.Environments[bitgo.getEnv()].uri;
pendingApprovalData.wallet = wallet;
});
['tsol', 'teth', 'tbtc'].forEach((coinName) => {
it(`should use correct tssUtils for ${coinName}`, () => {
const coin = bitgo.coin(coinName);
const pendingAproval = new sdk_core_1.PendingApproval(bitgo, coin, {});
if (coin.supportsTss()) {
if (coin.getMPCAlgorithm() === 'ecdsa') {
pendingAproval['tssUtils'].should.be.instanceOf(sdk_core_1.ECDSAUtils.EcdsaUtils);
}
else if (coin.getMPCAlgorithm() === 'eddsa') {
pendingAproval['tssUtils'].should.be.instanceOf(sdk_core_1.EddsaUtils);
}
}
else {
(pendingAproval['tssUtils'] === undefined).should.be.true();
}
});
});
['MPCv2', undefined].forEach((multisigTypeVersion) => {
it(`should use correct tssUtils for multisigTypeVersion: ${multisigTypeVersion}`, () => {
const coin = bitgo.coin('hteth');
const walletDataMpcV2 = {
...walletData,
multisigTypeVersion: multisigTypeVersion,
};
const walletMPCv2 = new sdk_core_1.Wallet(bitgo, basecoin, walletDataMpcV2);
const pendingAproval = new sdk_core_1.PendingApproval(bitgo, coin, {}, walletMPCv2);
if (walletMPCv2.multisigTypeVersion() === 'MPCv2') {
pendingAproval['tssUtils'].should.be.instanceOf(sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils);
}
else {
pendingAproval['tssUtils'].should.be.instanceOf(sdk_core_1.ECDSAUtils.EcdsaUtils);
}
});
});
it('should call consolidate instead of build when rebuilding consolidation pending approvals', async () => {
const scope = nock(bgUrl).post(`/api/v2/${coin}/wallet/${walletId}/consolidateUnspents`).reply(200);
const pendingApprovals = wallet.pendingApprovals();
pendingApprovals.should.have.length(1);
const pendingApproval = pendingApprovals[0];
// approval will fail when attempting to resign. This is ok - we just want to make sure
// the consolidateUnspents endpoint was called already before failing
await pendingApproval.approve({ xprv: 'nonsense' }).should.be.rejected();
scope.done();
});
it('should approve for transactionRequestLite if we cannot recreate transaction', async () => {
const pendingApprovalData2 = { ...pendingApprovalData, txRequestId: '1234-4567-6789' };
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, basecoin, pendingApprovalData2, wallet);
const paScope = nock(bgUrl)
.put(`/api/v2/${coin}/pendingapprovals/${pendingApprovalData.id}`, {
state: 'approved',
otp: undefined,
})
.reply(200, {
...pendingApprovalData2,
state: 'approved',
});
const recreateTransactionTssStub = sandbox.stub(sdk_core_1.PendingApproval.prototype, 'recreateAndSignTSSTransaction');
const recreateTransactionStub = sandbox.stub(sdk_core_1.PendingApproval.prototype, 'recreateAndSignTransaction');
pendingApproval.type().should.equal(sdk_core_1.Type.TRANSACTION_REQUEST);
await pendingApproval.approve({});
recreateTransactionTssStub.notCalled.should.be.true();
recreateTransactionStub.notCalled.should.be.true();
paScope.isDone().should.be.true();
});
it('should pass attestation without bypassing multisig half-signing', async () => {
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, basecoin, pendingApprovalData, wallet);
const halfSignedTxHex = 'half-signed-transaction';
const paScope = nock(bgUrl)
.put(`/api/v2/${coin}/pendingapprovals/${pendingApprovalData.id}`, {
state: 'approved',
attestation,
halfSigned: { txHex: halfSignedTxHex },
})
.reply(200, {
...pendingApprovalData,
state: 'approved',
});
await pendingApproval.approve({ tx: halfSignedTxHex, attestation });
paScope.isDone().should.be.true();
});
function testRecreateTransaction(coinName, recreateTransaction, type) {
it(`[${coinName}] should ${recreateTransaction ? 'not ' : ''}recreate the transaction during approving a pending approval if there are no recipients for PA type ${type}`, async () => {
const coin = bitgo.coin(coinName);
const txRequestId = coin.supportsTss() ? 'requestTxIdTest' : undefined;
const pendingApprovalInfo = type === 'transactionRequest'
? {
type,
transactionRequest: {
coinSpecific: {
[coinName]: { txHex: 'gabagool' },
},
recipients: [],
buildParams: {},
sourceWallet: walletId,
},
}
: { type };
const pendingApprovalDataTemp = {
id: 'pa0',
info: pendingApprovalInfo,
wallet: walletId,
state: sdk_core_1.State.PENDING,
creator: 'test',
txRequestId,
};
const walletDataTemp = {
id: walletId,
coinName,
pendingApprovals: [pendingApprovalDataTemp],
};
const walletTemp = new sdk_core_1.Wallet(bitgo, coin, walletDataTemp);
pendingApprovalDataTemp.wallet = walletTemp.id();
const pendingApprovals = walletTemp.pendingApprovals();
pendingApprovals.should.have.length(1);
const pendingApproval = pendingApprovals[0];
let stub;
if (coin.supportsTss()) {
stub = sandbox.stub(sdk_core_1.PendingApproval.prototype, 'recreateAndSignTSSTransaction').resolves({
txHex: 'gabagool',
});
}
else {
stub = sandbox.stub(sdk_core_1.PendingApproval.prototype, 'recreateAndSignTransaction').resolves({
state: 'approved',
halfSigned: { txHex: 'gabagool' },
});
}
const paScope = nock(bgUrl)
.put(`/api/v2/${coinName}/pendingapprovals/${pendingApprovalDataTemp.id}`, {
state: 'approved',
halfSigned: type === sdk_core_1.Type.TRANSACTION_REQUEST ? { txHex: 'gabagool' } : undefined,
})
.reply(200, {
...pendingApprovalDataTemp,
state: 'approved',
});
await pendingApproval.approve({ xprv: 'nonsense', walletPassphrase: 'gabagoolio' });
// Should not call build and should call pa
paScope.isDone().should.be.true();
stub.calledOnce.should.equal(recreateTransaction);
});
}
testRecreateTransaction('tbtc', false, sdk_core_1.Type.TRANSACTION_REQUEST);
testRecreateTransaction('tsol', true, sdk_core_1.Type.TRANSACTION_REQUEST);
testRecreateTransaction('tsol', true, sdk_core_1.Type.TRANSACTION_REQUEST_FULL);
testRecreateTransaction('teth', true, sdk_core_1.Type.TRANSACTION_REQUEST_FULL);
describe('recreateAndSignTSSTransaction', function () {
let coin;
before(() => {
coin = bitgo.coin('tsol');
});
it('should call approve and do the TSS flow and fail if the txRequestId is missing', async () => {
const pendingApproval = wallet.pendingApprovals()[0];
const reqId = new sdk_core_1.RequestTracer();
const params = { walletPassphrase: 'test' };
await pendingApproval
.recreateAndSignTSSTransaction(params, reqId)
.should.be.rejectedWith('txRequestId not found');
});
it('should call approve and do the TSS flow and fail if the walletPassphrase is missing', async () => {
const pendingApproval = wallet.pendingApprovals()[0];
pendingApprovalData['txRequestId'] = 'requestTxIdTest';
const reqId = new sdk_core_1.RequestTracer();
const params = {};
await pendingApproval
.recreateAndSignTSSTransaction(params, reqId)
.should.be.rejectedWith('walletPassphrase not found');
});
it('should call approve and do the TSS flow and fail if the wallet is missing', async () => {
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, coin, pendingApprovalData);
const reqId = new sdk_core_1.RequestTracer();
const params = { walletPassphrase: 'test' };
await pendingApproval.recreateAndSignTSSTransaction(params, reqId).should.be.rejectedWith('Wallet not found');
});
it('should get txHex for transactionRequestLite', async () => {
pendingApprovalData['txRequestId'] = 'requestTxIdTest';
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, coin, pendingApprovalData, wallet);
const reqId = new sdk_core_1.RequestTracer();
const txRequestId = 'test';
const walletPassphrase = 'test';
const decryptedPrvResponse = 'decryptedPrv';
const params = { txRequestId, walletPassphrase };
const txRequest = {
apiVersion: 'lite',
txRequestId: txRequestId,
unsignedTxs: [{ signableHex: 'randomhex', serializedTxHex: 'randomhex2', derivationPath: 'm/0' }],
signatureShares: [
{
from: sdk_core_1.SignatureShareType.BITGO,
to: sdk_core_1.SignatureShareType.USER,
share: '9d7159a76700635TEST',
},
],
transactions: [],
userId: 'userId',
date: new Date().toISOString(),
intent: {
intentType: 'payment',
},
latest: true,
walletId: 'walletId',
version: 1,
policiesChecked: false,
walletType: 'hot',
state: 'pendingUserSignature',
};
const decryptedPrv = sandbox.stub(sdk_core_1.Wallet.prototype, 'getPrv');
decryptedPrv.calledOnceWithExactly({ walletPassphrase });
decryptedPrv.resolves(decryptedPrvResponse);
const recreateTxRequest = sandbox.stub(sdk_core_1.TssUtils.prototype, 'recreateTxRequest');
recreateTxRequest.calledOnceWithExactly(txRequest.txRequestId, decryptedPrvResponse, reqId);
recreateTxRequest.resolves(txRequest);
const recreatedTx = await pendingApproval.recreateAndSignTSSTransaction(params, reqId);
recreatedTx.should.be.deepEqual({ txHex: txRequest.unsignedTxs[0].serializedTxHex });
sandbox.verify();
});
it('should get txHex for transactionRequestFull ', async () => {
pendingApprovalData['txRequestId'] = 'requestTxIdTest';
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, coin, pendingApprovalData, wallet);
const reqId = new sdk_core_1.RequestTracer();
const txRequestId = 'test';
const walletPassphrase = 'test';
const decryptedPrvResponse = 'decryptedPrv';
const params = { txRequestId, walletPassphrase };
const txRequest = {
txRequestId: txRequestId,
apiVersion: 'full',
unsignedTxs: [],
transactions: [
{
unsignedTx: { signableHex: 'randomhex', serializedTxHex: 'randomhex2', derivationPath: 'm/0' },
signatureShares: [
{
from: sdk_core_1.SignatureShareType.BITGO,
to: sdk_core_1.SignatureShareType.USER,
share: '9d7159a76700635TEST',
},
],
state: 'initialized',
},
],
userId: 'userId',
date: new Date().toISOString(),
intent: {
intentType: 'payment',
},
latest: true,
walletId: 'walletId',
version: 1,
policiesChecked: false,
walletType: 'hot',
state: 'pendingDelivery',
};
const decryptedPrv = sandbox.stub(sdk_core_1.Wallet.prototype, 'getPrv');
decryptedPrv.calledOnceWithExactly({ walletPassphrase });
decryptedPrv.resolves(decryptedPrvResponse);
const recreateTxRequest = sandbox.stub(sdk_core_1.TssUtils.prototype, 'recreateTxRequest');
recreateTxRequest.calledOnceWithExactly(txRequest.txRequestId, decryptedPrvResponse, reqId);
recreateTxRequest.resolves(txRequest);
const recreatedTx = await pendingApproval.recreateAndSignTSSTransaction(params, reqId);
recreatedTx.should.be.deepEqual({ txHex: txRequest.transactions[0].unsignedTx.serializedTxHex });
sandbox.verify();
});
});
describe('recreateAndSignTransaction', function () {
it('should preserve the verifyTokenEnablement verification flag when rebuilding an enabletoken pending approval (CSHLD-1358)', async () => {
const enableTokenPendingApprovalData = {
id: 'pa-enabletoken',
info: {
type: sdk_core_1.Type.TRANSACTION_REQUEST,
transactionRequest: {
coinSpecific: {
[coin]: {},
},
recipients: [],
buildParams: {
type: 'enabletoken',
},
sourceWallet: walletId,
},
},
state: sdk_core_1.State.PENDING,
creator: 'test',
};
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, basecoin, enableTokenPendingApprovalData, wallet);
const prebuildAndSignStub = sandbox
.stub(sdk_core_1.Wallet.prototype, 'prebuildAndSignTransaction')
.resolves({ txHex: 'signed-tx-hex' });
sandbox.stub(basecoin, 'parseTransaction').resolves({});
await pendingApproval.recreateAndSignTransaction({});
prebuildAndSignStub.calledOnce.should.be.true();
const prebuildParamsArg = prebuildAndSignStub.getCall(0).args[0];
prebuildParamsArg.verification.should.have.property('verifyTokenEnablement', true);
});
it('should not set verifyTokenEnablement for non-enabletoken pending approvals', async () => {
const fanoutPendingApprovalData = {
id: 'pa-fanout',
info: {
type: sdk_core_1.Type.TRANSACTION_REQUEST,
transactionRequest: {
coinSpecific: {
[coin]: {},
},
recipients: [],
buildParams: {
type: 'fanout',
},
sourceWallet: walletId,
},
},
state: sdk_core_1.State.PENDING,
creator: 'test',
};
const pendingApproval = new sdk_core_1.PendingApproval(bitgo, basecoin, fanoutPendingApprovalData, wallet);
const prebuildAndSignStub = sandbox
.stub(sdk_core_1.Wallet.prototype, 'prebuildAndSignTransaction')
.resolves({ txHex: 'signed-tx-hex' });
sandbox.stub(basecoin, 'parseTransaction').resolves({});
await pendingApproval.recreateAndSignTransaction({});
prebuildAndSignStub.calledOnce.should.be.true();
const prebuildParamsArg = prebuildAndSignStub.getCall(0).args[0];
(prebuildParamsArg.verification === undefined).should.be.true();
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVuZGluZ0FwcHJvdmFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC92Mi91bml0L3BlbmRpbmdBcHByb3ZhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBOztHQUVHO0FBQ0gsa0JBQWdCO0FBQ2hCLDZCQUE4QjtBQUM5QiwrQkFBK0I7QUFDL0IsOENBQXdEO0FBQ3hELHNDQUFxQztBQUVyQyw4Q0FleUI7QUFFekIsUUFBUSxDQUFDLG9CQUFvQixFQUFFLEdBQUcsRUFBRTtJQUNsQyxJQUFJLE9BQTJCLENBQUM7SUFDaEMsSUFBSSxLQUF5QixDQUFDO0lBQzlCLElBQUksUUFBa0IsQ0FBQztJQUN2QixJQUFJLE1BQWMsQ0FBQztJQUNuQixJQUFJLEtBQWEsQ0FBQztJQUVsQixNQUFNLElBQUksR0FBRyxNQUFNLENBQUM7SUFDcEIsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDO0lBQzdCLE1BQU0sV0FBVyxHQUFHO1FBQ2xCLFNBQVMsRUFBRSxXQUFXO1FBQ3RCLFlBQVksRUFBRSxlQUFlO1FBQzdCLGNBQWMsRUFBRSxrQkFBa0I7UUFDbEMsaUJBQWlCLEVBQUUsb0JBQW9CO0tBQ3hDLENBQUM7SUFFRixNQUFNLG1CQUFtQixHQUF3QjtRQUMvQyxFQUFFLEVBQUUsS0FBSztRQUNULElBQUksRUFBRTtZQUNKLElBQUksRUFBRSxlQUFJLENBQUMsbUJBQW1CO1lBQzlCLGtCQUFrQixFQUFFO2dCQUNsQixZQUFZLEVBQUU7b0JBQ1osQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO2lCQUNYO2dCQUNELFVBQVUsRUFBRSxFQUFFO2dCQUNkLFdBQVcsRUFBRTtvQkFDWCxJQUFJLEVBQUUsYUFBYTtpQkFDcEI7Z0JBQ0QsWUFBWSxFQUFFLFFBQVE7YUFDdkI7U0FDRjtRQUNELEtBQUssRUFBRSxnQkFBSyxDQUFDLE9BQU87UUFDcEIsT0FBTyxFQUFFLE1BQU07S0FDaEIsQ0FBQztJQUNGLE1BQU0sVUFBVSxHQUFH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QU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFFLENBQUM7WUFDbEUsQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEtBQUssU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsRSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwcmV0dGllclxuICovXG5pbXBvcnQgJ3Nob3VsZCc7XG5pbXBvcnQgbm9jayA9IHJlcXVpcmUoJ25vY2snKTtcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IFRlc3RhYmxlQkcsIFRlc3RCaXRHbyB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uLy4uL3NyYyc7XG5cbmltcG9ydCB7XG4gIEJhc2VDb2luLFxuICBFQ0RTQVV0aWxzLFxuICBFZGRzYVV0aWxzLFxuICBFbnZpcm9ubWVudHMsXG4gIFBlbmRpbmdBcHByb3ZhbCxcbiAgUGVuZGluZ0FwcHJvdmFsRGF0YSxcbiAgUGVuZGluZ0FwcHJvdmFsSW5mbyxcbiAgUmVxdWVzdFRyYWNlcixcbiAgU2lnbmF0dXJlU2hhcmVUeXBlLFxuICBTdGF0ZSxcbiAgVHNzVXRpbHMsXG4gIFR4UmVxdWVzdCxcbiAgVHlwZSxcbiAgV2FsbGV0LFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuXG5kZXNjcmliZSgnUGVuZGluZyBBcHByb3ZhbHM6JywgKCkgPT4ge1xuICBsZXQgc2FuZGJveDogc2lub24uU2lub25TYW5kYm94O1xuICBsZXQgYml0Z286IFRlc3RhYmxlQkcgJiBCaXRHbztcbiAgbGV0IGJhc2Vjb2luOiBCYXNlQ29pbjtcbiAgbGV0IHdhbGxldDogV2FsbGV0O1xuICBsZXQgYmdVcmw6IHN0cmluZztcblxuICBjb25zdCBjb2luID0gJ3RidGMnO1xuICBjb25zdCB3YWxsZXRJZCA9ICd3YWxsZXRfaWQnO1xuICBjb25zdCBhdHRlc3RhdGlvbiA9IHtcbiAgICBzaWduYXR1cmU6ICdzaWduYXR1cmUnLFxuICAgIGNyZWRlbnRpYWxJZDogJ2NyZWRlbnRpYWwtaWQnLFxuICAgIGNsaWVudERhdGFKU09OOiAnY2xpZW50LWRhdGEtanNvbicsXG4gICAgYXV0aGVudGljYXRvckRhdGE6ICdhdXRoZW50aWNhdG9yLWRhdGEnLFxuICB9O1xuXG4gIGNvbnN0IHBlbmRpbmdBcHByb3ZhbERhdGE6IFBlbmRpbmdBcHByb3ZhbERhdGEgPSB7XG4gICAgaWQ6ICdwYTAnLFxuICAgIGluZm86IHtcbiAgICAgIHR5cGU6IFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVCxcbiAgICAgIHRyYW5zYWN0aW9uUmVxdWVzdDoge1xuICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICBbY29pbl06IHt9LFxuICAgICAgICB9LFxuICAgICAgICByZWNpcGllbnRzOiBbXSxcbiAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnY29uc29saWRhdGUnLFxuICAgICAgICB9LFxuICAgICAgICBzb3VyY2VXYWxsZXQ6IHdhbGxldElkLFxuICAgICAgfSxcbiAgICB9LFxuICAgIHN0YXRlOiBTdGF0ZS5QRU5ESU5HLFxuICAgIGNyZWF0b3I6ICd0ZXN0JyxcbiAgfTtcbiAgY29uc3Qgd2FsbGV0RGF0YSA9IHtcbiAgICBpZDogd2FsbGV0SWQsXG4gICAgY29pbixcbiAgICBwZW5kaW5nQXBwcm92YWxzOiBbcGVuZGluZ0FwcHJvdmFsRGF0YV0sXG4gIH07XG5cbiAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcbiAgICBub2NrLmRpc2FibGVOZXRDb25uZWN0KCk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGJlZm9yZShhc3luYyAoKSA9PiB7XG4gICAgLy8gY3JlYXRlIHdhbGxldFxuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJhc2Vjb2luID0gYml0Z28uY29pbihjb2luKTtcblxuICAgIHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB3YWxsZXREYXRhKTtcbiAgICBiZ1VybCA9IEVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICAgIChwZW5kaW5nQXBwcm92YWxEYXRhIGFzIGFueSkud2FsbGV0ID0gd2FsbGV0O1xuICB9KTtcblxuICBbJ3Rzb2wnLCAndGV0aCcsICd0YnRjJ10uZm9yRWFjaCgoY29pbk5hbWUpID0+IHtcbiAgICBpdChgc2hvdWxkIHVzZSBjb3JyZWN0IHRzc1V0aWxzIGZvciAgJHtjb2luTmFtZX1gLCAoKSA9PiB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbihjb2luTmFtZSk7XG4gICAgICBjb25zdCBwZW5kaW5nQXByb3ZhbCA9IG5ldyBQZW5kaW5nQXBwcm92YWwoYml0Z28sIGNvaW4sIHt9IGFzIHVua25vd24gYXMgUGVuZGluZ0FwcHJvdmFsRGF0YSk7XG4gICAgICBpZiAoY29pbi5zdXBwb3J0c1RzcygpKSB7XG4gICAgICAgIGlmIChjb2luLmdldE1QQ0FsZ29yaXRobSgpID09PSAnZWNkc2EnKSB7XG4gICAgICAgICAgcGVuZGluZ0Fwcm92YWxbJ3Rzc1V0aWxzJ10uc2hvdWxkLmJlLmluc3RhbmNlT2YoRUNEU0FVdGlscy5FY2RzYVV0aWxzKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb2luLmdldE1QQ0FsZ29yaXRobSgpID09PSAnZWRkc2EnKSB7XG4gICAgICAgICAgcGVuZGluZ0Fwcm92YWxbJ3Rzc1V0aWxzJ10uc2hvdWxkLmJlLmluc3RhbmNlT2YoRWRkc2FVdGlscyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIChwZW5kaW5nQXByb3ZhbFsndHNzVXRpbHMnXSA9PT0gdW5kZWZpbmVkKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBbJ01QQ3YyJywgdW5kZWZpbmVkXS5mb3JFYWNoKChtdWx0aXNpZ1R5cGVWZXJzaW9uKSA9PiB7XG4gICAgaXQoYHNob3VsZCB1c2UgY29ycmVjdCB0c3NVdGlscyBmb3IgbXVsdGlzaWdUeXBlVmVyc2lvbjogJHttdWx0aXNpZ1R5cGVWZXJzaW9ufWAsICgpID0+IHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCdodGV0aCcpO1xuICAgICAgY29uc3Qgd2FsbGV0RGF0YU1wY1YyID0ge1xuICAgICAgICAuLi53YWxsZXREYXRhLFxuICAgICAgICBtdWx0aXNpZ1R5cGVWZXJzaW9uOiBtdWx0aXNpZ1R5cGVWZXJzaW9uLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHdhbGxldE1QQ3YyID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHdhbGxldERhdGFNcGNWMik7XG5cbiAgICAgIGNvbnN0IHBlbmRpbmdBcHJvdmFsID0gbmV3IFBlbmRpbmdBcHByb3ZhbChiaXRnbywgY29pbiwge30gYXMgdW5rbm93biBhcyBQZW5kaW5nQXBwcm92YWxEYXRhLCB3YWxsZXRNUEN2Mik7XG4gICAgICBpZiAod2FsbGV0TVBDdjIubXVsdGlzaWdUeXBlVmVyc2lvbigpID09PSAnTVBDdjInKSB7XG4gICAgICAgIHBlbmRpbmdBcHJvdmFsWyd0c3NVdGlscyddLnNob3VsZC5iZS5pbnN0YW5jZU9mKEVDRFNBVXRpbHMuRWNkc2FNUEN2MlV0aWxzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlbmRpbmdBcHJvdmFsWyd0c3NVdGlscyddLnNob3VsZC5iZS5pbnN0YW5jZU9mKEVDRFNBVXRpbHMuRWNkc2FVdGlscyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgY2FsbCBjb25zb2xpZGF0ZSBpbnN0ZWFkIG9mIGJ1aWxkIHdoZW4gcmVidWlsZGluZyBjb25zb2xpZGF0aW9uIHBlbmRpbmcgYXBwcm92YWxzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNjb3BlID0gbm9jayhiZ1VybCkucG9zdChgL2FwaS92Mi8ke2NvaW59L3dhbGxldC8ke3dhbGxldElkfS9jb25zb2xpZGF0ZVVuc3BlbnRzYCkucmVwbHkoMjAwKTtcbiAgICBjb25zdCBwZW5kaW5nQXBwcm92YWxzID0gd2FsbGV0LnBlbmRpbmdBcHByb3ZhbHMoKTtcbiAgICBwZW5kaW5nQXBwcm92YWxzLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICBjb25zdCBwZW5kaW5nQXBwcm92YWwgPSBwZW5kaW5nQXBwcm92YWxzWzBdO1xuXG4gICAgLy8gYXBwcm92YWwgd2lsbCBmYWlsIHdoZW4gYXR0ZW1wdGluZyB0byByZXNpZ24uIFRoaXMgaXMgb2sgLSB3ZSBqdXN0IHdhbnQgdG8gbWFrZSBzdXJlXG4gICAgLy8gdGhlIGNvbnNvbGlkYXRlVW5zcGVudHMgZW5kcG9pbnQgd2FzIGNhbGxlZCBhbHJlYWR5IGJlZm9yZSBmYWlsaW5nXG4gICAgYXdhaXQgcGVuZGluZ0FwcHJvdmFsLmFwcHJvdmUoeyB4cHJ2OiAnbm9uc2Vuc2UnIH0pLnNob3VsZC5iZS5yZWplY3RlZCgpO1xuXG4gICAgc2NvcGUuZG9uZSgpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGFwcHJvdmUgZm9yIHRyYW5zYWN0aW9uUmVxdWVzdExpdGUgaWYgd2UgY2Fubm90IHJlY3JlYXRlIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbERhdGEyID0geyAuLi5wZW5kaW5nQXBwcm92YWxEYXRhLCB0eFJlcXVlc3RJZDogJzEyMzQtNDU2Ny02Nzg5JyB9O1xuICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IG5ldyBQZW5kaW5nQXBwcm92YWwoYml0Z28sIGJhc2Vjb2luLCBwZW5kaW5nQXBwcm92YWxEYXRhMiwgd2FsbGV0KTtcblxuICAgIGNvbnN0IHBhU2NvcGUgPSBub2NrKGJnVXJsKVxuICAgICAgLnB1dChgL2FwaS92Mi8ke2NvaW59L3BlbmRpbmdhcHByb3ZhbHMvJHtwZW5kaW5nQXBwcm92YWxEYXRhLmlkfWAsIHtcbiAgICAgICAgc3RhdGU6ICdhcHByb3ZlZCcsXG4gICAgICAgIG90cDogdW5kZWZpbmVkLFxuICAgICAgfSlcbiAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgLi4ucGVuZGluZ0FwcHJvdmFsRGF0YTIsXG4gICAgICAgIHN0YXRlOiAnYXBwcm92ZWQnLFxuICAgICAgfSk7XG4gICAgY29uc3QgcmVjcmVhdGVUcmFuc2FjdGlvblRzc1N0dWIgPSBzYW5kYm94LnN0dWIoUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZSwgJ3JlY3JlYXRlQW5kU2lnblRTU1RyYW5zYWN0aW9uJyk7XG4gICAgY29uc3QgcmVjcmVhdGVUcmFuc2FjdGlvblN0dWIgPSBzYW5kYm94LnN0dWIoUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZSwgJ3JlY3JlYXRlQW5kU2lnblRyYW5zYWN0aW9uJyk7XG5cbiAgICBwZW5kaW5nQXBwcm92YWwudHlwZSgpLnNob3VsZC5lcXVhbChUeXBlLlRSQU5TQUNUSU9OX1JFUVVFU1QpO1xuICAgIGF3YWl0IHBlbmRpbmdBcHByb3ZhbC5hcHByb3ZlKHt9KTtcbiAgICByZWNyZWF0ZVRyYW5zYWN0aW9uVHNzU3R1Yi5ub3RDYWxsZWQuc2hvdWxkLmJlLnRydWUoKTtcbiAgICByZWNyZWF0ZVRyYW5zYWN0aW9uU3R1Yi5ub3RDYWxsZWQuc2hvdWxkLmJlLnRydWUoKTtcblxuICAgIHBhU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBwYXNzIGF0dGVzdGF0aW9uIHdpdGhvdXQgYnlwYXNzaW5nIG11bHRpc2lnIGhhbGYtc2lnbmluZycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwZW5kaW5nQXBwcm92YWwgPSBuZXcgUGVuZGluZ0FwcHJvdmFsKGJpdGdvLCBiYXNlY29pbiwgcGVuZGluZ0FwcHJvdmFsRGF0YSwgd2FsbGV0KTtcbiAgICBjb25zdCBoYWxmU2lnbmVkVHhIZXggPSAnaGFsZi1zaWduZWQtdHJhbnNhY3Rpb24nO1xuICAgIGNvbnN0IHBhU2NvcGUgPSBub2NrKGJnVXJsKVxuICAgICAgLnB1dChgL2FwaS92Mi8ke2NvaW59L3BlbmRpbmdhcHByb3ZhbHMvJHtwZW5kaW5nQXBwcm92YWxEYXRhLmlkfWAsIHtcbiAgICAgICAgc3RhdGU6ICdhcHByb3ZlZCcsXG4gICAgICAgIGF0dGVzdGF0aW9uLFxuICAgICAgICBoYWxmU2lnbmVkOiB7IHR4SGV4OiBoYWxmU2lnbmVkVHhIZXggfSxcbiAgICAgIH0pXG4gICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgIC4uLnBlbmRpbmdBcHByb3ZhbERhdGEsXG4gICAgICAgIHN0YXRlOiAnYXBwcm92ZWQnLFxuICAgICAgfSk7XG5cbiAgICBhd2FpdCBwZW5kaW5nQXBwcm92YWwuYXBwcm92ZSh7IHR4OiBoYWxmU2lnbmVkVHhIZXgsIGF0dGVzdGF0aW9uIH0pO1xuXG4gICAgcGFTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICB9KTtcblxuICBmdW5jdGlvbiB0ZXN0UmVjcmVhdGVUcmFuc2FjdGlvbihjb2luTmFtZTogc3RyaW5nLCByZWNyZWF0ZVRyYW5zYWN0aW9uOiBib29sZWFuLCB0eXBlOiBUeXBlKSB7XG4gICAgaXQoYFske2NvaW5OYW1lfV0gc2hvdWxkICR7XG4gICAgICByZWNyZWF0ZVRyYW5zYWN0aW9uID8gJ25vdCAnIDogJydcbiAgICB9cmVjcmVhdGUgdGhlIHRyYW5zYWN0aW9uIGR1cmluZyBhcHByb3ZpbmcgYSBwZW5kaW5nIGFwcHJvdmFsIGlmIHRoZXJlIGFyZSBubyByZWNpcGllbnRzIGZvciBQQSB0eXBlICR7dHlwZX1gLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbihjb2luTmFtZSk7XG4gICAgICBjb25zdCB0eFJlcXVlc3RJZCA9IGNvaW4uc3VwcG9ydHNUc3MoKSA/ICdyZXF1ZXN0VHhJZFRlc3QnIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsSW5mbyA9XG4gICAgICAgIHR5cGUgPT09ICd0cmFuc2FjdGlvblJlcXVlc3QnXG4gICAgICAgICAgPyB7XG4gICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9uUmVxdWVzdDoge1xuICAgICAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICAgICAgW2NvaW5OYW1lXTogeyB0eEhleDogJ2dhYmFnb29sJyB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVjaXBpZW50czogW10sXG4gICAgICAgICAgICAgICAgYnVpbGRQYXJhbXM6IHt9LFxuICAgICAgICAgICAgICAgIHNvdXJjZVdhbGxldDogd2FsbGV0SWQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiAoeyB0eXBlIH0gYXMgdW5rbm93biBhcyBQZW5kaW5nQXBwcm92YWxJbmZvKTtcbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbERhdGFUZW1wOiBQZW5kaW5nQXBwcm92YWxEYXRhID0ge1xuICAgICAgICBpZDogJ3BhMCcsXG4gICAgICAgIGluZm86IHBlbmRpbmdBcHByb3ZhbEluZm8sXG4gICAgICAgIHdhbGxldDogd2FsbGV0SWQsXG4gICAgICAgIHN0YXRlOiBTdGF0ZS5QRU5ESU5HLFxuICAgICAgICBjcmVhdG9yOiAndGVzdCcsXG4gICAgICAgIHR4UmVxdWVzdElkLFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgd2FsbGV0RGF0YVRlbXAgPSB7XG4gICAgICAgIGlkOiB3YWxsZXRJZCxcbiAgICAgICAgY29pbk5hbWUsXG4gICAgICAgIHBlbmRpbmdBcHByb3ZhbHM6IFtwZW5kaW5nQXBwcm92YWxEYXRhVGVtcF0sXG4gICAgICB9O1xuICAgICAgY29uc3Qgd2FsbGV0VGVtcCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHdhbGxldERhdGFUZW1wKTtcbiAgICAgIHBlbmRpbmdBcHByb3ZhbERhdGFUZW1wLndhbGxldCA9IHdhbGxldFRlbXAuaWQoKTtcblxuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFscyA9IHdhbGxldFRlbXAucGVuZGluZ0FwcHJvdmFscygpO1xuICAgICAgcGVuZGluZ0FwcHJvdmFscy5zaG91bGQuaGF2ZS5sZW5ndGgoMSk7XG4gICAgICBjb25zdCBwZW5kaW5nQXBwcm92YWwgPSBwZW5kaW5nQXBwcm92YWxzWzBdO1xuXG4gICAgICBsZXQgc3R1Yjogc2lub24uU2lub25TdHViO1xuICAgICAgaWYgKGNvaW4uc3VwcG9ydHNUc3MoKSkge1xuICAgICAgICBzdHViID0gc2FuZGJveC5zdHViKFBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUsICdyZWNyZWF0ZUFuZFNpZ25UU1NUcmFuc2FjdGlvbicpLnJlc29sdmVzKHtcbiAgICAgICAgICB0eEhleDogJ2dhYmFnb29sJyxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHViID0gc2FuZGJveC5zdHViKFBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUsICdyZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbicpLnJlc29sdmVzKHtcbiAgICAgICAgICBzdGF0ZTogJ2FwcHJvdmVkJyxcbiAgICAgICAgICBoYWxmU2lnbmVkOiB7IHR4SGV4OiAnZ2FiYWdvb2wnIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYVNjb3BlID0gbm9jayhiZ1VybClcbiAgICAgICAgLnB1dChgL2FwaS92Mi8ke2NvaW5OYW1lfS9wZW5kaW5nYXBwcm92YWxzLyR7cGVuZGluZ0FwcHJvdmFsRGF0YVRlbXAuaWR9YCwge1xuICAgICAgICAgIHN0YXRlOiAnYXBwcm92ZWQnLFxuICAgICAgICAgIGhhbGZTaWduZWQ6IHR5cGUgPT09IFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVCA/IHsgdHhIZXg6ICdnYWJhZ29vbCcgfSA6IHVuZGVmaW5lZCxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgIC4uLnBlbmRpbmdBcHByb3ZhbERhdGFUZW1wLFxuICAgICAgICAgIHN0YXRlOiAnYXBwcm92ZWQnLFxuICAgICAgICB9KTtcblxuICAgICAgYXdhaXQgcGVuZGluZ0FwcHJvdmFsLmFwcHJvdmUoeyB4cHJ2OiAnbm9uc2Vuc2UnLCB3YWxsZXRQYXNzcGhyYXNlOiAnZ2FiYWdvb2xpbycgfSk7XG5cbiAgICAgIC8vIFNob3VsZCBub3QgY2FsbCBidWlsZCBhbmQgc2hvdWxkIGNhbGwgcGFcbiAgICAgIHBhU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIHN0dWIuY2FsbGVkT25jZS5zaG91bGQuZXF1YWwocmVjcmVhdGVUcmFuc2FjdGlvbik7XG4gICAgfSk7XG4gIH1cblxuICB0ZXN0UmVjcmVhdGVUcmFuc2FjdGlvbigndGJ0YycsIGZhbHNlLCBUeXBlLlRSQU5TQUNUSU9OX1JFUVVFU1QpO1xuICB0ZXN0UmVjcmVhdGVUcmFuc2FjdGlvbigndHNvbCcsIHRydWUsIFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVCk7XG4gIHRlc3RSZWNyZWF0ZVRyYW5zYWN0aW9uKCd0c29sJywgdHJ1ZSwgVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNUX0ZVTEwpO1xuICB0ZXN0UmVjcmVhdGVUcmFuc2FjdGlvbigndGV0aCcsIHRydWUsIFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVF9GVUxMKTtcblxuICBkZXNjcmliZSgncmVjcmVhdGVBbmRTaWduVFNTVHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGNvaW46IEJhc2VDb2luO1xuXG4gICAgYmVmb3JlKCgpID0+IHtcbiAgICAgIGNvaW4gPSBiaXRnby5jb2luKCd0c29sJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgYXBwcm92ZSBhbmQgZG8gdGhlIFRTUyBmbG93IGFuZCBmYWlsIGlmIHRoZSB0eFJlcXVlc3RJZCBpcyBtaXNzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gd2FsbGV0LnBlbmRpbmdBcHByb3ZhbHMoKVswXTtcbiAgICAgIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHsgd2FsbGV0UGFzc3BocmFzZTogJ3Rlc3QnIH07XG4gICAgICBhd2FpdCBwZW5kaW5nQXBwcm92YWxcbiAgICAgICAgLnJlY3JlYXRlQW5kU2lnblRTU1RyYW5zYWN0aW9uKHBhcmFtcywgcmVxSWQpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCd0eFJlcXVlc3RJZCBub3QgZm91bmQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBhcHByb3ZlIGFuZCBkbyB0aGUgVFNTIGZsb3cgYW5kIGZhaWwgaWYgdGhlIHdhbGxldFBhc3NwaHJhc2UgaXMgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IHdhbGxldC5wZW5kaW5nQXBwcm92YWxzKClbMF07XG4gICAgICBwZW5kaW5nQXBwcm92YWxEYXRhWyd0eFJlcXVlc3RJZCddID0gJ3JlcXVlc3RUeElkVGVzdCc7XG4gICAgICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7fTtcbiAgICAgIGF3YWl0IHBlbmRpbmdBcHByb3ZhbFxuICAgICAgICAucmVjcmVhdGVBbmRTaWduVFNTVHJhbnNhY3Rpb24ocGFyYW1zLCByZXFJZClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3dhbGxldFBhc3NwaHJhc2Ugbm90IGZvdW5kJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgYXBwcm92ZSBhbmQgZG8gdGhlIFRTUyBmbG93IGFuZCBmYWlsIGlmIHRoZSB3YWxsZXQgaXMgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IG5ldyBQZW5kaW5nQXBwcm92YWwoYml0Z28sIGNvaW4sIHBlbmRpbmdBcHByb3ZhbERhdGEpO1xuICAgICAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICAgICAgY29uc3QgcGFyYW1zID0geyB3YWxsZXRQYXNzcGhyYXNlOiAndGVzdCcgfTtcbiAgICAgIGF3YWl0IHBlbmRpbmdBcHByb3ZhbC5yZWNyZWF0ZUFuZFNpZ25UU1NUcmFuc2FjdGlvbihwYXJhbXMsIHJlcUlkKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdXYWxsZXQgbm90IGZvdW5kJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdldCB0eEhleCBmb3IgdHJhbnNhY3Rpb25SZXF1ZXN0TGl0ZScsIGFzeW5jICgpID0+IHtcbiAgICAgIHBlbmRpbmdBcHByb3ZhbERhdGFbJ3R4UmVxdWVzdElkJ10gPSAncmVxdWVzdFR4SWRUZXN0JztcbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IG5ldyBQZW5kaW5nQXBwcm92YWwoYml0Z28sIGNvaW4sIHBlbmRpbmdBcHByb3ZhbERhdGEsIHdhbGxldCk7XG4gICAgICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gICAgICBjb25zdCB0eFJlcXVlc3RJZCA9ICd0ZXN0JztcbiAgICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdCc7XG4gICAgICBjb25zdCBkZWNyeXB0ZWRQcnZSZXNwb25zZSA9ICdkZWNyeXB0ZWRQcnYnO1xuICAgICAgY29uc3QgcGFyYW1zID0geyB0eFJlcXVlc3RJZCwgd2FsbGV0UGFzc3BocmFzZSB9O1xuICAgICAgY29uc3QgdHhSZXF1ZXN0OiBUeFJlcXVlc3QgPSB7XG4gICAgICAgIGFwaVZlcnNpb246ICdsaXRlJyxcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdElkLFxuICAgICAgICB1bnNpZ25lZFR4czogW3sgc2lnbmFibGVIZXg6ICdyYW5kb21oZXgnLCBzZXJpYWxpemVkVHhIZXg6ICdyYW5kb21oZXgyJywgZGVyaXZhdGlvblBhdGg6ICdtLzAnIH1dLFxuICAgICAgICBzaWduYXR1cmVTaGFyZXM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgICAgICBzaGFyZTogJzlkNzE1OWE3NjcwMDYzNVRFU1QnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHRyYW5zYWN0aW9uczogW10sXG4gICAgICAgIHVzZXJJZDogJ3VzZXJJZCcsXG4gICAgICAgIGRhdGU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgaW50ZW50OiB7XG4gICAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgICB9LFxuICAgICAgICBsYXRlc3Q6IHRydWUsXG4gICAgICAgIHdhbGxldElkOiAnd2FsbGV0SWQnLFxuICAgICAgICB2ZXJzaW9uOiAxLFxuICAgICAgICBwb2xpY2llc0NoZWNrZWQ6IGZhbHNlLFxuICAgICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgICAgc3RhdGU6ICdwZW5kaW5nVXNlclNpZ25hdHVyZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBkZWNyeXB0ZWRQcnYgPSBzYW5kYm94LnN0dWIoV2FsbGV0LnByb3RvdHlwZSwgJ2dldFBydicpO1xuICAgICAgZGVjcnlwdGVkUHJ2LmNhbGxlZE9uY2VXaXRoRXhhY3RseSh7IHdhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgICBkZWNyeXB0ZWRQcnYucmVzb2x2ZXMoZGVjcnlwdGVkUHJ2UmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCByZWNyZWF0ZVR4UmVxdWVzdCA9IHNhbmRib3guc3R1YihUc3NVdGlscy5wcm90b3R5cGUsICdyZWNyZWF0ZVR4UmVxdWVzdCcpO1xuICAgICAgcmVjcmVhdGVUeFJlcXVlc3QuY2FsbGVkT25jZVdpdGhFeGFjdGx5KHR4UmVxdWVzdC50eFJlcXVlc3RJZCwgZGVjcnlwdGVkUHJ2UmVzcG9uc2UsIHJlcUlkKTtcbiAgICAgIHJlY3JlYXRlVHhSZXF1ZXN0LnJlc29sdmVzKHR4UmVxdWVzdCk7XG5cbiAgICAgIGNvbnN0IHJlY3JlYXRlZFR4ID0gYXdhaXQgcGVuZGluZ0FwcHJvdmFsLnJlY3JlYXRlQW5kU2lnblRTU1RyYW5zYWN0aW9uKHBhcmFtcywgcmVxSWQpO1xuICAgICAgcmVjcmVhdGVkVHguc2hvdWxkLmJlLmRlZXBFcXVhbCh7IHR4SGV4OiB0eFJlcXVlc3QudW5zaWduZWRUeHNbMF0uc2VyaWFsaXplZFR4SGV4IH0pO1xuXG4gICAgICBzYW5kYm94LnZlcmlmeSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZXQgdHhIZXggZm9yIHRyYW5zYWN0aW9uUmVxdWVzdEZ1bGwgJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcGVuZGluZ0FwcHJvdmFsRGF0YVsndHhSZXF1ZXN0SWQnXSA9ICdyZXF1ZXN0VHhJZFRlc3QnO1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gbmV3IFBlbmRpbmdBcHByb3ZhbChiaXRnbywgY29pbiwgcGVuZGluZ0FwcHJvdmFsRGF0YSwgd2FsbGV0KTtcbiAgICAgIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdElkID0gJ3Rlc3QnO1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICd0ZXN0JztcbiAgICAgIGNvbnN0IGRlY3J5cHRlZFBydlJlc3BvbnNlID0gJ2RlY3J5cHRlZFBydic7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7IHR4UmVxdWVzdElkLCB3YWxsZXRQYXNzcGhyYXNlIH07XG4gICAgICBjb25zdCB0eFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdElkLFxuICAgICAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgICAgIHVuc2lnbmVkVHhzOiBbXSxcbiAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdW5zaWduZWRUeDogeyBzaWduYWJsZUhleDogJ3JhbmRvbWhleCcsIHNlcmlhbGl6ZWRUeEhleDogJ3JhbmRvbWhleDInLCBkZXJpdmF0aW9uUGF0aDogJ20vMCcgfSxcbiAgICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICAgICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgICAgICAgICBzaGFyZTogJzlkNzE1OWE3NjcwMDYzNVRFU1QnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHN0YXRlOiAnaW5pdGlhbGl6ZWQnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHVzZXJJZDogJ3VzZXJJZCcsXG4gICAgICAgIGRhdGU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgaW50ZW50OiB7XG4gICAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgICB9LFxuICAgICAgICBsYXRlc3Q6IHRydWUsXG4gICAgICAgIHdhbGxldElkOiAnd2FsbGV0SWQnLFxuICAgICAgICB2ZXJzaW9uOiAxLFxuICAgICAgICBwb2xpY2llc0NoZWNrZWQ6IGZhbHNlLFxuICAgICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgICAgc3RhdGU6ICdwZW5kaW5nRGVsaXZlcnknLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZGVjcnlwdGVkUHJ2ID0gc2FuZGJveC5zdHViKFdhbGxldC5wcm90b3R5cGUsICdnZXRQcnYnKTtcbiAgICAgIGRlY3J5cHRlZFBydi5jYWxsZWRPbmNlV2l0aEV4YWN0bHkoeyB3YWxsZXRQYXNzcGhyYXNlIH0pO1xuICAgICAgZGVjcnlwdGVkUHJ2LnJlc29sdmVzKGRlY3J5cHRlZFBydlJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgcmVjcmVhdGVUeFJlcXVlc3QgPSBzYW5kYm94LnN0dWIoVHNzVXRpbHMucHJvdG90eXBlLCAncmVjcmVhdGVUeFJlcXVlc3QnKTtcbiAgICAgIHJlY3JlYXRlVHhSZXF1ZXN0LmNhbGxlZE9uY2VXaXRoRXhhY3RseSh0eFJlcXVlc3QudHhSZXF1ZXN0SWQsIGRlY3J5cHRlZFBydlJlc3BvbnNlLCByZXFJZCk7XG4gICAgICByZWNyZWF0ZVR4UmVxdWVzdC5yZXNvbHZlcyh0eFJlcXVlc3QpO1xuXG4gICAgICBjb25zdCByZWNyZWF0ZWRUeCA9IGF3YWl0IHBlbmRpbmdBcHByb3ZhbC5yZWNyZWF0ZUFuZFNpZ25UU1NUcmFuc2FjdGlvbihwYXJhbXMsIHJlcUlkKTtcbiAgICAgIHJlY3JlYXRlZFR4LnNob3VsZC5iZS5kZWVwRXF1YWwoeyB0eEhleDogdHhSZXF1ZXN0LnRyYW5zYWN0aW9ucyFbMF0udW5zaWduZWRUeC5zZXJpYWxpemVkVHhIZXggfSk7XG5cbiAgICAgIHNhbmRib3gudmVyaWZ5KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIHRoZSB2ZXJpZnlUb2tlbkVuYWJsZW1lbnQgdmVyaWZpY2F0aW9uIGZsYWcgd2hlbiByZWJ1aWxkaW5nIGFuIGVuYWJsZXRva2VuIHBlbmRpbmcgYXBwcm92YWwgKENTSExELTEzNTgpJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZW5hYmxlVG9rZW5QZW5kaW5nQXBwcm92YWxEYXRhOiBQZW5kaW5nQXBwcm92YWxEYXRhID0ge1xuICAgICAgICBpZDogJ3BhLWVuYWJsZXRva2VuJyxcbiAgICAgICAgaW5mbzoge1xuICAgICAgICAgIHR5cGU6IFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVCxcbiAgICAgICAgICB0cmFuc2FjdGlvblJlcXVlc3Q6IHtcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICBbY29pbl06IHt9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFtdLFxuICAgICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzb3VyY2VXYWxsZXQ6IHdhbGxldElkLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHN0YXRlOiBTdGF0ZS5QRU5ESU5HLFxuICAgICAgICBjcmVhdG9yOiAndGVzdCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gbmV3IFBlbmRpbmdBcHByb3ZhbChiaXRnbywgYmFzZWNvaW4sIGVuYWJsZVRva2VuUGVuZGluZ0FwcHJvdmFsRGF0YSwgd2FsbGV0KTtcblxuICAgICAgY29uc3QgcHJlYnVpbGRBbmRTaWduU3R1YiA9IHNhbmRib3hcbiAgICAgICAgLnN0dWIoV2FsbGV0LnByb3RvdHlwZSwgJ3ByZWJ1aWxkQW5kU2lnblRyYW5zYWN0aW9uJylcbiAgICAgICAgLnJlc29sdmVzKHsgdHhIZXg6ICdzaWduZWQtdHgtaGV4JyB9KTtcbiAgICAgIHNhbmRib3guc3R1YihiYXNlY29pbiwgJ3BhcnNlVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh7fSk7XG5cbiAgICAgIGF3YWl0IHBlbmRpbmdBcHByb3ZhbC5yZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbih7fSk7XG5cbiAgICAgIHByZWJ1aWxkQW5kU2lnblN0dWIuY2FsbGVkT25jZS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgY29uc3QgcHJlYnVpbGRQYXJhbXNBcmcgPSBwcmVidWlsZEFuZFNpZ25TdHViLmdldENhbGwoMCkuYXJnc1swXSE7XG4gICAgICBwcmVidWlsZFBhcmFtc0FyZy52ZXJpZmljYXRpb24hLnNob3VsZC5oYXZlLnByb3BlcnR5KCd2ZXJpZnlUb2tlbkVuYWJsZW1lbnQnLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHNldCB2ZXJpZnlUb2tlbkVuYWJsZW1lbnQgZm9yIG5vbi1lbmFibGV0b2tlbiBwZW5kaW5nIGFwcHJvdmFscycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZhbm91dFBlbmRpbmdBcHByb3ZhbERhdGE6IFBlbmRpbmdBcHByb3ZhbERhdGEgPSB7XG4gICAgICAgIGlkOiAncGEtZmFub3V0JyxcbiAgICAgICAgaW5mbzoge1xuICAgICAgICAgIHR5cGU6IFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVCxcbiAgICAgICAgICB0cmFuc2FjdGlvblJlcXVlc3Q6IHtcbiAgICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgICBbY29pbl06IHt9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFtdLFxuICAgICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ2Zhbm91dCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc291cmNlV2FsbGV0OiB3YWxsZXRJZCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBzdGF0ZTogU3RhdGUuUEVORElORyxcbiAgICAgICAgY3JlYXRvcjogJ3Rlc3QnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IG5ldyBQZW5kaW5nQXBwcm92YWwoYml0Z28sIGJhc2Vjb2luLCBmYW5vdXRQZW5kaW5nQXBwcm92YWxEYXRhLCB3YWxsZXQpO1xuXG4gICAgICBjb25zdCBwcmVidWlsZEFuZFNpZ25TdHViID0gc2FuZGJveFxuICAgICAgICAuc3R1YihXYWxsZXQucHJvdG90eXBlLCAncHJlYnVpbGRBbmRTaWduVHJhbnNhY3Rpb24nKVxuICAgICAgICAucmVzb2x2ZXMoeyB0eEhleDogJ3NpZ25lZC10eC1oZXgnIH0pO1xuICAgICAgc2FuZGJveC5zdHViKGJhc2Vjb2luLCAncGFyc2VUcmFuc2FjdGlvbicpLnJlc29sdmVzKHt9KTtcblxuICAgICAgYXdhaXQgcGVuZGluZ0FwcHJvdmFsLnJlY3JlYXRlQW5kU2lnblRyYW5zYWN0aW9uKHt9KTtcblxuICAgICAgcHJlYnVpbGRBbmRTaWduU3R1Yi5jYWxsZWRPbmNlLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBjb25zdCBwcmVidWlsZFBhcmFtc0FyZyA9IHByZWJ1aWxkQW5kU2lnblN0dWIuZ2V0Q2FsbCgwKS5hcmdzWzBdITtcbiAgICAgIChwcmVidWlsZFBhcmFtc0FyZy52ZXJpZmljYXRpb24gPT09IHVuZGVmaW5lZCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==