bitgo
Version:
BitGo JavaScript SDK
319 lines • 55.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const nock = require("nock");
const should = require("should");
const stakingWallet_1 = require("../../fixtures/staking/stakingWallet");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_test_1 = require("@bitgo/sdk-test");
const src_1 = require("../../../../src");
const sinon = require("sinon");
describe('Staking Wallet Common', function () {
const microservicesUri = sdk_core_1.Environments['mock'].uri;
let bitgo;
let baseCoin;
let enterprise;
let stakingWallet;
before(function () {
bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock', microservicesUri });
bitgo.initializeTestVars();
baseCoin = bitgo.coin('eth');
baseCoin.keychains();
enterprise = new sdk_core_1.Enterprise(bitgo, baseCoin, { id: '5cf940949449412d00f53b3d92dbcaa3', name: 'Test Enterprise' });
const walletData = {
id: 'walletId',
coin: 'eth',
enterprise: enterprise.id,
keys: ['5b3424f91bf349930e340175'],
};
const wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData);
stakingWallet = wallet.toStakingWallet();
});
const sandbox = sinon.createSandbox();
afterEach(function () {
sandbox.verifyAndRestore();
});
describe('stake', function () {
it('should call staking-service to stake', async function () {
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, {
amount: '1',
clientId: 'clientId',
type: 'STAKE',
})
.reply(201, expected);
const stakingRequest = await stakingWallet.stake({
amount: '1',
clientId: 'clientId',
});
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
it('should call staking-service to stake with optional parameters', async function () {
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, {
amount: '1',
clientId: 'clientId',
type: 'STAKE',
validator: '123',
durationSeconds: '60',
})
.reply(201, expected);
const options = {
amount: '1',
clientId: 'clientId',
validator: '123',
durationSeconds: '60',
};
const stakingRequest = await stakingWallet.stake(options);
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
it('should call staking-service to stake with optional stakeMany parameters', async function () {
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, {
clientId: 'clientId',
type: 'STAKE',
delegationRequests: [
{ amount: '1', validator: '123' },
{ amount: '2', validator: '456' },
],
durationSeconds: '60',
})
.reply(201, expected);
const options = {
clientId: 'clientId',
delegationRequests: [
{ amount: '1', validator: '123' },
{ amount: '2', validator: '456' },
],
durationSeconds: '60',
};
const stakingRequest = await stakingWallet.stake(options);
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
});
describe('unstake', function () {
it('should call staking-service to unstake', async function () {
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, {
amount: '1',
clientId: 'clientId',
type: 'UNSTAKE',
})
.reply(201, expected);
const stakingRequest = await stakingWallet.unstake({
amount: '1',
clientId: 'clientId',
});
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
});
describe('switch validator', function () {
it('should call staking-service to switch validator', async function () {
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, {
amount: '1',
clientId: 'clientId',
validator: 'validator',
delegationId: 'delegation',
type: 'SWITCH_VALIDATOR',
})
.reply(201, expected);
const stakingRequest = await stakingWallet.switchValidator({
amount: '1',
clientId: 'clientId',
validator: 'validator',
delegationId: 'delegation',
});
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
});
describe('claim rewards', function () {
it('should call staking-service to claim rewards', async function () {
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.post(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests`, {
amount: '1',
clientId: 'clientId',
delegationId: 'delegation',
type: 'CLAIM_REWARDS',
})
.reply(201, expected);
const stakingRequest = await stakingWallet.claimRewards({
amount: '1',
clientId: 'clientId',
delegationId: 'delegation',
});
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
});
describe('cancelStakingRequest', function () {
it('should call staking-service to cancel staking request', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expected = {
...stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('REJECTED')]),
status: 'REJECTED',
};
const msScope = nock(microservicesUri)
.delete(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests/${stakingRequestId}`)
.reply(200, expected);
const stakingRequest = await stakingWallet.cancelStakingRequest(stakingRequestId);
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
});
describe('getStakingRequest', function () {
it('should call staking-service to get staking request', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = nock(microservicesUri)
.get(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests/${stakingRequestId}`)
.reply(200, expected);
const stakingRequest = await stakingWallet.getStakingRequest(stakingRequestId);
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
});
describe('getTransactionsReadyToSign', function () {
function mockGetStakingRequest(stakingRequestId, expected) {
return nock(microservicesUri)
.get(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests/${stakingRequestId}`)
.reply(200, expected);
}
it('should return allSigningComplete false when no transactions exist', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expected = stakingWallet_1.default.stakingRequest([]);
const msScope = mockGetStakingRequest(stakingRequestId, expected);
const transactionsReadyToSign = await stakingWallet.getTransactionsReadyToSign(stakingRequestId);
should.exist(transactionsReadyToSign);
transactionsReadyToSign.allSigningComplete.should.be.False();
transactionsReadyToSign.transactions.should.be.empty();
msScope.isDone().should.be.True();
});
it('should return allSigningComplete true and 0 transactions when only a CONFIRMED transaction exists', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expected = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('CONFIRMED')]);
const msScope = mockGetStakingRequest(stakingRequestId, expected);
const transactionsReadyToSign = await stakingWallet.getTransactionsReadyToSign(stakingRequestId);
should.exist(transactionsReadyToSign);
transactionsReadyToSign.allSigningComplete.should.be.True();
transactionsReadyToSign.transactions.should.be.empty();
msScope.isDone().should.be.True();
});
it('should return allSigningComplete false and 0 transactions when only a NEW transaction exists', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expectedStakingRequest = stakingWallet_1.default.stakingRequest([stakingWallet_1.default.transaction('NEW')]);
const msScope = mockGetStakingRequest(stakingRequestId, expectedStakingRequest);
const transactionsReadyToSign = await stakingWallet.getTransactionsReadyToSign(stakingRequestId);
should.exist(transactionsReadyToSign);
transactionsReadyToSign.allSigningComplete.should.be.False();
transactionsReadyToSign.transactions.should.be.empty();
msScope.isDone().should.be.True();
});
it('should return allSigningComplete false and 1 transactions when only a READY transaction exists', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expectedTransaction = stakingWallet_1.default.transaction('READY');
const expectedStakingRequest = stakingWallet_1.default.stakingRequest([expectedTransaction]);
const msScope = mockGetStakingRequest(stakingRequestId, expectedStakingRequest);
const transactionsReadyToSign = await stakingWallet.getTransactionsReadyToSign(stakingRequestId);
should.exist(transactionsReadyToSign);
transactionsReadyToSign.allSigningComplete.should.be.False();
transactionsReadyToSign.transactions.should.containEql(expectedTransaction);
msScope.isDone().should.be.True();
});
it('should return allSigningComplete false and 1 transaction when NEW and READY transaction exists', async function () {
const stakingRequestId = '8638284a-dab2-46b9-b07f-21109a6e7220';
const expectedTransaction = stakingWallet_1.default.transaction('READY');
const expectedStakingRequest = stakingWallet_1.default.stakingRequest([expectedTransaction, stakingWallet_1.default.transaction('NEW')]);
const msScope = mockGetStakingRequest(stakingRequestId, expectedStakingRequest);
const transactionsReadyToSign = await stakingWallet.getTransactionsReadyToSign(stakingRequestId);
should.exist(transactionsReadyToSign);
transactionsReadyToSign.allSigningComplete.should.be.False();
transactionsReadyToSign.transactions.should.containEql(expectedTransaction);
msScope.isDone().should.be.True();
});
});
describe('prebuildSelfManagedStakingTransaction', function () {
it('should prebuild self-managed staking transaction', async function () {
const transaction = stakingWallet_1.default.transaction('READY', stakingWallet_1.default.buildParams, false);
nock(microservicesUri)
.get(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
.query({ expandBuildParams: true })
.reply(200, transaction);
const deleteSignatureShares = sandbox.stub(sdk_core_1.TssUtils.prototype, 'deleteSignatureShares');
const prebuildTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'prebuildTransaction');
const build = sandbox.stub(sdk_core_1.StakingWallet.prototype, 'build');
const txPrebuild = {
walletId: stakingWallet.walletId,
txHex: 'hex',
buildParams: transaction.buildParams,
};
prebuildTransaction.resolves(txPrebuild);
prebuildTransaction.calledOnceWithExactly(transaction.buildParams);
const formattedParams = {
...stakingWallet_1.default.buildParams,
coin: stakingWallet.coin,
walletId: stakingWallet.walletId,
walletType: stakingWallet.wallet.type(),
preview: true,
};
const stakingTransaction = await stakingWallet.prebuildSelfManagedStakingTransaction(transaction);
sandbox.assert.calledOnce(prebuildTransaction);
sandbox.assert.notCalled(build);
sandbox.assert.notCalled(deleteSignatureShares);
const expected = await stakingWallet.wallet.prebuildTransaction(formattedParams);
stakingTransaction.should.deepEqual(expected);
should.exist(stakingTransaction);
});
it('should prebuild self-managed staking transaction - no build params', async function () {
const transaction = stakingWallet_1.default.transaction('READY', undefined, true);
nock(microservicesUri)
.get(`/api/staking/v1/${stakingWallet.coin}/wallets/${stakingWallet.walletId}/requests/${transaction.stakingRequestId}/transactions/${transaction.id}`)
.query({ expandBuildParams: true })
.reply(200, transaction);
const deleteSignatureShares = sandbox.stub(sdk_core_1.TssUtils.prototype, 'deleteSignatureShares');
const prebuildTransaction = sandbox.stub(sdk_core_1.Wallet.prototype, 'prebuildTransaction');
const build = sandbox.stub(sdk_core_1.StakingWallet.prototype, 'build');
const txPrebuild = {
walletId: stakingWallet.walletId,
txHex: 'hex',
};
prebuildTransaction.resolves(txPrebuild);
if (transaction.txRequestId) {
deleteSignatureShares.calledOnceWithExactly(transaction.txRequestId);
}
const formattedParams = {
...stakingWallet_1.default.buildParams,
coin: stakingWallet.coin,
walletId: stakingWallet.walletId,
walletType: stakingWallet.wallet.type(),
preview: true,
};
const stakingTransaction = await stakingWallet.prebuildSelfManagedStakingTransaction(transaction);
sandbox.assert.calledOnce(prebuildTransaction);
sandbox.assert.notCalled(build);
sandbox.assert.calledOnce(deleteSignatureShares);
const expected = await stakingWallet.wallet.prebuildTransaction(formattedParams);
stakingTransaction.should.deepEqual(expected);
should.exist(stakingTransaction);
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Rha2luZ1dhbGxldENvbW1vbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdjIvdW5pdC9zdGFraW5nL3N0YWtpbmdXYWxsZXRDb21tb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2QkFBOEI7QUFDOUIsaUNBQWtDO0FBQ2xDLHdFQUE0RDtBQUU1RCw4Q0FBNEc7QUFDNUcsOENBQTRDO0FBQzVDLHlDQUF3QztBQUN4QywrQkFBK0I7QUFFL0IsUUFBUSxDQUFDLHVCQUF1QixFQUFFO0lBQ2hDLE1BQU0sZ0JBQWdCLEdBQUcsdUJBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDbEQsSUFBSSxLQUFLLENBQUM7SUFDVixJQUFJLFFBQVEsQ0FBQztJQUNiLElBQUksVUFBVSxDQUFDO0lBQ2YsSUFBSSxhQUE0QixDQUFDO0lBRWpDLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxXQUFLLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFTLENBQUMsQ0FBQztRQUM1RSxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUMzQixRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDckIsVUFBVSxHQUFHLElBQUkscUJBQVUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLGtDQUFrQyxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxDQUFDLENBQUM7UUFDbEgsTUFBTSxVQUFVLEdBQUc7WUFDakIsRUFBRSxFQUFFLFVBQVU7WUFDZCxJQUFJLEVBQUUsS0FBSztZQUNYLFVBQVUsRUFBRSxVQUFVLENBQUMsRUFBRTtZQUN6QixJQUFJLEVBQUUsQ0FBQywwQkFBMEIsQ0FBQztTQUNuQyxDQUFDO1FBQ0YsTUFBTSxN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QUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFFakQsTUFBTSxRQUFRLEdBQUcsTUFBTSxhQUFhLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRWpGLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDOUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ25DLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBub2NrID0gcmVxdWlyZSgnbm9jaycpO1xuaW1wb3J0IHNob3VsZCA9IHJlcXVpcmUoJ3Nob3VsZCcpO1xuaW1wb3J0IGZpeHR1cmVzIGZyb20gJy4uLy4uL2ZpeHR1cmVzL3N0YWtpbmcvc3Rha2luZ1dhbGxldCc7XG5cbmltcG9ydCB7IEVudGVycHJpc2UsIEVudmlyb25tZW50cywgU3Rha2luZ1JlcXVlc3QsIFN0YWtpbmdXYWxsZXQsIFRzc1V0aWxzLCBXYWxsZXQgfSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgVGVzdEJpdEdvIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvIH0gZnJvbSAnLi4vLi4vLi4vLi4vc3JjJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcblxuZGVzY3JpYmUoJ1N0YWtpbmcgV2FsbGV0IENvbW1vbicsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgbWljcm9zZXJ2aWNlc1VyaSA9IEVudmlyb25tZW50c1snbW9jayddLnVyaTtcbiAgbGV0IGJpdGdvO1xuICBsZXQgYmFzZUNvaW47XG4gIGxldCBlbnRlcnByaXNlO1xuICBsZXQgc3Rha2luZ1dhbGxldDogU3Rha2luZ1dhbGxldDtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snLCBtaWNyb3NlcnZpY2VzVXJpIH0gYXMgYW55KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICBiYXNlQ29pbiA9IGJpdGdvLmNvaW4oJ2V0aCcpO1xuICAgIGJhc2VDb2luLmtleWNoYWlucygpO1xuICAgIGVudGVycHJpc2UgPSBuZXcgRW50ZXJwcmlzZShiaXRnbywgYmFzZUNvaW4sIHsgaWQ6ICc1Y2Y5NDA5NDk0NDk0MTJkMDBmNTNiM2Q5MmRiY2FhMycsIG5hbWU6ICdUZXN0IEVudGVycHJpc2UnIH0pO1xuICAgIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgICBpZDogJ3dhbGxldElkJyxcbiAgICAgIGNvaW46ICdldGgnLFxuICAgICAgZW50ZXJwcmlzZTogZW50ZXJwcmlzZS5pZCxcbiAgICAgIGtleXM6IFsnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc1J10sXG4gICAgfTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgd2FsbGV0RGF0YSk7XG4gICAgc3Rha2luZ1dhbGxldCA9IHdhbGxldC50b1N0YWtpbmdXYWxsZXQoKTtcbiAgfSk7XG5cbiAgY29uc3Qgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3Rha2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byBzdGFrZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkID0gZml4dHVyZXMuc3Rha2luZ1JlcXVlc3QoW2ZpeHR1cmVzLnRyYW5zYWN0aW9uKCdORVcnKV0pO1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLnBvc3QoYC9hcGkvc3Rha2luZy92MS8ke3N0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke3N0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzYCwge1xuICAgICAgICAgIGFtb3VudDogJzEnLFxuICAgICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICAgIHR5cGU6ICdTVEFLRScsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDEsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LnN0YWtlKHtcbiAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIHN0YWtpbmdSZXF1ZXN0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWQpO1xuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byBzdGFrZSB3aXRoIG9wdGlvbmFsIHBhcmFtZXRlcnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5wb3N0KGAvYXBpL3N0YWtpbmcvdjEvJHtzdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtzdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0c2AsIHtcbiAgICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgICBjbGllbnRJZDogJ2NsaWVudElkJyxcbiAgICAgICAgICB0eXBlOiAnU1RBS0UnLFxuICAgICAgICAgIHZhbGlkYXRvcjogJzEyMycsXG4gICAgICAgICAgZHVyYXRpb25TZWNvbmRzOiAnNjAnLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAxLCBleHBlY3RlZCk7XG5cbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgIGFtb3VudDogJzEnLFxuICAgICAgICBjbGllbnRJZDogJ2NsaWVudElkJyxcbiAgICAgICAgdmFsaWRhdG9yOiAnMTIzJyxcbiAgICAgICAgZHVyYXRpb25TZWNvbmRzOiAnNjAnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0ID0gYXdhaXQgc3Rha2luZ1dhbGxldC5zdGFrZShvcHRpb25zKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHN0YWtpbmdSZXF1ZXN0KTtcblxuICAgICAgc3Rha2luZ1JlcXVlc3Quc2hvdWxkLmRlZXBFcXVhbChleHBlY3RlZCk7XG4gICAgICBtc1Njb3BlLmlzRG9uZSgpLnNob3VsZC5iZS5UcnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgc3Rha2luZy1zZXJ2aWNlIHRvIHN0YWtlIHdpdGggb3B0aW9uYWwgc3Rha2VNYW55IHBhcmFtZXRlcnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5wb3N0KGAvYXBpL3N0YWtpbmcvdjEvJHtzdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtzdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0c2AsIHtcbiAgICAgICAgICBjbGllbnRJZDogJ2NsaWVudElkJyxcbiAgICAgICAgICB0eXBlOiAnU1RBS0UnLFxuICAgICAgICAgIGRlbGVnYXRpb25SZXF1ZXN0czogW1xuICAgICAgICAgICAgeyBhbW91bnQ6ICcxJywgdmFsaWRhdG9yOiAnMTIzJyB9LFxuICAgICAgICAgICAgeyBhbW91bnQ6ICcyJywgdmFsaWRhdG9yOiAnNDU2JyB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgZHVyYXRpb25TZWNvbmRzOiAnNjAnLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAxLCBleHBlY3RlZCk7XG5cbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICBkZWxlZ2F0aW9uUmVxdWVzdHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEnLCB2YWxpZGF0b3I6ICcxMjMnIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyJywgdmFsaWRhdG9yOiAnNDU2JyB9LFxuICAgICAgICBdLFxuICAgICAgICBkdXJhdGlvblNlY29uZHM6ICc2MCcsXG4gICAgICB9O1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LnN0YWtlKG9wdGlvbnMpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Vuc3Rha2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byB1bnN0YWtlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHNgLCB7XG4gICAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgICAgdHlwZTogJ1VOU1RBS0UnLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAxLCBleHBlY3RlZCk7XG5cbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0ID0gYXdhaXQgc3Rha2luZ1dhbGxldC51bnN0YWtlKHtcbiAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIHN0YWtpbmdSZXF1ZXN0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWQpO1xuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3dpdGNoIHZhbGlkYXRvcicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNhbGwgc3Rha2luZy1zZXJ2aWNlIHRvIHN3aXRjaCB2YWxpZGF0b3InLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5wb3N0KGAvYXBpL3N0YWtpbmcvdjEvJHtzdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtzdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0c2AsIHtcbiAgICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgICBjbGllbnRJZDogJ2NsaWVudElkJyxcbiAgICAgICAgICB2YWxpZGF0b3I6ICd2YWxpZGF0b3InLFxuICAgICAgICAgIGRlbGVnYXRpb25JZDogJ2RlbGVnYXRpb24nLFxuICAgICAgICAgIHR5cGU6ICdTV0lUQ0hfVkFMSURBVE9SJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGx5KDIwMSwgZXhwZWN0ZWQpO1xuXG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdCA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuc3dpdGNoVmFsaWRhdG9yKHtcbiAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICB2YWxpZGF0b3I6ICd2YWxpZGF0b3InLFxuICAgICAgICBkZWxlZ2F0aW9uSWQ6ICdkZWxlZ2F0aW9uJyxcbiAgICAgIH0pO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NsYWltIHJld2FyZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byBjbGFpbSByZXdhcmRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHNgLCB7XG4gICAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgICAgZGVsZWdhdGlvbklkOiAnZGVsZWdhdGlvbicsXG4gICAgICAgICAgdHlwZTogJ0NMQUlNX1JFV0FSRFMnLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAxLCBleHBlY3RlZCk7XG5cbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0ID0gYXdhaXQgc3Rha2luZ1dhbGxldC5jbGFpbVJld2FyZHMoe1xuICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgIGRlbGVnYXRpb25JZDogJ2RlbGVnYXRpb24nLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIHN0YWtpbmdSZXF1ZXN0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWQpO1xuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY2FuY2VsU3Rha2luZ1JlcXVlc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byBjYW5jZWwgc3Rha2luZyByZXF1ZXN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSB7XG4gICAgICAgIC4uLmZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignUkVKRUNURUQnKV0pLFxuICAgICAgICBzdGF0dXM6ICdSRUpFQ1RFRCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmRlbGV0ZShgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHtzdGFraW5nUmVxdWVzdElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LmNhbmNlbFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldFN0YWtpbmdSZXF1ZXN0JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY2FsbCBzdGFraW5nLXNlcnZpY2UgdG8gZ2V0IHN0YWtpbmcgcmVxdWVzdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0SWQgPSAnODYzODI4NGEtZGFiMi00NmI5LWIwN2YtMjExMDlhNmU3MjIwJztcbiAgICAgIGNvbnN0IGV4cGVjdGVkID0gZml4dHVyZXMuc3Rha2luZ1JlcXVlc3QoW2ZpeHR1cmVzLnRyYW5zYWN0aW9uKCdORVcnKV0pO1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHtzdGFraW5nUmVxdWVzdElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LmdldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldFRyYW5zYWN0aW9uc1JlYWR5VG9TaWduJywgZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIG1vY2tHZXRTdGFraW5nUmVxdWVzdChzdGFraW5nUmVxdWVzdElkOiBzdHJpbmcsIGV4cGVjdGVkOiBTdGFraW5nUmVxdWVzdCkge1xuICAgICAgcmV0dXJuIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHtzdGFraW5nUmVxdWVzdElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkKTtcbiAgICB9XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBhbGxTaWduaW5nQ29tcGxldGUgZmFsc2Ugd2hlbiBubyB0cmFuc2FjdGlvbnMgZXhpc3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdElkID0gJzg2MzgyODRhLWRhYjItNDZiOS1iMDdmLTIxMTA5YTZlNzIyMCc7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtdKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBtb2NrR2V0U3Rha2luZ1JlcXVlc3Qoc3Rha2luZ1JlcXVlc3RJZCwgZXhwZWN0ZWQpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuZ2V0VHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24oc3Rha2luZ1JlcXVlc3RJZCk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbik7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi5hbGxTaWduaW5nQ29tcGxldGUuc2hvdWxkLmJlLkZhbHNlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSB0cnVlIGFuZCAwIHRyYW5zYWN0aW9ucyB3aGVuIG9ubHkgYSBDT05GSVJNRUQgdHJhbnNhY3Rpb24gZXhpc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ0NPTkZJUk1FRCcpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbW9ja0dldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24gPSBhd2FpdCBzdGFraW5nV2FsbGV0LmdldFRyYW5zYWN0aW9uc1JlYWR5VG9TaWduKHN0YWtpbmdSZXF1ZXN0SWQpO1xuXG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24pO1xuICAgICAgdHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24uYWxsU2lnbmluZ0NvbXBsZXRlLnNob3VsZC5iZS5UcnVlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSBmYWxzZSBhbmQgMCB0cmFuc2FjdGlvbnMgd2hlbiBvbmx5IGEgTkVXIHRyYW5zYWN0aW9uIGV4aXN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0SWQgPSAnODYzODI4NGEtZGFiMi00NmI5LWIwN2YtMjExMDlhNmU3MjIwJztcbiAgICAgIGNvbnN0IGV4cGVjdGVkU3Rha2luZ1JlcXVlc3QgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbW9ja0dldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQsIGV4cGVjdGVkU3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuZ2V0VHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24oc3Rha2luZ1JlcXVlc3RJZCk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbik7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi5hbGxTaWduaW5nQ29tcGxldGUuc2hvdWxkLmJlLkZhbHNlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSBmYWxzZSBhbmQgMSB0cmFuc2FjdGlvbnMgd2hlbiBvbmx5IGEgUkVBRFkgdHJhbnNhY3Rpb24gZXhpc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUcmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRTdGFraW5nUmVxdWVzdCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtleHBlY3RlZFRyYW5zYWN0aW9uXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbW9ja0dldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQsIGV4cGVjdGVkU3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuZ2V0VHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24oc3Rha2luZ1JlcXVlc3RJZCk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbik7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi5hbGxTaWduaW5nQ29tcGxldGUuc2hvdWxkLmJlLkZhbHNlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmNvbnRhaW5FcWwoZXhwZWN0ZWRUcmFuc2FjdGlvbik7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSBmYWxzZSBhbmQgMSB0cmFuc2FjdGlvbiB3aGVuIE5FVyBhbmQgUkVBRFkgdHJhbnNhY3Rpb24gZXhpc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUcmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRTdGFraW5nUmVxdWVzdCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtleHBlY3RlZFRyYW5zYWN0aW9uLCBmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBtb2NrR2V0U3Rha2luZ1JlcXVlc3Qoc3Rha2luZ1JlcXVlc3RJZCwgZXhwZWN0ZWRTdGFraW5nUmVxdWVzdCk7XG5cbiAgI