bitgo
Version:
BitGo JavaScript SDK
343 lines • 58.8 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();
});
it('should preserve existing staking subtypes in the request payload', 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',
subType: 'ETH_STAKE_PECTRA',
type: 'STAKE',
})
.reply(201, expected);
const stakingRequest = await stakingWallet.stake({
amount: '1',
clientId: 'clientId',
subType: 'ETH_STAKE_PECTRA',
});
should.exist(stakingRequest);
stakingRequest.should.deepEqual(expected);
msScope.isDone().should.be.True();
});
it('should reject incomplete pox5-bond options before making a request', async function () {
await stakingWallet
.stake({ subType: 'pox5-bond' })
.should.be.rejectedWith('bondIndex is required for pox5-bond staking');
});
});
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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QU0sQ0FBQyxVQUFVLENBQUMscUJBQXFCLENBQUMsQ0FBQztZQUVqRCxNQUFNLFFBQVEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsZUFBZSxDQUFDLENBQUM7WUFFakYsa0JBQWtCLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM5QyxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgc2hvdWxkID0gcmVxdWlyZSgnc2hvdWxkJyk7XG5pbXBvcnQgZml4dHVyZXMgZnJvbSAnLi4vLi4vZml4dHVyZXMvc3Rha2luZy9zdGFraW5nV2FsbGV0JztcblxuaW1wb3J0IHsgRW50ZXJwcmlzZSwgRW52aXJvbm1lbnRzLCBTdGFraW5nUmVxdWVzdCwgU3Rha2luZ1dhbGxldCwgVHNzVXRpbHMsIFdhbGxldCB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R28gfSBmcm9tICcuLi8uLi8uLi8uLi9zcmMnO1xuaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuXG5kZXNjcmliZSgnU3Rha2luZyBXYWxsZXQgQ29tbW9uJywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBtaWNyb3NlcnZpY2VzVXJpID0gRW52aXJvbm1lbnRzWydtb2NrJ10udXJpO1xuICBsZXQgYml0Z287XG4gIGxldCBiYXNlQ29pbjtcbiAgbGV0IGVudGVycHJpc2U7XG4gIGxldCBzdGFraW5nV2FsbGV0OiBTdGFraW5nV2FsbGV0O1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycsIG1pY3Jvc2VydmljZXNVcmkgfSBhcyBhbnkpO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJhc2VDb2luID0gYml0Z28uY29pbignZXRoJyk7XG4gICAgYmFzZUNvaW4ua2V5Y2hhaW5zKCk7XG4gICAgZW50ZXJwcmlzZSA9IG5ldyBFbnRlcnByaXNlKGJpdGdvLCBiYXNlQ29pbiwgeyBpZDogJzVjZjk0MDk0OTQ0OTQxMmQwMGY1M2IzZDkyZGJjYWEzJywgbmFtZTogJ1Rlc3QgRW50ZXJwcmlzZScgfSk7XG4gICAgY29uc3Qgd2FsbGV0RGF0YSA9IHtcbiAgICAgIGlkOiAnd2FsbGV0SWQnLFxuICAgICAgY29pbjogJ2V0aCcsXG4gICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlLmlkLFxuICAgICAga2V5czogWyc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzUnXSxcbiAgICB9O1xuICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB3YWxsZXREYXRhKTtcbiAgICBzdGFraW5nV2FsbGV0ID0gd2FsbGV0LnRvU3Rha2luZ1dhbGxldCgpO1xuICB9KTtcblxuICBjb25zdCBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdzdGFrZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNhbGwgc3Rha2luZy1zZXJ2aWNlIHRvIHN0YWtlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHNgLCB7XG4gICAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgICAgdHlwZTogJ1NUQUtFJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGx5KDIwMSwgZXhwZWN0ZWQpO1xuXG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdCA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuc3Rha2Uoe1xuICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICB9KTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHN0YWtpbmdSZXF1ZXN0KTtcblxuICAgICAgc3Rha2luZ1JlcXVlc3Quc2hvdWxkLmRlZXBFcXVhbChleHBlY3RlZCk7XG4gICAgICBtc1Njb3BlLmlzRG9uZSgpLnNob3VsZC5iZS5UcnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgc3Rha2luZy1zZXJ2aWNlIHRvIHN0YWtlIHdpdGggb3B0aW9uYWwgcGFyYW1ldGVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkID0gZml4dHVyZXMuc3Rha2luZ1JlcXVlc3QoW2ZpeHR1cmVzLnRyYW5zYWN0aW9uKCdORVcnKV0pO1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLnBvc3QoYC9hcGkvc3Rha2luZy92MS8ke3N0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke3N0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzYCwge1xuICAgICAgICAgIGFtb3VudDogJzEnLFxuICAgICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICAgIHR5cGU6ICdTVEFLRScsXG4gICAgICAgICAgdmFsaWRhdG9yOiAnMTIzJyxcbiAgICAgICAgICBkdXJhdGlvblNlY29uZHM6ICc2MCcsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDEsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICB2YWxpZGF0b3I6ICcxMjMnLFxuICAgICAgICBkdXJhdGlvblNlY29uZHM6ICc2MCcsXG4gICAgICB9O1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LnN0YWtlKG9wdGlvbnMpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBzdGFraW5nLXNlcnZpY2UgdG8gc3Rha2Ugd2l0aCBvcHRpb25hbCBzdGFrZU1hbnkgcGFyYW1ldGVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkID0gZml4dHVyZXMuc3Rha2luZ1JlcXVlc3QoW2ZpeHR1cmVzLnRyYW5zYWN0aW9uKCdORVcnKV0pO1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLnBvc3QoYC9hcGkvc3Rha2luZy92MS8ke3N0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke3N0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzYCwge1xuICAgICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICAgIHR5cGU6ICdTVEFLRScsXG4gICAgICAgICAgZGVsZWdhdGlvblJlcXVlc3RzOiBbXG4gICAgICAgICAgICB7IGFtb3VudDogJzEnLCB2YWxpZGF0b3I6ICcxMjMnIH0sXG4gICAgICAgICAgICB7IGFtb3VudDogJzInLCB2YWxpZGF0b3I6ICc0NTYnIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkdXJhdGlvblNlY29uZHM6ICc2MCcsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDEsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgIGRlbGVnYXRpb25SZXF1ZXN0czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMScsIHZhbGlkYXRvcjogJzEyMycgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzInLCB2YWxpZGF0b3I6ICc0NTYnIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGR1cmF0aW9uU2Vjb25kczogJzYwJyxcbiAgICAgIH07XG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdCA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuc3Rha2Uob3B0aW9ucyk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIHN0YWtpbmdSZXF1ZXN0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWQpO1xuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBleGlzdGluZyBzdGFraW5nIHN1YnR5cGVzIGluIHRoZSByZXF1ZXN0IHBheWxvYWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5wb3N0KGAvYXBpL3N0YWtpbmcvdjEvJHtzdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtzdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0c2AsIHtcbiAgICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgICBjbGllbnRJZDogJ2NsaWVudElkJyxcbiAgICAgICAgICBzdWJUeXBlOiAnRVRIX1NUQUtFX1BFQ1RSQScsXG4gICAgICAgICAgdHlwZTogJ1NUQUtFJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGx5KDIwMSwgZXhwZWN0ZWQpO1xuXG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdCA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuc3Rha2Uoe1xuICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgIHN1YlR5cGU6ICdFVEhfU1RBS0VfUEVDVFJBJyxcbiAgICAgIH0pO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuICAgICAgc3Rha2luZ1JlcXVlc3Quc2hvdWxkLmRlZXBFcXVhbChleHBlY3RlZCk7XG4gICAgICBtc1Njb3BlLmlzRG9uZSgpLnNob3VsZC5iZS5UcnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBpbmNvbXBsZXRlIHBveDUtYm9uZCBvcHRpb25zIGJlZm9yZSBtYWtpbmcgYSByZXF1ZXN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgc3Rha2luZ1dhbGxldFxuICAgICAgICAuc3Rha2UoeyBzdWJUeXBlOiAncG94NS1ib25kJyB9IGFzIGFueSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2JvbmRJbmRleCBpcyByZXF1aXJlZCBmb3IgcG94NS1ib25kIHN0YWtpbmcnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3Vuc3Rha2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byB1bnN0YWtlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHNgLCB7XG4gICAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgICAgdHlwZTogJ1VOU1RBS0UnLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAxLCBleHBlY3RlZCk7XG5cbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0ID0gYXdhaXQgc3Rha2luZ1dhbGxldC51bnN0YWtlKHtcbiAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIHN0YWtpbmdSZXF1ZXN0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWQpO1xuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3dpdGNoIHZhbGlkYXRvcicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNhbGwgc3Rha2luZy1zZXJ2aWNlIHRvIHN3aXRjaCB2YWxpZGF0b3InLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5wb3N0KGAvYXBpL3N0YWtpbmcvdjEvJHtzdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtzdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0c2AsIHtcbiAgICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgICBjbGllbnRJZDogJ2NsaWVudElkJyxcbiAgICAgICAgICB2YWxpZGF0b3I6ICd2YWxpZGF0b3InLFxuICAgICAgICAgIGRlbGVnYXRpb25JZDogJ2RlbGVnYXRpb24nLFxuICAgICAgICAgIHR5cGU6ICdTV0lUQ0hfVkFMSURBVE9SJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGx5KDIwMSwgZXhwZWN0ZWQpO1xuXG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdCA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuc3dpdGNoVmFsaWRhdG9yKHtcbiAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIGNsaWVudElkOiAnY2xpZW50SWQnLFxuICAgICAgICB2YWxpZGF0b3I6ICd2YWxpZGF0b3InLFxuICAgICAgICBkZWxlZ2F0aW9uSWQ6ICdkZWxlZ2F0aW9uJyxcbiAgICAgIH0pO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NsYWltIHJld2FyZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byBjbGFpbSByZXdhcmRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAucG9zdChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHNgLCB7XG4gICAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgICAgZGVsZWdhdGlvbklkOiAnZGVsZWdhdGlvbicsXG4gICAgICAgICAgdHlwZTogJ0NMQUlNX1JFV0FSRFMnLFxuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAxLCBleHBlY3RlZCk7XG5cbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0ID0gYXdhaXQgc3Rha2luZ1dhbGxldC5jbGFpbVJld2FyZHMoe1xuICAgICAgICBhbW91bnQ6ICcxJyxcbiAgICAgICAgY2xpZW50SWQ6ICdjbGllbnRJZCcsXG4gICAgICAgIGRlbGVnYXRpb25JZDogJ2RlbGVnYXRpb24nLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIHN0YWtpbmdSZXF1ZXN0LnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWQpO1xuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY2FuY2VsU3Rha2luZ1JlcXVlc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjYWxsIHN0YWtpbmctc2VydmljZSB0byBjYW5jZWwgc3Rha2luZyByZXF1ZXN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSB7XG4gICAgICAgIC4uLmZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtmaXh0dXJlcy50cmFuc2FjdGlvbignUkVKRUNURUQnKV0pLFxuICAgICAgICBzdGF0dXM6ICdSRUpFQ1RFRCcsXG4gICAgICB9O1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmRlbGV0ZShgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHtzdGFraW5nUmVxdWVzdElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LmNhbmNlbFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldFN0YWtpbmdSZXF1ZXN0JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY2FsbCBzdGFraW5nLXNlcnZpY2UgdG8gZ2V0IHN0YWtpbmcgcmVxdWVzdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0SWQgPSAnODYzODI4NGEtZGFiMi00NmI5LWIwN2YtMjExMDlhNmU3MjIwJztcbiAgICAgIGNvbnN0IGV4cGVjdGVkID0gZml4dHVyZXMuc3Rha2luZ1JlcXVlc3QoW2ZpeHR1cmVzLnRyYW5zYWN0aW9uKCdORVcnKV0pO1xuICAgICAgY29uc3QgbXNTY29wZSA9IG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHtzdGFraW5nUmVxdWVzdElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3QgPSBhd2FpdCBzdGFraW5nV2FsbGV0LmdldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQpO1xuXG4gICAgICBzaG91bGQuZXhpc3Qoc3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBzdGFraW5nUmVxdWVzdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldFRyYW5zYWN0aW9uc1JlYWR5VG9TaWduJywgZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIG1vY2tHZXRTdGFraW5nUmVxdWVzdChzdGFraW5nUmVxdWVzdElkOiBzdHJpbmcsIGV4cGVjdGVkOiBTdGFraW5nUmVxdWVzdCkge1xuICAgICAgcmV0dXJuIG5vY2sobWljcm9zZXJ2aWNlc1VyaSlcbiAgICAgICAgLmdldChgL2FwaS9zdGFraW5nL3YxLyR7c3Rha2luZ1dhbGxldC5jb2lufS93YWxsZXRzLyR7c3Rha2luZ1dhbGxldC53YWxsZXRJZH0vcmVxdWVzdHMvJHtzdGFraW5nUmVxdWVzdElkfWApXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkKTtcbiAgICB9XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBhbGxTaWduaW5nQ29tcGxldGUgZmFsc2Ugd2hlbiBubyB0cmFuc2FjdGlvbnMgZXhpc3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdGFraW5nUmVxdWVzdElkID0gJzg2MzgyODRhLWRhYjItNDZiOS1iMDdmLTIxMTA5YTZlNzIyMCc7XG4gICAgICBjb25zdCBleHBlY3RlZCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtdKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBtb2NrR2V0U3Rha2luZ1JlcXVlc3Qoc3Rha2luZ1JlcXVlc3RJZCwgZXhwZWN0ZWQpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuZ2V0VHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24oc3Rha2luZ1JlcXVlc3RJZCk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbik7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi5hbGxTaWduaW5nQ29tcGxldGUuc2hvdWxkLmJlLkZhbHNlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSB0cnVlIGFuZCAwIHRyYW5zYWN0aW9ucyB3aGVuIG9ubHkgYSBDT05GSVJNRUQgdHJhbnNhY3Rpb24gZXhpc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ0NPTkZJUk1FRCcpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbW9ja0dldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQsIGV4cGVjdGVkKTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24gPSBhd2FpdCBzdGFraW5nV2FsbGV0LmdldFRyYW5zYWN0aW9uc1JlYWR5VG9TaWduKHN0YWtpbmdSZXF1ZXN0SWQpO1xuXG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24pO1xuICAgICAgdHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24uYWxsU2lnbmluZ0NvbXBsZXRlLnNob3VsZC5iZS5UcnVlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSBmYWxzZSBhbmQgMCB0cmFuc2FjdGlvbnMgd2hlbiBvbmx5IGEgTkVXIHRyYW5zYWN0aW9uIGV4aXN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YWtpbmdSZXF1ZXN0SWQgPSAnODYzODI4NGEtZGFiMi00NmI5LWIwN2YtMjExMDlhNmU3MjIwJztcbiAgICAgIGNvbnN0IGV4cGVjdGVkU3Rha2luZ1JlcXVlc3QgPSBmaXh0dXJlcy5zdGFraW5nUmVxdWVzdChbZml4dHVyZXMudHJhbnNhY3Rpb24oJ05FVycpXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbW9ja0dldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQsIGV4cGVjdGVkU3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuZ2V0VHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24oc3Rha2luZ1JlcXVlc3RJZCk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbik7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi5hbGxTaWduaW5nQ29tcGxldGUuc2hvdWxkLmJlLkZhbHNlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSBmYWxzZSBhbmQgMSB0cmFuc2FjdGlvbnMgd2hlbiBvbmx5IGEgUkVBRFkgdHJhbnNhY3Rpb24gZXhpc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUcmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRTdGFraW5nUmVxdWVzdCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtleHBlY3RlZFRyYW5zYWN0aW9uXSk7XG4gICAgICBjb25zdCBtc1Njb3BlID0gbW9ja0dldFN0YWtpbmdSZXF1ZXN0KHN0YWtpbmdSZXF1ZXN0SWQsIGV4cGVjdGVkU3Rha2luZ1JlcXVlc3QpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQuZ2V0VHJhbnNhY3Rpb25zUmVhZHlUb1NpZ24oc3Rha2luZ1JlcXVlc3RJZCk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbik7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi5hbGxTaWduaW5nQ29tcGxldGUuc2hvdWxkLmJlLkZhbHNlKCk7XG4gICAgICB0cmFuc2FjdGlvbnNSZWFkeVRvU2lnbi50cmFuc2FjdGlvbnMuc2hvdWxkLmNvbnRhaW5FcWwoZXhwZWN0ZWRUcmFuc2FjdGlvbik7XG5cbiAgICAgIG1zU2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLlRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGFsbFNpZ25pbmdDb21wbGV0ZSBmYWxzZSBhbmQgMSB0cmFuc2FjdGlvbiB3aGVuIE5FVyBhbmQgUkVBRFkgdHJhbnNhY3Rpb24gZXhpc3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3Rha2luZ1JlcXVlc3RJZCA9ICc4NjM4Mjg0YS1kYWIyLTQ2YjktYjA3Zi0yMTEwOWE2ZTcyMjAnO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUcmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRTdGFraW5nUmVxdWVzdCA9IGZpeHR1cmVzLnN0YWtpbmdSZXF1ZXN0KFtleHBlY3RlZFRyYW5zYWN0aW9uLCBmaXh0dXJlcy50cmFuc2FjdGlvbignTkVXJyldKTtcbiAgICAgIGNvbnN0IG1zU2NvcGUgPSBtb2NrR2V0U3Rha2luZ1JlcXVlc3Qoc3Rha2luZ1JlcXVlc3RJZCwgZXhwZWN0ZWRTdGFraW5nUmVxdWVzdCk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uc1JlYWR5VG9TaWduID0gYXdhaXQgc3Rha2luZ1dhbGxldC5nZXRUcmFuc2FjdGlvbnNSZWFkeVRvU2lnbihzdGFraW5nUmVxdWVzdElkKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uc1JlYWR5VG9TaWduKTtcbiAgICAgIHRyYW5zYWN0aW9uc1JlYWR5VG9TaWduLmFsbFNpZ25pbmdDb21wbGV0ZS5zaG91bGQuYmUuRmFsc2UoKTtcbiAgICAgIHRyYW5zYWN0aW9uc1JlYWR5VG9TaWduLnRyYW5zYWN0aW9ucy5zaG91bGQuY29udGFpbkVxbChleHBlY3RlZFRyYW5zYWN0aW9uKTtcblxuICAgICAgbXNTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUuVHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncHJlYnVpbGRTZWxmTWFuYWdlZFN0YWtpbmdUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByZWJ1aWxkIHNlbGYtbWFuYWdlZCBzdGFraW5nIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSBmaXh0dXJlcy50cmFuc2FjdGlvbignUkVBRFknLCBmaXh0dXJlcy5idWlsZFBhcmFtcywgZmFsc2UpO1xuICAgICAgbm9jayhtaWNyb3NlcnZpY2VzVXJpKVxuICAgICAgICAuZ2V0KFxuICAgICAgICAgIGAvYXBpL3N0YWtpbmcvdjEvJHtzdGFraW5nV2FsbGV0LmNvaW59L3dhbGxldHMvJHtzdGFraW5nV2FsbGV0LndhbGxldElkfS9yZXF1ZXN0cy8ke3RyYW5zYWN0aW9uLnN0YWtpbmdSZXF1ZXN0SWR9L3RyYW5zYWN0aW9ucy8ke3RyYW5zYWN0aW9uLmlkfWBcbiAgICAgICAgKVxuICAgICAgICAucXVlcnkoeyBleHBhbmRCdWlsZFBhcmFtczogdHJ1ZSB9KVxuICAgICAgICAucmVwbHkoMjAwLCB0cmFuc2FjdGlvbik7XG5cbiAgICAgIGNvbnN0IGRlbGV0ZVNpZ25hdHVyZVNoYXJlcyA9IHNhbmRib3guc3R1YihUc3NVdGlscy5wcm90b3R5cGUsICdkZWxldGVTaWduYXR1cmVTaGFyZXMnKTtcbiAgICAgIGNvbnN0IHByZWJ1aWxkVHJhbnNhY3Rpb24gPSBzYW5kYm94LnN0dWIoV2FsbGV0LnByb3RvdHlwZSwgJ3ByZWJ1aWxkVHJhbnNhY3Rpb24nKTtcbiAgICAgIGNvbnN0IGJ1aWxkID0gc2FuZGJveC5zdHViKFN0YWtpbmdXYWxsZXQucHJvdG90eXBlLCAnYnVpbGQnKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHdhbGxldElkOiBzdGFraW5nV2FsbGV0LndhbGxldElkLFxuICAgICAgICB0eEhleDogJ2hleCcsXG4gICAgICAgIGJ1aWxkUGFyYW1zOiB0cmFuc2FjdGlvbi5idWlsZFBhcmFtcyxcbiAgICAgIH07XG4gICAgICBwcmVidWlsZFRyYW5zYWN0aW9uLnJlc29sdmVzKHR4UHJlYnVpbGQpO1xuICAgICAgcHJlYnVpbGRUcmFuc2FjdGlvbi5jYWxsZWRPbmNlV2l0aEV4YWN0bHkodHJhbnNhY3Rpb24uYnVpbGRQYXJhbXMpO1xuICAgICAgY29uc3QgZm9ybWF0dGVkUGFyYW1zID0ge1xuICAgICAgICAuLi5maXh0dXJlcy5idWlsZFBhcmFtcyxcbiAgICAgICAgY29pbjogc3Rha2luZ1dhbGxldC5jb2luLFxuICAgICAgICB3YWxsZXRJZDogc3Rha2luZ1dhbGxldC53YWxsZXRJZCxcbiAgICAgICAgd2FsbGV0VHlwZTogc3Rha2luZ1dhbGxldC53YWxsZXQudHlwZSgpLFxuICAgICAgICBwcmV2aWV3OiB0cnVlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHN0YWtpbmdUcmFuc2FjdGlvbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQucHJlYnVpbGRTZWxmTWFuYWdlZFN0YWtpbmdUcmFuc2FjdGlvbih0cmFuc2FjdGlvbik7XG4gICAgICBzYW5kYm94LmFzc2VydC5jYWxsZWRPbmNlKHByZWJ1aWxkVHJhbnNhY3Rpb24pO1xuICAgICAgc2FuZGJveC5hc3NlcnQubm90Q2FsbGVkKGJ1aWxkKTtcbiAgICAgIHNhbmRib3guYXNzZXJ0Lm5vdENhbGxlZChkZWxldGVTaWduYXR1cmVTaGFyZXMpO1xuXG4gICAgICBjb25zdCBleHBlY3RlZCA9IGF3YWl0IHN0YWtpbmdXYWxsZXQud2FsbGV0LnByZWJ1aWxkVHJhbnNhY3Rpb24oZm9ybWF0dGVkUGFyYW1zKTtcbiAgICAgIHN0YWtpbmdUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nVHJhbnNhY3Rpb24pO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgcHJlYnVpbGQgc2VsZi1tYW5hZ2VkIHN0YWtpbmcgdHJhbnNhY3Rpb24gLSBubyBidWlsZCBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGZpeHR1cmVzLnRyYW5zYWN0aW9uKCdSRUFEWScsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICBub2NrKG1pY3Jvc2VydmljZXNVcmkpXG4gICAgICAgIC5nZXQoXG4gICAgICAgICAgYC9hcGkvc3Rha2luZy92MS8ke3N0YWtpbmdXYWxsZXQuY29pbn0vd2FsbGV0cy8ke3N0YWtpbmdXYWxsZXQud2FsbGV0SWR9L3JlcXVlc3RzLyR7dHJhbnNhY3Rpb24uc3Rha2luZ1JlcXVlc3RJZH0vdHJhbnNhY3Rpb25zLyR7dHJhbnNhY3Rpb24uaWR9YFxuICAgICAgICApXG4gICAgICAgIC5xdWVyeSh7IGV4cGFuZEJ1aWxkUGFyYW1zOiB0cnVlIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHRyYW5zYWN0aW9uKTtcblxuICAgICAgY29uc3QgZGVsZXRlU2lnbmF0dXJlU2hhcmVzID0gc2FuZGJveC5zdHViKFRzc1V0aWxzLnByb3RvdHlwZSwgJ2RlbGV0ZVNpZ25hdHVyZVNoYXJlcycpO1xuICAgICAgY29uc3QgcHJlYnVpbGRUcmFuc2FjdGlvbiA9IHNhbmRib3guc3R1YihXYWxsZXQucHJvdG90eXBlLCAncHJlYnVpbGRUcmFuc2FjdGlvbicpO1xuICAgICAgY29uc3QgYnVpbGQgPSBzYW5kYm94LnN0dWIoU3Rha2luZ1dhbGxldC5wcm90b3R5cGUsICdidWlsZCcpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgd2FsbGV0SWQ6IHN0YWtpbmdXYWxsZXQud2FsbGV0SWQsXG4gICAgICAgIHR4SGV4OiAnaGV4JyxcbiAgICAgIH07XG4gICAgICBwcmVidWlsZFRyYW5zYWN0aW9uLnJlc29sdmVzKHR4UHJlYnVpbGQpO1xuICAgICAgaWYgKHRyYW5zYWN0aW9uLnR4UmVxdWVzdElkKSB7XG4gICAgICAgIGRlbGV0ZVNpZ25hdHVyZVNoYXJlcy5jYWxsZWRPbmNlV2l0aEV4YWN0bHkodHJhbnNhY3Rpb24udHhSZXF1ZXN0SWQpO1xuICAgICAgfVxuICAgICAgY29uc3QgZm9ybWF0dGVkUGFyYW1zID0ge1xuICAgICAgICAuLi5maXh0dXJlcy5idWlsZFBhcmFtcyxcbiAgICAgICAgY29pbjogc3Rha2luZ1dhbGxldC5jb2luLFxuICAgICAgICB3YWxsZXRJZDogc3Rha2luZ1dhbGxldC53YWxsZXRJZCxcbiAgICAgICAgd2FsbGV0VHlwZTogc3Rha2luZ1dhbGxldC53YWxsZXQudHlwZSgpLFxuICAgICAgICBwcmV2aWV3OiB0cnVlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHN0YWtpbmdUcmFuc2FjdGlvbiA9IGF3YWl0IHN0YWtpbmdXYWxsZXQucHJlYnVpbGRTZWxmTWFuYWdlZFN0YWtpbmdUcmFuc2FjdGlvbih0cmFuc2FjdGlvbik7XG4gICAgICBzYW5kYm94LmFzc2VydC5jYWxsZWRPbmNlKHByZWJ1aWxkVHJhbnNhY3Rpb24pO1xuICAgICAgc2FuZGJveC5hc3NlcnQubm90Q2FsbGVkKGJ1aWxkKTtcbiAgICAgIHNhbmRib3guYXNzZXJ0LmNhbGxlZE9uY2UoZGVsZXRlU2lnbmF0dXJlU2hhcmVzKTtcblxuICAgICAgY29uc3QgZXhwZWN0ZWQgPSBhd2FpdCBzdGFraW5nV2FsbGV0LndhbGxldC5wcmVidWlsZFRyYW5zYWN0aW9uKGZvcm1hdHRlZFBhcmFtcyk7XG5cbiAgICAgIHN0YWtpbmdUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkKTtcbiAgICAgIHNob3VsZC5leGlzdChzdGFraW5nVHJhbnNhY3Rpb24pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19