bitgo
Version:
BitGo JavaScript SDK
308 lines • 46.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 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();
});
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();
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVuZGluZ0FwcHJvdmFsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC92Mi91bml0L3BlbmRpbmdBcHByb3ZhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBOztHQUVHO0FBQ0gsa0JBQWdCO0FBQ2hCLDZCQUE4QjtBQUM5QiwrQkFBK0I7QUFDL0IsOENBQXdEO0FBQ3hELHNDQUFxQztBQUVyQyw4Q0FleUI7QUFFekIsUUFBUSxDQUFDLG9CQUFvQixFQUFFLEdBQUcsRUFBRTtJQUNsQyxJQUFJLE9BQTJCLENBQUM7SUFDaEMsSUFBSSxLQUF5QixDQUFDO0lBQzlCLElBQUksUUFBa0IsQ0FBQztJQUN2QixJQUFJLE1BQWMsQ0FBQztJQUNuQixJQUFJLEtBQWEsQ0FBQztJQUVsQixNQUFNLElBQUksR0FBRyxNQUFNLENBQUM7SUFDcEIsTUFBTSxRQUFRLEdBQUcsV0FBVyxDQUFDO0lBRTdCLE1BQU0sbUJBQW1CLEdBQXdCO1FBQy9DLEVBQUUsRUFBRSxLQUFLO1FBQ1QsSUFBSSxFQUFFO1lBQ0osSUFBSSxFQUFFLGVBQUksQ0FBQyxtQkFBbUI7WUFDOUIsa0JBQWtCLEVBQUU7Z0JBQ2xCLFlBQVksRUFBRTtvQkFDWixDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7aUJBQ1g7Z0JBQ0QsVUFBVSxFQUFFLEVBQUU7Z0JBQ2QsV0FBVyxFQUFFO29CQUNYLElBQUksRUFBRSxhQUFhO2lCQUNwQjtnQkFDRCxZQUFZLEVBQUUsUUFBUTthQUN2QjtTQUNGO1FBQ0QsS0FBSyxFQUFFLGdCQUFLLENBQUMsT0FBTztRQUNwQixPQUFPLEVBQUUsTUFBTTtLQUNoQixDQUFDO0lBQ0YsTUFBTSxVQUFVLEdBQUc7UUFDakIsRUFBRSxFQUFFLFFBQVE7UUFDWixJQUFJO1FBQ0osZ0JBQWdCLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztLQUN4QyxDQUFDO0lBRUYsVUFBVSxDQUFDO1FBQ1QsT0FBTyxHQUFHLEtBQUssQ0FBQyxhQUFh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QUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLFlBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQztZQUVsRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0ICdzaG91bGQnO1xuaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgeyBUZXN0YWJsZUJHLCBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R28gfSBmcm9tICcuLi8uLi8uLi9zcmMnO1xuXG5pbXBvcnQge1xuICBCYXNlQ29pbixcbiAgRUNEU0FVdGlscyxcbiAgRWRkc2FVdGlscyxcbiAgRW52aXJvbm1lbnRzLFxuICBQZW5kaW5nQXBwcm92YWwsXG4gIFBlbmRpbmdBcHByb3ZhbERhdGEsXG4gIFBlbmRpbmdBcHByb3ZhbEluZm8sXG4gIFJlcXVlc3RUcmFjZXIsXG4gIFNpZ25hdHVyZVNoYXJlVHlwZSxcbiAgU3RhdGUsXG4gIFRzc1V0aWxzLFxuICBUeFJlcXVlc3QsXG4gIFR5cGUsXG4gIFdhbGxldCxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcblxuZGVzY3JpYmUoJ1BlbmRpbmcgQXBwcm92YWxzOicsICgpID0+IHtcbiAgbGV0IHNhbmRib3g6IHNpbm9uLlNpbm9uU2FuZGJveDtcbiAgbGV0IGJpdGdvOiBUZXN0YWJsZUJHICYgQml0R287XG4gIGxldCBiYXNlY29pbjogQmFzZUNvaW47XG4gIGxldCB3YWxsZXQ6IFdhbGxldDtcbiAgbGV0IGJnVXJsOiBzdHJpbmc7XG5cbiAgY29uc3QgY29pbiA9ICd0YnRjJztcbiAgY29uc3Qgd2FsbGV0SWQgPSAnd2FsbGV0X2lkJztcblxuICBjb25zdCBwZW5kaW5nQXBwcm92YWxEYXRhOiBQZW5kaW5nQXBwcm92YWxEYXRhID0ge1xuICAgIGlkOiAncGEwJyxcbiAgICBpbmZvOiB7XG4gICAgICB0eXBlOiBUeXBlLlRSQU5TQUNUSU9OX1JFUVVFU1QsXG4gICAgICB0cmFuc2FjdGlvblJlcXVlc3Q6IHtcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgW2NvaW5dOiB7fSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVjaXBpZW50czogW10sXG4gICAgICAgIGJ1aWxkUGFyYW1zOiB7XG4gICAgICAgICAgdHlwZTogJ2NvbnNvbGlkYXRlJyxcbiAgICAgICAgfSxcbiAgICAgICAgc291cmNlV2FsbGV0OiB3YWxsZXRJZCxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBzdGF0ZTogU3RhdGUuUEVORElORyxcbiAgICBjcmVhdG9yOiAndGVzdCcsXG4gIH07XG4gIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgaWQ6IHdhbGxldElkLFxuICAgIGNvaW4sXG4gICAgcGVuZGluZ0FwcHJvdmFsczogW3BlbmRpbmdBcHByb3ZhbERhdGFdLFxuICB9O1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgbm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuICB9KTtcblxuICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3gucmVzdG9yZSgpO1xuICB9KTtcblxuICBiZWZvcmUoYXN5bmMgKCkgPT4ge1xuICAgIC8vIGNyZWF0ZSB3YWxsZXRcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHbywgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oY29pbik7XG5cbiAgICB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwgd2FsbGV0RGF0YSk7XG4gICAgYmdVcmwgPSBFbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaTtcbiAgICAocGVuZGluZ0FwcHJvdmFsRGF0YSBhcyBhbnkpLndhbGxldCA9IHdhbGxldDtcbiAgfSk7XG5cbiAgWyd0c29sJywgJ3RldGgnLCAndGJ0YyddLmZvckVhY2goKGNvaW5OYW1lKSA9PiB7XG4gICAgaXQoYHNob3VsZCB1c2UgY29ycmVjdCB0c3NVdGlscyBmb3IgICR7Y29pbk5hbWV9YCwgKCkgPT4ge1xuICAgICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oY29pbk5hbWUpO1xuICAgICAgY29uc3QgcGVuZGluZ0Fwcm92YWwgPSBuZXcgUGVuZGluZ0FwcHJvdmFsKGJpdGdvLCBjb2luLCB7fSBhcyB1bmtub3duIGFzIFBlbmRpbmdBcHByb3ZhbERhdGEpO1xuICAgICAgaWYgKGNvaW4uc3VwcG9ydHNUc3MoKSkge1xuICAgICAgICBpZiAoY29pbi5nZXRNUENBbGdvcml0aG0oKSA9PT0gJ2VjZHNhJykge1xuICAgICAgICAgIHBlbmRpbmdBcHJvdmFsWyd0c3NVdGlscyddLnNob3VsZC5iZS5pbnN0YW5jZU9mKEVDRFNBVXRpbHMuRWNkc2FVdGlscyk7XG4gICAgICAgIH0gZWxzZSBpZiAoY29pbi5nZXRNUENBbGdvcml0aG0oKSA9PT0gJ2VkZHNhJykge1xuICAgICAgICAgIHBlbmRpbmdBcHJvdmFsWyd0c3NVdGlscyddLnNob3VsZC5iZS5pbnN0YW5jZU9mKEVkZHNhVXRpbHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAocGVuZGluZ0Fwcm92YWxbJ3Rzc1V0aWxzJ10gPT09IHVuZGVmaW5lZCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgWydNUEN2MicsIHVuZGVmaW5lZF0uZm9yRWFjaCgobXVsdGlzaWdUeXBlVmVyc2lvbikgPT4ge1xuICAgIGl0KGBzaG91bGQgdXNlIGNvcnJlY3QgdHNzVXRpbHMgZm9yIG11bHRpc2lnVHlwZVZlcnNpb246ICR7bXVsdGlzaWdUeXBlVmVyc2lvbn1gLCAoKSA9PiB7XG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbignaHRldGgnKTtcbiAgICAgIGNvbnN0IHdhbGxldERhdGFNcGNWMiA9IHtcbiAgICAgICAgLi4ud2FsbGV0RGF0YSxcbiAgICAgICAgbXVsdGlzaWdUeXBlVmVyc2lvbjogbXVsdGlzaWdUeXBlVmVyc2lvbixcbiAgICAgIH07XG4gICAgICBjb25zdCB3YWxsZXRNUEN2MiA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB3YWxsZXREYXRhTXBjVjIpO1xuXG4gICAgICBjb25zdCBwZW5kaW5nQXByb3ZhbCA9IG5ldyBQZW5kaW5nQXBwcm92YWwoYml0Z28sIGNvaW4sIHt9IGFzIHVua25vd24gYXMgUGVuZGluZ0FwcHJvdmFsRGF0YSwgd2FsbGV0TVBDdjIpO1xuICAgICAgaWYgKHdhbGxldE1QQ3YyLm11bHRpc2lnVHlwZVZlcnNpb24oKSA9PT0gJ01QQ3YyJykge1xuICAgICAgICBwZW5kaW5nQXByb3ZhbFsndHNzVXRpbHMnXS5zaG91bGQuYmUuaW5zdGFuY2VPZihFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZW5kaW5nQXByb3ZhbFsndHNzVXRpbHMnXS5zaG91bGQuYmUuaW5zdGFuY2VPZihFQ0RTQVV0aWxzLkVjZHNhVXRpbHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGNhbGwgY29uc29saWRhdGUgaW5zdGVhZCBvZiBidWlsZCB3aGVuIHJlYnVpbGRpbmcgY29uc29saWRhdGlvbiBwZW5kaW5nIGFwcHJvdmFscycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzY29wZSA9IG5vY2soYmdVcmwpLnBvc3QoYC9hcGkvdjIvJHtjb2lufS93YWxsZXQvJHt3YWxsZXRJZH0vY29uc29saWRhdGVVbnNwZW50c2ApLnJlcGx5KDIwMCk7XG4gICAgY29uc3QgcGVuZGluZ0FwcHJvdmFscyA9IHdhbGxldC5wZW5kaW5nQXBwcm92YWxzKCk7XG4gICAgcGVuZGluZ0FwcHJvdmFscy5zaG91bGQuaGF2ZS5sZW5ndGgoMSk7XG4gICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gcGVuZGluZ0FwcHJvdmFsc1swXTtcblxuICAgIC8vIGFwcHJvdmFsIHdpbGwgZmFpbCB3aGVuIGF0dGVtcHRpbmcgdG8gcmVzaWduLiBUaGlzIGlzIG9rIC0gd2UganVzdCB3YW50IHRvIG1ha2Ugc3VyZVxuICAgIC8vIHRoZSBjb25zb2xpZGF0ZVVuc3BlbnRzIGVuZHBvaW50IHdhcyBjYWxsZWQgYWxyZWFkeSBiZWZvcmUgZmFpbGluZ1xuICAgIGF3YWl0IHBlbmRpbmdBcHByb3ZhbC5hcHByb3ZlKHsgeHBydjogJ25vbnNlbnNlJyB9KS5zaG91bGQuYmUucmVqZWN0ZWQoKTtcblxuICAgIHNjb3BlLmRvbmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBhcHByb3ZlIGZvciB0cmFuc2FjdGlvblJlcXVlc3RMaXRlIGlmIHdlIGNhbm5vdCByZWNyZWF0ZSB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwZW5kaW5nQXBwcm92YWxEYXRhMiA9IHsgLi4ucGVuZGluZ0FwcHJvdmFsRGF0YSwgdHhSZXF1ZXN0SWQ6ICcxMjM0LTQ1NjctNjc4OScgfTtcbiAgICBjb25zdCBwZW5kaW5nQXBwcm92YWwgPSBuZXcgUGVuZGluZ0FwcHJvdmFsKGJpdGdvLCBiYXNlY29pbiwgcGVuZGluZ0FwcHJvdmFsRGF0YTIsIHdhbGxldCk7XG5cbiAgICBjb25zdCBwYVNjb3BlID0gbm9jayhiZ1VybClcbiAgICAgIC5wdXQoYC9hcGkvdjIvJHtjb2lufS9wZW5kaW5nYXBwcm92YWxzLyR7cGVuZGluZ0FwcHJvdmFsRGF0YS5pZH1gLCB7XG4gICAgICAgIHN0YXRlOiAnYXBwcm92ZWQnLFxuICAgICAgICBvdHA6IHVuZGVmaW5lZCxcbiAgICAgIH0pXG4gICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgIC4uLnBlbmRpbmdBcHByb3ZhbERhdGEyLFxuICAgICAgICBzdGF0ZTogJ2FwcHJvdmVkJyxcbiAgICAgIH0pO1xuICAgIGNvbnN0IHJlY3JlYXRlVHJhbnNhY3Rpb25Uc3NTdHViID0gc2FuZGJveC5zdHViKFBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUsICdyZWNyZWF0ZUFuZFNpZ25UU1NUcmFuc2FjdGlvbicpO1xuICAgIGNvbnN0IHJlY3JlYXRlVHJhbnNhY3Rpb25TdHViID0gc2FuZGJveC5zdHViKFBlbmRpbmdBcHByb3ZhbC5wcm90b3R5cGUsICdyZWNyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbicpO1xuXG4gICAgcGVuZGluZ0FwcHJvdmFsLnR5cGUoKS5zaG91bGQuZXF1YWwoVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNUKTtcbiAgICBhd2FpdCBwZW5kaW5nQXBwcm92YWwuYXBwcm92ZSh7fSk7XG4gICAgcmVjcmVhdGVUcmFuc2FjdGlvblRzc1N0dWIubm90Q2FsbGVkLnNob3VsZC5iZS50cnVlKCk7XG4gICAgcmVjcmVhdGVUcmFuc2FjdGlvblN0dWIubm90Q2FsbGVkLnNob3VsZC5iZS50cnVlKCk7XG5cbiAgICBwYVNjb3BlLmlzRG9uZSgpLnNob3VsZC5iZS50cnVlKCk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIHRlc3RSZWNyZWF0ZVRyYW5zYWN0aW9uKGNvaW5OYW1lOiBzdHJpbmcsIHJlY3JlYXRlVHJhbnNhY3Rpb246IGJvb2xlYW4sIHR5cGU6IFR5cGUpIHtcbiAgICBpdChgWyR7Y29pbk5hbWV9XSBzaG91bGQgJHtcbiAgICAgIHJlY3JlYXRlVHJhbnNhY3Rpb24gPyAnbm90ICcgOiAnJ1xuICAgIH1yZWNyZWF0ZSB0aGUgdHJhbnNhY3Rpb24gZHVyaW5nIGFwcHJvdmluZyBhIHBlbmRpbmcgYXBwcm92YWwgaWYgdGhlcmUgYXJlIG5vIHJlY2lwaWVudHMgZm9yIFBBIHR5cGUgJHt0eXBlfWAsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lKTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdElkID0gY29pbi5zdXBwb3J0c1RzcygpID8gJ3JlcXVlc3RUeElkVGVzdCcgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCBwZW5kaW5nQXBwcm92YWxJbmZvID1cbiAgICAgICAgdHlwZSA9PT0gJ3RyYW5zYWN0aW9uUmVxdWVzdCdcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgdHJhbnNhY3Rpb25SZXF1ZXN0OiB7XG4gICAgICAgICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICAgICAgICBbY29pbk5hbWVdOiB7IHR4SGV4OiAnZ2FiYWdvb2wnIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZWNpcGllbnRzOiBbXSxcbiAgICAgICAgICAgICAgICBidWlsZFBhcmFtczoge30sXG4gICAgICAgICAgICAgICAgc291cmNlV2FsbGV0OiB3YWxsZXRJZCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICA6ICh7IHR5cGUgfSBhcyB1bmtub3duIGFzIFBlbmRpbmdBcHByb3ZhbEluZm8pO1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsRGF0YVRlbXA6IFBlbmRpbmdBcHByb3ZhbERhdGEgPSB7XG4gICAgICAgIGlkOiAncGEwJyxcbiAgICAgICAgaW5mbzogcGVuZGluZ0FwcHJvdmFsSW5mbyxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXRJZCxcbiAgICAgICAgc3RhdGU6IFN0YXRlLlBFTkRJTkcsXG4gICAgICAgIGNyZWF0b3I6ICd0ZXN0JyxcbiAgICAgICAgdHhSZXF1ZXN0SWQsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB3YWxsZXREYXRhVGVtcCA9IHtcbiAgICAgICAgaWQ6IHdhbGxldElkLFxuICAgICAgICBjb2luTmFtZSxcbiAgICAgICAgcGVuZGluZ0FwcHJvdmFsczogW3BlbmRpbmdBcHByb3ZhbERhdGFUZW1wXSxcbiAgICAgIH07XG4gICAgICBjb25zdCB3YWxsZXRUZW1wID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwgd2FsbGV0RGF0YVRlbXApO1xuICAgICAgcGVuZGluZ0FwcHJvdmFsRGF0YVRlbXAud2FsbGV0ID0gd2FsbGV0VGVtcC5pZCgpO1xuXG4gICAgICBjb25zdCBwZW5kaW5nQXBwcm92YWxzID0gd2FsbGV0VGVtcC5wZW5kaW5nQXBwcm92YWxzKCk7XG4gICAgICBwZW5kaW5nQXBwcm92YWxzLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICAgIGNvbnN0IHBlbmRpbmdBcHByb3ZhbCA9IHBlbmRpbmdBcHByb3ZhbHNbMF07XG5cbiAgICAgIGxldCBzdHViOiBzaW5vbi5TaW5vblN0dWI7XG4gICAgICBpZiAoY29pbi5zdXBwb3J0c1RzcygpKSB7XG4gICAgICAgIHN0dWIgPSBzYW5kYm94LnN0dWIoUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZSwgJ3JlY3JlYXRlQW5kU2lnblRTU1RyYW5zYWN0aW9uJykucmVzb2x2ZXMoe1xuICAgICAgICAgIHR4SGV4OiAnZ2FiYWdvb2wnLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0dWIgPSBzYW5kYm94LnN0dWIoUGVuZGluZ0FwcHJvdmFsLnByb3RvdHlwZSwgJ3JlY3JlYXRlQW5kU2lnblRyYW5zYWN0aW9uJykucmVzb2x2ZXMoe1xuICAgICAgICAgIHN0YXRlOiAnYXBwcm92ZWQnLFxuICAgICAgICAgIGhhbGZTaWduZWQ6IHsgdHhIZXg6ICdnYWJhZ29vbCcgfSxcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBhU2NvcGUgPSBub2NrKGJnVXJsKVxuICAgICAgICAucHV0KGAvYXBpL3YyLyR7Y29pbk5hbWV9L3BlbmRpbmdhcHByb3ZhbHMvJHtwZW5kaW5nQXBwcm92YWxEYXRhVGVtcC5pZH1gLCB7XG4gICAgICAgICAgc3RhdGU6ICdhcHByb3ZlZCcsXG4gICAgICAgICAgaGFsZlNpZ25lZDogdHlwZSA9PT0gVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNUID8geyB0eEhleDogJ2dhYmFnb29sJyB9IDogdW5kZWZpbmVkLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgLi4ucGVuZGluZ0FwcHJvdmFsRGF0YVRlbXAsXG4gICAgICAgICAgc3RhdGU6ICdhcHByb3ZlZCcsXG4gICAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBwZW5kaW5nQXBwcm92YWwuYXBwcm92ZSh7IHhwcnY6ICdub25zZW5zZScsIHdhbGxldFBhc3NwaHJhc2U6ICdnYWJhZ29vbGlvJyB9KTtcblxuICAgICAgLy8gU2hvdWxkIG5vdCBjYWxsIGJ1aWxkIGFuZCBzaG91bGQgY2FsbCBwYVxuICAgICAgcGFTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc3R1Yi5jYWxsZWRPbmNlLnNob3VsZC5lcXVhbChyZWNyZWF0ZVRyYW5zYWN0aW9uKTtcbiAgICB9KTtcbiAgfVxuXG4gIHRlc3RSZWNyZWF0ZVRyYW5zYWN0aW9uKCd0YnRjJywgZmFsc2UsIFR5cGUuVFJBTlNBQ1RJT05fUkVRVUVTVCk7XG4gIHRlc3RSZWNyZWF0ZVRyYW5zYWN0aW9uKCd0c29sJywgdHJ1ZSwgVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNUKTtcbiAgdGVzdFJlY3JlYXRlVHJhbnNhY3Rpb24oJ3Rzb2wnLCB0cnVlLCBUeXBlLlRSQU5TQUNUSU9OX1JFUVVFU1RfRlVMTCk7XG4gIHRlc3RSZWNyZWF0ZVRyYW5zYWN0aW9uKCd0ZXRoJywgdHJ1ZSwgVHlwZS5UUkFOU0FDVElPTl9SRVFVRVNUX0ZVTEwpO1xuXG4gIGRlc2NyaWJlKCdyZWNyZWF0ZUFuZFNpZ25UU1NUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgY29pbjogQmFzZUNvaW47XG5cbiAgICBiZWZvcmUoKCkgPT4ge1xuICAgICAgY29pbiA9IGJpdGdvLmNvaW4oJ3Rzb2wnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBhcHByb3ZlIGFuZCBkbyB0aGUgVFNTIGZsb3cgYW5kIGZhaWwgaWYgdGhlIHR4UmVxdWVzdElkIGlzIG1pc3NpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwZW5kaW5nQXBwcm92YWwgPSB3YWxsZXQucGVuZGluZ0FwcHJvdmFscygpWzBdO1xuICAgICAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICAgICAgY29uc3QgcGFyYW1zID0geyB3YWxsZXRQYXNzcGhyYXNlOiAndGVzdCcgfTtcbiAgICAgIGF3YWl0IHBlbmRpbmdBcHByb3ZhbFxuICAgICAgICAucmVjcmVhdGVBbmRTaWduVFNTVHJhbnNhY3Rpb24ocGFyYW1zLCByZXFJZClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3R4UmVxdWVzdElkIG5vdCBmb3VuZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGFwcHJvdmUgYW5kIGRvIHRoZSBUU1MgZmxvdyBhbmQgZmFpbCBpZiB0aGUgd2FsbGV0UGFzc3BocmFzZSBpcyBtaXNzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gd2FsbGV0LnBlbmRpbmdBcHByb3ZhbHMoKVswXTtcbiAgICAgIHBlbmRpbmdBcHByb3ZhbERhdGFbJ3R4UmVxdWVzdElkJ10gPSAncmVxdWVzdFR4SWRUZXN0JztcbiAgICAgIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHt9O1xuICAgICAgYXdhaXQgcGVuZGluZ0FwcHJvdmFsXG4gICAgICAgIC5yZWNyZWF0ZUFuZFNpZ25UU1NUcmFuc2FjdGlvbihwYXJhbXMsIHJlcUlkKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnd2FsbGV0UGFzc3BocmFzZSBub3QgZm91bmQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBhcHByb3ZlIGFuZCBkbyB0aGUgVFNTIGZsb3cgYW5kIGZhaWwgaWYgdGhlIHdhbGxldCBpcyBtaXNzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gbmV3IFBlbmRpbmdBcHByb3ZhbChiaXRnbywgY29pbiwgcGVuZGluZ0FwcHJvdmFsRGF0YSk7XG4gICAgICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7IHdhbGxldFBhc3NwaHJhc2U6ICd0ZXN0JyB9O1xuICAgICAgYXdhaXQgcGVuZGluZ0FwcHJvdmFsLnJlY3JlYXRlQW5kU2lnblRTU1RyYW5zYWN0aW9uKHBhcmFtcywgcmVxSWQpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ1dhbGxldCBub3QgZm91bmQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2V0IHR4SGV4IGZvciB0cmFuc2FjdGlvblJlcXVlc3RMaXRlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgcGVuZGluZ0FwcHJvdmFsRGF0YVsndHhSZXF1ZXN0SWQnXSA9ICdyZXF1ZXN0VHhJZFRlc3QnO1xuICAgICAgY29uc3QgcGVuZGluZ0FwcHJvdmFsID0gbmV3IFBlbmRpbmdBcHByb3ZhbChiaXRnbywgY29pbiwgcGVuZGluZ0FwcHJvdmFsRGF0YSwgd2FsbGV0KTtcbiAgICAgIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdElkID0gJ3Rlc3QnO1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICd0ZXN0JztcbiAgICAgIGNvbnN0IGRlY3J5cHRlZFBydlJlc3BvbnNlID0gJ2RlY3J5cHRlZFBydic7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7IHR4UmVxdWVzdElkLCB3YWxsZXRQYXNzcGhyYXNlIH07XG4gICAgICBjb25zdCB0eFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICAgICAgYXBpVmVyc2lvbjogJ2xpdGUnLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0SWQsXG4gICAgICAgIHVuc2lnbmVkVHhzOiBbeyBzaWduYWJsZUhleDogJ3JhbmRvbWhleCcsIHNlcmlhbGl6ZWRUeEhleDogJ3JhbmRvbWhleDInLCBkZXJpdmF0aW9uUGF0aDogJ20vMCcgfV0sXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgICAgIHNoYXJlOiAnOWQ3MTU5YTc2NzAwNjM1VEVTVCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgdHJhbnNhY3Rpb25zOiBbXSxcbiAgICAgICAgdXNlcklkOiAndXNlcklkJyxcbiAgICAgICAgZGF0ZTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICBpbnRlbnQ6IHtcbiAgICAgICAgICBpbnRlbnRUeXBlOiAncGF5bWVudCcsXG4gICAgICAgIH0sXG4gICAgICAgIGxhdGVzdDogdHJ1ZSxcbiAgICAgICAgd2FsbGV0SWQ6ICd3YWxsZXRJZCcsXG4gICAgICAgIHZlcnNpb246IDEsXG4gICAgICAgIHBvbGljaWVzQ2hlY2tlZDogZmFsc2UsXG4gICAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgICBzdGF0ZTogJ3BlbmRpbmdVc2VyU2lnbmF0dXJlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGRlY3J5cHRlZFBydiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAnZ2V0UHJ2Jyk7XG4gICAgICBkZWNyeXB0ZWRQcnYuY2FsbGVkT25jZVdpdGhFeGFjdGx5KHsgd2FsbGV0UGFzc3BocmFzZSB9KTtcbiAgICAgIGRlY3J5cHRlZFBydi5yZXNvbHZlcyhkZWNyeXB0ZWRQcnZSZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHJlY3JlYXRlVHhSZXF1ZXN0ID0gc2FuZGJveC5zdHViKFRzc1V0aWxzLnByb3RvdHlwZSwgJ3JlY3JlYXRlVHhSZXF1ZXN0Jyk7XG4gICAgICByZWNyZWF0ZVR4UmVxdWVzdC5jYWxsZWRPbmNlV2l0aEV4YWN0bHkodHhSZXF1ZXN0LnR4UmVxdWVzdElkLCBkZWNyeXB0ZWRQcnZSZXNwb25zZSwgcmVxSWQpO1xuICAgICAgcmVjcmVhdGVUeFJlcXVlc3QucmVzb2x2ZXModHhSZXF1ZXN0KTtcblxuICAgICAgY29uc3QgcmVjcmVhdGVkVHggPSBhd2FpdCBwZW5kaW5nQXBwcm92YWwucmVjcmVhdGVBbmRTaWduVFNTVHJhbnNhY3Rpb24ocGFyYW1zLCByZXFJZCk7XG4gICAgICByZWNyZWF0ZWRUeC5zaG91bGQuYmUuZGVlcEVxdWFsKHsgdHhIZXg6IHR4UmVxdWVzdC51bnNpZ25lZFR4c1swXS5zZXJpYWxpemVkVHhIZXggfSk7XG5cbiAgICAgIHNhbmRib3gudmVyaWZ5KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdldCB0eEhleCBmb3IgdHJhbnNhY3Rpb25SZXF1ZXN0RnVsbCAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBwZW5kaW5nQXBwcm92YWxEYXRhWyd0eFJlcXVlc3RJZCddID0gJ3JlcXVlc3RUeElkVGVzdCc7XG4gICAgICBjb25zdCBwZW5kaW5nQXBwcm92YWwgPSBuZXcgUGVuZGluZ0FwcHJvdmFsKGJpdGdvLCBjb2luLCBwZW5kaW5nQXBwcm92YWxEYXRhLCB3YWxsZXQpO1xuICAgICAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICAgICAgY29uc3QgdHhSZXF1ZXN0SWQgPSAndGVzdCc7XG4gICAgICBjb25zdCB3YWxsZXRQYXNzcGhyYXNlID0gJ3Rlc3QnO1xuICAgICAgY29uc3QgZGVjcnlwdGVkUHJ2UmVzcG9uc2UgPSAnZGVjcnlwdGVkUHJ2JztcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHsgdHhSZXF1ZXN0SWQsIHdhbGxldFBhc3NwaHJhc2UgfTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0SWQsXG4gICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgdW5zaWduZWRUeHM6IFtdLFxuICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB1bnNpZ25lZFR4OiB7IHNpZ25hYmxlSGV4OiAncmFuZG9taGV4Jywgc2VyaWFsaXplZFR4SGV4OiAncmFuZG9taGV4MicsIGRlcml2YXRpb25QYXRoOiAnbS8wJyB9LFxuICAgICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgICAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICAgICAgICAgIHNoYXJlOiAnOWQ3MTU5YTc2NzAwNjM1VEVTVCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgc3RhdGU6ICdpbml0aWFsaXplZCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgdXNlcklkOiAndXNlcklkJyxcbiAgICAgICAgZGF0ZTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICBpbnRlbnQ6IHtcbiAgICAgICAgICBpbnRlbnRUeXBlOiAncGF5bWVudCcsXG4gICAgICAgIH0sXG4gICAgICAgIGxhdGVzdDogdHJ1ZSxcbiAgICAgICAgd2FsbGV0SWQ6ICd3YWxsZXRJZCcsXG4gICAgICAgIHZlcnNpb246IDEsXG4gICAgICAgIHBvbGljaWVzQ2hlY2tlZDogZmFsc2UsXG4gICAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgICBzdGF0ZTogJ3BlbmRpbmdEZWxpdmVyeScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBkZWNyeXB0ZWRQcnYgPSBzYW5kYm94LnN0dWIoV2FsbGV0LnByb3RvdHlwZSwgJ2dldFBydicpO1xuICAgICAgZGVjcnlwdGVkUHJ2LmNhbGxlZE9uY2VXaXRoRXhhY3RseSh7IHdhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgICBkZWNyeXB0ZWRQcnYucmVzb2x2ZXMoZGVjcnlwdGVkUHJ2UmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCByZWNyZWF0ZVR4UmVxdWVzdCA9IHNhbmRib3guc3R1YihUc3NVdGlscy5wcm90b3R5cGUsICdyZWNyZWF0ZVR4UmVxdWVzdCcpO1xuICAgICAgcmVjcmVhdGVUeFJlcXVlc3QuY2FsbGVkT25jZVdpdGhFeGFjdGx5KHR4UmVxdWVzdC50eFJlcXVlc3RJZCwgZGVjcnlwdGVkUHJ2UmVzcG9uc2UsIHJlcUlkKTtcbiAgICAgIHJlY3JlYXRlVHhSZXF1ZXN0LnJlc29sdmVzKHR4UmVxdWVzdCk7XG5cbiAgICAgIGNvbnN0IHJlY3JlYXRlZFR4ID0gYXdhaXQgcGVuZGluZ0FwcHJvdmFsLnJlY3JlYXRlQW5kU2lnblRTU1RyYW5zYWN0aW9uKHBhcmFtcywgcmVxSWQpO1xuICAgICAgcmVjcmVhdGVkVHguc2hvdWxkLmJlLmRlZXBFcXVhbCh7IHR4SGV4OiB0eFJlcXVlc3QudHJhbnNhY3Rpb25zIVswXS51bnNpZ25lZFR4LnNlcmlhbGl6ZWRUeEhleCB9KTtcblxuICAgICAgc2FuZGJveC52ZXJpZnkoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==