@bitgo-beta/sdk-coin-polygon 1.3.3-alpha.45 → 1.3.3-alpha.450
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/index.js +6 -2
- package/dist/src/lib/index.d.ts +2 -1
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +30 -12
- package/dist/src/lib/resources.d.ts.map +1 -1
- package/dist/src/lib/resources.js +8 -4
- package/dist/src/lib/transactionBuilder.d.ts +11 -8
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +21 -21
- package/dist/src/lib/transferBuilder.d.ts +1 -1
- package/dist/src/lib/transferBuilder.js +3 -3
- package/dist/src/lib/utils.d.ts +1 -1
- package/dist/src/lib/utils.js +6 -6
- package/dist/src/polygon.d.ts +23 -63
- package/dist/src/polygon.d.ts.map +1 -1
- package/dist/src/polygon.js +26 -392
- package/dist/src/polygonToken.d.ts +15 -24
- package/dist/src/polygonToken.d.ts.map +1 -1
- package/dist/src/polygonToken.js +31 -59
- package/dist/src/tpolygon.d.ts +0 -1
- package/dist/src/tpolygon.d.ts.map +1 -1
- package/dist/src/tpolygon.js +1 -4
- package/dist/test/fixtures/polygon.d.ts +151 -0
- package/dist/test/fixtures/polygon.d.ts.map +1 -0
- package/dist/test/fixtures/polygon.js +233 -0
- package/dist/test/getBuilder.d.ts +3 -0
- package/dist/test/getBuilder.d.ts.map +1 -0
- package/dist/test/getBuilder.js +9 -0
- package/dist/test/resources.d.ts +27 -0
- package/dist/test/resources.d.ts.map +1 -0
- package/dist/test/resources.js +41 -0
- package/dist/test/unit/polygon.d.ts +2 -0
- package/dist/test/unit/polygon.d.ts.map +1 -0
- package/dist/test/unit/polygon.js +1202 -0
- package/dist/test/unit/polygonToken.d.ts +2 -0
- package/dist/test/unit/polygonToken.d.ts.map +1 -0
- package/dist/test/unit/polygonToken.js +62 -0
- package/dist/test/unit/transaction.d.ts +2 -0
- package/dist/test/unit/transaction.d.ts.map +1 -0
- package/dist/test/unit/transaction.js +92 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/addressInitialization.js +104 -0
- package/dist/test/unit/transactionBuilder/flushTokens.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/flushTokens.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/flushTokens.js +9 -0
- package/dist/test/unit/transactionBuilder/send.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/send.js +114 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/walletInitialization.js +169 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +20 -19
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -102
|
@@ -0,0 +1,1202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
40
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
41
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
42
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
43
|
+
const secp256k1_1 = require("@bitgo-beta/secp256k1");
|
|
44
|
+
const nock_1 = __importDefault(require("nock"));
|
|
45
|
+
const secp256k1 = __importStar(require("secp256k1"));
|
|
46
|
+
const should = __importStar(require("should"));
|
|
47
|
+
const src_1 = require("../../src");
|
|
48
|
+
const abstract_eth_1 = require("@bitgo-beta/abstract-eth");
|
|
49
|
+
const getBuilder_1 = require("../getBuilder");
|
|
50
|
+
const mockData = __importStar(require("../fixtures/polygon"));
|
|
51
|
+
const sjcl = __importStar(require("@bitgo-beta/sjcl"));
|
|
52
|
+
const assert_1 = __importDefault(require("assert"));
|
|
53
|
+
nock_1.default.enableNetConnect();
|
|
54
|
+
describe('Polygon', function () {
|
|
55
|
+
let bitgo;
|
|
56
|
+
let basecoin;
|
|
57
|
+
let hopTxBitgoSignature;
|
|
58
|
+
const address1 = '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be';
|
|
59
|
+
const address2 = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
|
|
60
|
+
const hopContractAddress = '0x47ce7cc86efefef19f8fb516b11735d183da8635';
|
|
61
|
+
const hopDestinationAddress = '0x9c7e8ce6825bD48278B3Ab59228EE26f8BE7925b';
|
|
62
|
+
const hopTx = '0xf86b808504a817c8ff8252ff949c7e8ce6825bd48278b3ab59228ee26f8be7925b87038d7ea4c68000801ca011bc22c664570133dfca4f08a0b8d02339cf467046d6a4152f04f368d0eaf99ea01d6dc5cf0c897c8d4c3e1df53d0d042784c424536a4cc5b802552b7d64fee8b5';
|
|
63
|
+
const hopTxid = '0x4af65143bc77da2b50f35b3d13cacb4db18f026bf84bc0743550bc57b9b53351';
|
|
64
|
+
const userReqSig = '0x404db307f6147f0d8cd338c34c13906ef46a6faa7e0e119d5194ef05aec16e6f3d710f9b7901460f97e924066b62efd74443bd34402c6d40b49c203a559ff2c8';
|
|
65
|
+
before(function () {
|
|
66
|
+
const bitgoKeyXprv = 'xprv9s21ZrQH143K3tpWBHWe31sLoXNRQ9AvRYJgitkKxQ4ATFQMwvr7hHNqYRUnS7PsjzB7aK1VxqHLuNQjj1sckJ2Jwo2qxmsvejwECSpFMfC';
|
|
67
|
+
const bitgoKey = secp256k1_1.bip32.fromBase58(bitgoKeyXprv);
|
|
68
|
+
if (!bitgoKey.privateKey) {
|
|
69
|
+
throw new Error('no privateKey');
|
|
70
|
+
}
|
|
71
|
+
const bitgoXpub = bitgoKey.neutered().toBase58();
|
|
72
|
+
hopTxBitgoSignature =
|
|
73
|
+
'0xaa' +
|
|
74
|
+
Buffer.from(secp256k1.ecdsaSign(Buffer.from(hopTxid.slice(2), 'hex'), bitgoKey.privateKey).signature).toString('hex');
|
|
75
|
+
const env = 'test';
|
|
76
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env });
|
|
77
|
+
sdk_core_1.common.Environments[env].hsmXpub = bitgoXpub;
|
|
78
|
+
bitgo.safeRegister('polygon', src_1.Polygon.createInstance);
|
|
79
|
+
bitgo.safeRegister('tpolygon', src_1.Tpolygon.createInstance);
|
|
80
|
+
bitgo.initializeTestVars();
|
|
81
|
+
basecoin = bitgo.coin('tpolygon');
|
|
82
|
+
});
|
|
83
|
+
after(function () {
|
|
84
|
+
nock_1.default.cleanAll();
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* Build an unsigned account-lib multi-signature send transactino
|
|
88
|
+
* @param destination The destination address of the transaction
|
|
89
|
+
* @param contractAddress The address of the smart contract processing the transaction
|
|
90
|
+
* @param contractSequenceId The sequence id of the contract
|
|
91
|
+
* @param nonce The nonce of the sending address
|
|
92
|
+
* @param expireTime The expire time of the transaction
|
|
93
|
+
* @param amount The amount to send to the recipient
|
|
94
|
+
* @param gasPrice The gas price of the transaction
|
|
95
|
+
* @param gasLimit The gas limit of the transaction
|
|
96
|
+
*/
|
|
97
|
+
const buildUnsignedTransaction = async function ({ destination, contractAddress, contractSequenceId = 1, nonce = 0, expireTime = Math.floor(new Date().getTime() / 1000), amount = '100000', gasPrice = '10000', gasLimit = '20000', }) {
|
|
98
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
99
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
100
|
+
txBuilder.fee({
|
|
101
|
+
fee: gasPrice,
|
|
102
|
+
gasLimit: gasLimit,
|
|
103
|
+
});
|
|
104
|
+
txBuilder.counter(nonce);
|
|
105
|
+
txBuilder.contract(contractAddress);
|
|
106
|
+
const transferBuilder = txBuilder.transfer();
|
|
107
|
+
transferBuilder
|
|
108
|
+
.coin('tpolygon')
|
|
109
|
+
.expirationTime(expireTime)
|
|
110
|
+
.amount(amount)
|
|
111
|
+
.to(destination)
|
|
112
|
+
.contractSequenceId(contractSequenceId);
|
|
113
|
+
return await txBuilder.build();
|
|
114
|
+
};
|
|
115
|
+
describe('Instantiate', () => {
|
|
116
|
+
it('should instantiate the coin', function () {
|
|
117
|
+
let localBasecoin = bitgo.coin('tpolygon');
|
|
118
|
+
localBasecoin.should.be.an.instanceof(src_1.Tpolygon);
|
|
119
|
+
localBasecoin = bitgo.coin('polygon');
|
|
120
|
+
localBasecoin.should.be.an.instanceof(src_1.Polygon);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('Explain transaction:', () => {
|
|
124
|
+
it('should fail if the options object is missing parameters', async function () {
|
|
125
|
+
const explainParams = {
|
|
126
|
+
feeInfo: { fee: 1 },
|
|
127
|
+
txHex: null,
|
|
128
|
+
};
|
|
129
|
+
await basecoin.explainTransaction(explainParams).should.be.rejectedWith('missing explain tx parameters');
|
|
130
|
+
});
|
|
131
|
+
it('explain a transfer transaction', async function () {
|
|
132
|
+
const destination = '0xfaa8f14f46a99eb439c50e0c3b835cc21dad51b4';
|
|
133
|
+
const contractAddress = '0x9e2c5712ab4caf402a98c4bf58c79a0dfe718ad1';
|
|
134
|
+
const unsignedTransaction = await buildUnsignedTransaction({
|
|
135
|
+
destination,
|
|
136
|
+
contractAddress,
|
|
137
|
+
});
|
|
138
|
+
const explainParams = {
|
|
139
|
+
halfSigned: {
|
|
140
|
+
txHex: unsignedTransaction.toBroadcastFormat(),
|
|
141
|
+
},
|
|
142
|
+
feeInfo: { fee: 1 },
|
|
143
|
+
};
|
|
144
|
+
const explanation = await basecoin.explainTransaction(explainParams);
|
|
145
|
+
should.exist(explanation.id);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe('Sign Transaction', () => {
|
|
149
|
+
const account_1 = {
|
|
150
|
+
address: '0x8Ce59c2d1702844F8EdED451AA103961bC37B4e8',
|
|
151
|
+
owner_1: '4ee089aceabf3ddbf748db79b1066c33b7d3ea1ab3eb7e325121bba2bff2f5ca',
|
|
152
|
+
owner_2: '5c7e4efff7304d4dfff6d5f1591844ec6f2adfa6a47e9fece6a3c1a4d755f1e3',
|
|
153
|
+
owner_3: '4421ab25dd91e1a3180d03d57c323a7886dcc313d3b3a4b4256a5791572bf597',
|
|
154
|
+
};
|
|
155
|
+
const account_2 = {
|
|
156
|
+
address: '0xeeaf0F05f37891ab4a21208B105A0687d12c5aF7',
|
|
157
|
+
owner_1: '4ee089aceabf3ddbf748db79b1066c33b7d3ea1ab3eb7e325121bba2bff2f5ca',
|
|
158
|
+
owner_2: '5ca116d25aec5f765465432cc421ff25ef9ffdc330b10bb3d9ad61e3baad88d7',
|
|
159
|
+
owner_3: '1fae946cc84af8bd74d610a88537e24e19c3349d478d86fc5bb59ba4c88fb9cc',
|
|
160
|
+
};
|
|
161
|
+
it('should sign an unsigned test tx', async function () {
|
|
162
|
+
const builder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
163
|
+
builder.fee({
|
|
164
|
+
fee: '280000000000',
|
|
165
|
+
gasLimit: '7000000',
|
|
166
|
+
});
|
|
167
|
+
builder.counter(1);
|
|
168
|
+
builder.type(sdk_core_1.TransactionType.Send);
|
|
169
|
+
builder.contract(account_1.address);
|
|
170
|
+
builder.transfer().amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);
|
|
171
|
+
const unsignedTx = await builder.build();
|
|
172
|
+
const unsignedTxForBroadcasting = unsignedTx.toBroadcastFormat();
|
|
173
|
+
const halfSignedRawTx = await basecoin.signTransaction({
|
|
174
|
+
txPrebuild: {
|
|
175
|
+
txHex: unsignedTxForBroadcasting,
|
|
176
|
+
},
|
|
177
|
+
prv: account_1.owner_2,
|
|
178
|
+
});
|
|
179
|
+
builder.transfer().key(account_1.owner_2);
|
|
180
|
+
const halfSignedTx = await builder.build();
|
|
181
|
+
const halfSignedTxForBroadcasting = halfSignedTx.toBroadcastFormat();
|
|
182
|
+
halfSignedRawTx.halfSigned.txHex.should.equals(halfSignedTxForBroadcasting);
|
|
183
|
+
halfSignedRawTx.halfSigned.recipients.length.should.equals(1);
|
|
184
|
+
halfSignedRawTx.halfSigned.recipients[0].address.toLowerCase().should.equals(account_2.address.toLowerCase());
|
|
185
|
+
halfSignedRawTx.halfSigned.recipients[0].amount.toLowerCase().should.equals('1');
|
|
186
|
+
});
|
|
187
|
+
it('should sign an unsigned test tx with eip1559', async function () {
|
|
188
|
+
const builder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
189
|
+
builder.fee({
|
|
190
|
+
fee: '280000000000',
|
|
191
|
+
gasLimit: '7000000',
|
|
192
|
+
eip1559: {
|
|
193
|
+
maxFeePerGas: '7593123',
|
|
194
|
+
maxPriorityFeePerGas: '150',
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
builder.counter(1);
|
|
198
|
+
builder.type(sdk_core_1.TransactionType.Send);
|
|
199
|
+
builder.contract(account_1.address);
|
|
200
|
+
builder.transfer().amount('1').to(account_2.address).expirationTime(10000).contractSequenceId(1);
|
|
201
|
+
const unsignedTx = await builder.build();
|
|
202
|
+
const unsignedTxForBroadcasting = unsignedTx.toBroadcastFormat();
|
|
203
|
+
const halfSignedRawTx = await basecoin.signTransaction({
|
|
204
|
+
txPrebuild: {
|
|
205
|
+
txHex: unsignedTxForBroadcasting,
|
|
206
|
+
eip1559: {
|
|
207
|
+
maxFeePerGas: '7593123',
|
|
208
|
+
maxPriorityFeePerGas: '150',
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
prv: account_1.owner_2,
|
|
212
|
+
});
|
|
213
|
+
builder.transfer().key(account_1.owner_2);
|
|
214
|
+
const halfSignedTx = await builder.build();
|
|
215
|
+
const halfSignedTxForBroadcasting = halfSignedTx.toBroadcastFormat();
|
|
216
|
+
halfSignedRawTx.halfSigned.txHex.should.equals(halfSignedTxForBroadcasting);
|
|
217
|
+
halfSignedRawTx.halfSigned.recipients.length.should.equals(1);
|
|
218
|
+
halfSignedRawTx.halfSigned.recipients[0].address.toLowerCase().should.equals(account_2.address.toLowerCase());
|
|
219
|
+
halfSignedRawTx.halfSigned.recipients[0].amount.toLowerCase().should.equals('1');
|
|
220
|
+
halfSignedRawTx.halfSigned.eip1559.maxFeePerGas.should.equal('7593123');
|
|
221
|
+
halfSignedRawTx.halfSigned.eip1559.maxPriorityFeePerGas.should.equal('150');
|
|
222
|
+
});
|
|
223
|
+
it('should include isBatch field in halfSigned when signing a native batch transaction', async function () {
|
|
224
|
+
const batcherContractAddress = '0xb1b7e7cc1ecafbfd0771a5eb5454ab5b0356980d';
|
|
225
|
+
const recipients = [
|
|
226
|
+
{
|
|
227
|
+
address: account_2.address,
|
|
228
|
+
amount: '500000000000',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
address: '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6',
|
|
232
|
+
amount: '500000000000',
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
const totalAmount = recipients.reduce((sum, recipient) => new bignumber_js_1.default(sum).plus(recipient.amount).toString(), '0');
|
|
236
|
+
const BATCH_METHOD_NAME = 'batch';
|
|
237
|
+
const BATCH_METHOD_TYPES = ['address[]', 'uint256[]'];
|
|
238
|
+
const addresses = recipients.map((r) => r.address);
|
|
239
|
+
const amounts = recipients.map((r) => r.amount);
|
|
240
|
+
const batchExecutionInfo = {
|
|
241
|
+
values: [addresses, amounts],
|
|
242
|
+
totalAmount: totalAmount,
|
|
243
|
+
};
|
|
244
|
+
const ethAbi = require('ethereumjs-abi');
|
|
245
|
+
const ethUtil = require('ethereumjs-util');
|
|
246
|
+
const getMethodCallData = (functionName, types, values) => {
|
|
247
|
+
return Buffer.concat([
|
|
248
|
+
// function signature
|
|
249
|
+
ethAbi.methodID(functionName, types),
|
|
250
|
+
// function arguments
|
|
251
|
+
ethAbi.rawEncode(types, values),
|
|
252
|
+
]);
|
|
253
|
+
};
|
|
254
|
+
const batchData = ethUtil.addHexPrefix(getMethodCallData(BATCH_METHOD_NAME, BATCH_METHOD_TYPES, batchExecutionInfo.values).toString('hex'));
|
|
255
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
256
|
+
txBuilder.fee({
|
|
257
|
+
fee: '280000000000',
|
|
258
|
+
gasLimit: '7000000',
|
|
259
|
+
});
|
|
260
|
+
txBuilder.counter(1);
|
|
261
|
+
txBuilder.type(sdk_core_1.TransactionType.Send);
|
|
262
|
+
txBuilder.contract(account_1.address);
|
|
263
|
+
txBuilder
|
|
264
|
+
.transfer()
|
|
265
|
+
.amount(totalAmount)
|
|
266
|
+
.to(batcherContractAddress)
|
|
267
|
+
.data(batchData)
|
|
268
|
+
.expirationTime(10000)
|
|
269
|
+
.contractSequenceId(1);
|
|
270
|
+
const unsignedTx = await txBuilder.build();
|
|
271
|
+
const unsignedTxHex = unsignedTx.toBroadcastFormat();
|
|
272
|
+
const txPrebuild = {
|
|
273
|
+
txHex: unsignedTxHex,
|
|
274
|
+
isBatch: true,
|
|
275
|
+
recipients: [
|
|
276
|
+
{
|
|
277
|
+
amount: totalAmount,
|
|
278
|
+
address: batcherContractAddress,
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
nextContractSequenceId: 1,
|
|
282
|
+
gasPrice: 280000000000,
|
|
283
|
+
gasLimit: 7000000,
|
|
284
|
+
coin: 'tpolygon',
|
|
285
|
+
walletId: 'fakeWalletId',
|
|
286
|
+
walletContractAddress: account_1.address,
|
|
287
|
+
};
|
|
288
|
+
const signedTx = await basecoin.signTransaction({
|
|
289
|
+
txPrebuild,
|
|
290
|
+
prv: account_1.owner_2,
|
|
291
|
+
});
|
|
292
|
+
should.exist(signedTx);
|
|
293
|
+
should.exist(signedTx.halfSigned);
|
|
294
|
+
signedTx.halfSigned.should.have.property('isBatch', true);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
describe('Transaction Verification', function () {
|
|
298
|
+
it('should verify a normal txPrebuild from the bitgo server that matches the client txParams', async function () {
|
|
299
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
300
|
+
const txParams = {
|
|
301
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
302
|
+
wallet: wallet,
|
|
303
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
304
|
+
};
|
|
305
|
+
const txPrebuild = {
|
|
306
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
307
|
+
nextContractSequenceId: 0,
|
|
308
|
+
gasPrice: 20000000000,
|
|
309
|
+
gasLimit: 500000,
|
|
310
|
+
isBatch: false,
|
|
311
|
+
coin: 'tpolygon',
|
|
312
|
+
walletId: 'fakeWalletId',
|
|
313
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
314
|
+
};
|
|
315
|
+
const verification = {};
|
|
316
|
+
const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet, verification });
|
|
317
|
+
isTransactionVerified.should.equal(true);
|
|
318
|
+
});
|
|
319
|
+
it('should verify a hop txPrebuild from the bitgo server that matches the client txParams', async function () {
|
|
320
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
321
|
+
const txParams = {
|
|
322
|
+
recipients: [{ amount: 1000000000000000, address: hopDestinationAddress }],
|
|
323
|
+
wallet: wallet,
|
|
324
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
325
|
+
hop: true,
|
|
326
|
+
};
|
|
327
|
+
const txPrebuild = {
|
|
328
|
+
recipients: [{ amount: '5000000000000000', address: hopContractAddress }],
|
|
329
|
+
nextContractSequenceId: 0,
|
|
330
|
+
gasPrice: 20000000000,
|
|
331
|
+
gasLimit: 500000,
|
|
332
|
+
isBatch: false,
|
|
333
|
+
coin: 'tpolygon',
|
|
334
|
+
walletId: 'fakeWalletId',
|
|
335
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
336
|
+
hopTransaction: {
|
|
337
|
+
tx: hopTx,
|
|
338
|
+
id: hopTxid,
|
|
339
|
+
signature: hopTxBitgoSignature,
|
|
340
|
+
paymentId: '2773928196',
|
|
341
|
+
gasPrice: 20000000000,
|
|
342
|
+
gasLimit: 500000,
|
|
343
|
+
amount: '1000000000000000',
|
|
344
|
+
recipient: hopDestinationAddress,
|
|
345
|
+
nonce: 0,
|
|
346
|
+
userReqSig: userReqSig,
|
|
347
|
+
gasPriceMax: 500000000000,
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
const verification = {};
|
|
351
|
+
const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, wallet, verification });
|
|
352
|
+
isTransactionVerified.should.equal(true);
|
|
353
|
+
});
|
|
354
|
+
it('should reject when client txParams are missing', async function () {
|
|
355
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
356
|
+
const txParams = null;
|
|
357
|
+
const txPrebuild = {
|
|
358
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
359
|
+
nextContractSequenceId: 0,
|
|
360
|
+
gasPrice: 20000000000,
|
|
361
|
+
gasLimit: 500000,
|
|
362
|
+
isBatch: false,
|
|
363
|
+
coin: 'tpolygon',
|
|
364
|
+
walletId: 'fakeWalletId',
|
|
365
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
366
|
+
};
|
|
367
|
+
const verification = {};
|
|
368
|
+
await basecoin
|
|
369
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
370
|
+
.should.be.rejectedWith('missing params');
|
|
371
|
+
});
|
|
372
|
+
it('should reject txPrebuild that is both batch and hop', async function () {
|
|
373
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
374
|
+
const txParams = {
|
|
375
|
+
recipients: [
|
|
376
|
+
{ amount: '1000000000000', address: address1 },
|
|
377
|
+
{ amount: '2500000000000', address: address2 },
|
|
378
|
+
],
|
|
379
|
+
wallet: wallet,
|
|
380
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
381
|
+
hop: true,
|
|
382
|
+
};
|
|
383
|
+
const txPrebuild = {
|
|
384
|
+
recipients: [{ amount: '3500000000000', address: address1 }],
|
|
385
|
+
nextContractSequenceId: 0,
|
|
386
|
+
gasPrice: 20000000000,
|
|
387
|
+
gasLimit: 500000,
|
|
388
|
+
isBatch: true,
|
|
389
|
+
coin: 'tpolygon',
|
|
390
|
+
walletId: 'fakeWalletId',
|
|
391
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
392
|
+
hopTransaction: {
|
|
393
|
+
tx: hopTx,
|
|
394
|
+
id: hopTxid,
|
|
395
|
+
signature: hopTxBitgoSignature,
|
|
396
|
+
paymentId: '2773928196',
|
|
397
|
+
gasPrice: 20000000000,
|
|
398
|
+
gasLimit: 500000,
|
|
399
|
+
amount: '1000000000000000',
|
|
400
|
+
recipient: hopDestinationAddress,
|
|
401
|
+
nonce: 0,
|
|
402
|
+
userReqSig: userReqSig,
|
|
403
|
+
gasPriceMax: 500000000000,
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
const verification = {};
|
|
407
|
+
await basecoin
|
|
408
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
409
|
+
.should.be.rejectedWith('tx cannot be both a batch and hop transaction');
|
|
410
|
+
});
|
|
411
|
+
it('should reject a txPrebuild with more than one recipient', async function () {
|
|
412
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
413
|
+
const txParams = {
|
|
414
|
+
recipients: [
|
|
415
|
+
{ amount: '1000000000000', address: address1 },
|
|
416
|
+
{ amount: '2500000000000', address: address2 },
|
|
417
|
+
],
|
|
418
|
+
wallet: wallet,
|
|
419
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
420
|
+
};
|
|
421
|
+
const txPrebuild = {
|
|
422
|
+
recipients: [
|
|
423
|
+
{ amount: '1000000000000', address: address1 },
|
|
424
|
+
{ amount: '2500000000000', address: address2 },
|
|
425
|
+
],
|
|
426
|
+
nextContractSequenceId: 0,
|
|
427
|
+
gasPrice: 20000000000,
|
|
428
|
+
gasLimit: 500000,
|
|
429
|
+
isBatch: true,
|
|
430
|
+
coin: 'tpolygon',
|
|
431
|
+
walletId: 'fakeWalletId',
|
|
432
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
433
|
+
};
|
|
434
|
+
const verification = {};
|
|
435
|
+
await basecoin
|
|
436
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
437
|
+
.should.be.rejectedWith(`tpolygon doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
|
|
438
|
+
});
|
|
439
|
+
it('should reject a hop txPrebuild that does not send to its hop address', async function () {
|
|
440
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
441
|
+
const txParams = {
|
|
442
|
+
recipients: [{ amount: '1000000000000000', address: hopDestinationAddress }],
|
|
443
|
+
wallet: wallet,
|
|
444
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
445
|
+
hop: true,
|
|
446
|
+
};
|
|
447
|
+
const txPrebuild = {
|
|
448
|
+
recipients: [{ amount: '5000000000000000', address: address1 }],
|
|
449
|
+
nextContractSequenceId: 0,
|
|
450
|
+
gasPrice: 20000000000,
|
|
451
|
+
gasLimit: 500000,
|
|
452
|
+
isBatch: false,
|
|
453
|
+
coin: 'tpolygon',
|
|
454
|
+
walletId: 'fakeWalletId',
|
|
455
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
456
|
+
hopTransaction: {
|
|
457
|
+
tx: hopTx,
|
|
458
|
+
id: hopTxid,
|
|
459
|
+
signature: hopTxBitgoSignature,
|
|
460
|
+
paymentId: '0',
|
|
461
|
+
gasPrice: 20000000000,
|
|
462
|
+
gasLimit: 500000,
|
|
463
|
+
amount: '1000000000000000',
|
|
464
|
+
recipient: hopDestinationAddress,
|
|
465
|
+
nonce: 0,
|
|
466
|
+
userReqSig: userReqSig,
|
|
467
|
+
gasPriceMax: 500000000000,
|
|
468
|
+
},
|
|
469
|
+
};
|
|
470
|
+
const verification = {};
|
|
471
|
+
await basecoin
|
|
472
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
473
|
+
.should.be.rejectedWith('recipient address of txPrebuild does not match hop address');
|
|
474
|
+
});
|
|
475
|
+
it('should reject a normal txPrebuild from the bitgo server with the wrong amount', async function () {
|
|
476
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
477
|
+
const txParams = {
|
|
478
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
479
|
+
wallet: wallet,
|
|
480
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
481
|
+
};
|
|
482
|
+
const txPrebuild = {
|
|
483
|
+
recipients: [{ amount: '2000000000000', address: address1 }],
|
|
484
|
+
nextContractSequenceId: 0,
|
|
485
|
+
gasPrice: 20000000000,
|
|
486
|
+
gasLimit: 500000,
|
|
487
|
+
isBatch: false,
|
|
488
|
+
coin: 'tpolygon',
|
|
489
|
+
walletId: 'fakeWalletId',
|
|
490
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
491
|
+
};
|
|
492
|
+
const verification = {};
|
|
493
|
+
await basecoin
|
|
494
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
495
|
+
.should.be.rejectedWith('normal transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client');
|
|
496
|
+
});
|
|
497
|
+
it('should reject a normal txPrebuild from the bitgo server with the wrong recipient', async function () {
|
|
498
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
499
|
+
const txParams = {
|
|
500
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
501
|
+
wallet: wallet,
|
|
502
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
503
|
+
};
|
|
504
|
+
const txPrebuild = {
|
|
505
|
+
recipients: [{ amount: '1000000000000', address: address2 }],
|
|
506
|
+
nextContractSequenceId: 0,
|
|
507
|
+
gasPrice: 20000000000,
|
|
508
|
+
gasLimit: 500000,
|
|
509
|
+
isBatch: false,
|
|
510
|
+
coin: 'tpolygon',
|
|
511
|
+
walletId: 'fakeWalletId',
|
|
512
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
513
|
+
};
|
|
514
|
+
const verification = {};
|
|
515
|
+
await basecoin
|
|
516
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
517
|
+
.should.be.rejectedWith('destination address in normal txPrebuild does not match that in txParams supplied by client');
|
|
518
|
+
});
|
|
519
|
+
it('should reject a txPrebuild from the bitgo server with the wrong coin', async function () {
|
|
520
|
+
const wallet = new sdk_core_1.Wallet(bitgo, basecoin, {});
|
|
521
|
+
const txParams = {
|
|
522
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
523
|
+
wallet: wallet,
|
|
524
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
525
|
+
};
|
|
526
|
+
const txPrebuild = {
|
|
527
|
+
recipients: [{ amount: '1000000000000', address: address1 }],
|
|
528
|
+
nextContractSequenceId: 0,
|
|
529
|
+
gasPrice: 20000000000,
|
|
530
|
+
gasLimit: 500000,
|
|
531
|
+
isBatch: false,
|
|
532
|
+
coin: 'btc',
|
|
533
|
+
walletId: 'fakeWalletId',
|
|
534
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
535
|
+
};
|
|
536
|
+
const verification = {};
|
|
537
|
+
await basecoin
|
|
538
|
+
.verifyTransaction({ txParams, txPrebuild, wallet, verification })
|
|
539
|
+
.should.be.rejectedWith('coin in txPrebuild did not match that in txParams supplied by client');
|
|
540
|
+
});
|
|
541
|
+
});
|
|
542
|
+
describe('Recover transaction:', function () {
|
|
543
|
+
const baseUrl = sdk_core_1.common.Environments.test.polygonscanBaseUrl;
|
|
544
|
+
const userXpub = 'xpub661MyMwAqRbcEeTc8789MK5PUGEYiPG4F4V17n2Rd2LoTATA1XoCnJT5FAYAShQxSxtFjpo5NHmcWwTp2LiWGBMwpUcAA3HywhxivgYfq7q';
|
|
545
|
+
const userXprv = 'xprv9s21ZrQH143K2AP925b8zB8evEQ4JvYCsqZQKPcp4gopaN81TzUxEW8bPtVyDgjmddGhRRETn8xi1cVAB9bf1Bx9kGRRFgTZXxJayZLnag1';
|
|
546
|
+
const backupXpub = 'xpub661MyMwAqRbcFZX15xpZf4ERCGHiVSJm8r5C4yh1yXV2GrdZCUPYo4WQr6tN9oUywKXsgSHo7Risf9r22GH5joVD2hEEEhqnSCvK8qy11wW';
|
|
547
|
+
const backupXprv = 'xprv9s21ZrQH143K35SXywHZHvHgeETE5yaumd9bGbHQRBx3Q4JQew5JFGBvzqiZjCUkBdBUZnfuMDTGURRayN1hFSWxEJQsCEAMm1D3pk1h7Jj';
|
|
548
|
+
it('should generate an unsigned sweep', async function () {
|
|
549
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
550
|
+
const backupKeyAddress = '0x4f2c4830cc37f2785c646f89ded8a919219fa0e9';
|
|
551
|
+
(0, nock_1.default)(baseUrl)
|
|
552
|
+
.get('/api')
|
|
553
|
+
.twice()
|
|
554
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
555
|
+
.reply(200, mockData.getTxListResponse);
|
|
556
|
+
(0, nock_1.default)(baseUrl)
|
|
557
|
+
.get('/api')
|
|
558
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
559
|
+
.reply(200, mockData.getBalanceResponse);
|
|
560
|
+
(0, nock_1.default)(baseUrl)
|
|
561
|
+
.get('/api')
|
|
562
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
563
|
+
.reply(200, mockData.getBalanceResponse);
|
|
564
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
565
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
566
|
+
const transaction = (await basecoin.recover({
|
|
567
|
+
userKey: userXpub,
|
|
568
|
+
backupKey: backupXpub,
|
|
569
|
+
walletContractAddress: walletContractAddress,
|
|
570
|
+
recoveryDestination: sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT,
|
|
571
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
572
|
+
gasLimit: 500000,
|
|
573
|
+
}));
|
|
574
|
+
should.exist(transaction);
|
|
575
|
+
transaction.should.have.property('txHex');
|
|
576
|
+
transaction.should.have.property('contractSequenceId');
|
|
577
|
+
transaction.should.have.property('expireTime');
|
|
578
|
+
transaction.should.have.property('gasLimit');
|
|
579
|
+
transaction.gasLimit.should.equal('500000');
|
|
580
|
+
transaction.should.have.property('walletContractAddress');
|
|
581
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
582
|
+
transaction.should.have.property('recipients');
|
|
583
|
+
const recipient = transaction.recipients[0];
|
|
584
|
+
recipient.should.have.property('address');
|
|
585
|
+
recipient.address.should.equal(sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT);
|
|
586
|
+
recipient.should.have.property('amount');
|
|
587
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
588
|
+
});
|
|
589
|
+
it('should construct a recovery transaction without BitGo', async function () {
|
|
590
|
+
const backupKeyAddress = '0x6d22efdd634996248170c948e5726007fc251bb3';
|
|
591
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
592
|
+
(0, nock_1.default)(baseUrl)
|
|
593
|
+
.get('/api')
|
|
594
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
595
|
+
.reply(200, mockData.getTxListResponse);
|
|
596
|
+
(0, nock_1.default)(baseUrl)
|
|
597
|
+
.get('/api')
|
|
598
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
599
|
+
.reply(200, mockData.getBalanceResponse);
|
|
600
|
+
(0, nock_1.default)(baseUrl)
|
|
601
|
+
.get('/api')
|
|
602
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
603
|
+
.reply(200, mockData.getBalanceResponse);
|
|
604
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
605
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
606
|
+
const transaction = (await basecoin.recover({
|
|
607
|
+
userKey: '{"iv":"VFZ3jvXhxo1Z+Yaf2MtZnA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
608
|
+
':"ccm","adata":"","cipher":"aes","salt":"p+fkHuLa/8k=","ct":"hYG7pvljLIgCjZ\n' +
|
|
609
|
+
'53PBlCde5KZRmlUKKHLtDMk+HJfuU46hW+x+C9WsIAO4gFPnTCvFVmQ8x7czCtcNFub5AO2otOG\n' +
|
|
610
|
+
'OsX4GE2gXOEmCl1TpWwwNhm7yMUjGJUpgW6ZZgXSXdDitSKi4V/hk78SGSzjFOBSPYRa6I="}\n',
|
|
611
|
+
backupKey: '{"iv":"AbsCtv1qwPIhOgyrCpNagA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
612
|
+
':"ccm","adata":"","cipher":"aes","salt":"5vpUDBUlzm8=","ct":"PapYYCjBXRLUKA\n' +
|
|
613
|
+
'JbOsB/EJ9B8fUmVQTxMPjUnQyAky12me9K66GiMEAxTD7kd6bYAQJuuTkATXKU7Bnf7vK9JxNOw\n' +
|
|
614
|
+
'oji7HF9eFH0aD4/hX5SWFfHF2Qfi+TnXv6hVsMAoisDZs3/F67/ZUaDYR0ZsdrQ4Q/cLD0="}\n',
|
|
615
|
+
walletContractAddress: walletContractAddress,
|
|
616
|
+
walletPassphrase: sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE,
|
|
617
|
+
recoveryDestination: sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT,
|
|
618
|
+
gasLimit: 500000,
|
|
619
|
+
}));
|
|
620
|
+
should.exist(transaction);
|
|
621
|
+
transaction.should.have.property('tx');
|
|
622
|
+
transaction.should.have.property('id');
|
|
623
|
+
const decodedTx = abstract_eth_1.optionalDeps.EthTx.Transaction.fromSerializedTx(abstract_eth_1.optionalDeps.ethUtil.toBuffer(transaction.tx));
|
|
624
|
+
decodedTx.should.have.property('gasPrice');
|
|
625
|
+
decodedTx.should.have.property('nonce');
|
|
626
|
+
decodedTx.should.have.property('to');
|
|
627
|
+
});
|
|
628
|
+
xit('should construct a recovery tx with TSS', async function () {
|
|
629
|
+
const backupKeyAddress = '0xe7406dc43d13f698fb41a345c7783d39a4c2d191';
|
|
630
|
+
(0, nock_1.default)(baseUrl)
|
|
631
|
+
.get('/api')
|
|
632
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
633
|
+
.reply(200, mockData.getTxListResponse);
|
|
634
|
+
(0, nock_1.default)(baseUrl)
|
|
635
|
+
.get('/api')
|
|
636
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
637
|
+
.reply(200, mockData.getBalanceResponse);
|
|
638
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
639
|
+
const userKey = mockData.keyShares.userKeyShare;
|
|
640
|
+
const backupKey = mockData.keyShares.backupKeyShare;
|
|
641
|
+
const bitgoKey = mockData.keyShares.bitgoKeyShare;
|
|
642
|
+
const userSigningMaterial = {
|
|
643
|
+
pShare: userKey.pShare,
|
|
644
|
+
backupNShare: backupKey.nShares[1],
|
|
645
|
+
bitgoNShare: bitgoKey.nShares[1],
|
|
646
|
+
};
|
|
647
|
+
const backupSigningMaterial = {
|
|
648
|
+
pShare: backupKey.pShare,
|
|
649
|
+
userNShare: userKey.nShares[2],
|
|
650
|
+
bitgoNShare: bitgoKey.nShares[2],
|
|
651
|
+
};
|
|
652
|
+
const encryptedBackupSigningMaterial = sjcl.encrypt(sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE, JSON.stringify(backupSigningMaterial));
|
|
653
|
+
const encryptedUserSigningMaterial = sjcl.encrypt(sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE, JSON.stringify(userSigningMaterial));
|
|
654
|
+
const recoveryParams = {
|
|
655
|
+
userKey: encryptedUserSigningMaterial,
|
|
656
|
+
backupKey: encryptedBackupSigningMaterial,
|
|
657
|
+
walletContractAddress: '0xe7406dc43d13f698fb41a345c7783d39a4c2d191',
|
|
658
|
+
recoveryDestination: '0xac05da78464520aa7c9d4c19bd7a440b111b3054',
|
|
659
|
+
walletPassphrase: sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE,
|
|
660
|
+
isTss: true,
|
|
661
|
+
};
|
|
662
|
+
const recovery = await basecoin.recover(recoveryParams);
|
|
663
|
+
// id and tx will always be different because of expireTime
|
|
664
|
+
should.exist(recovery);
|
|
665
|
+
recovery.should.have.property('id');
|
|
666
|
+
recovery.should.have.property('tx');
|
|
667
|
+
});
|
|
668
|
+
it('should be able to second sign', async function () {
|
|
669
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
670
|
+
const backupKeyAddress = '0x4f2c4830cc37f2785c646f89ded8a919219fa0e9';
|
|
671
|
+
(0, nock_1.default)(baseUrl)
|
|
672
|
+
.get('/api')
|
|
673
|
+
.twice()
|
|
674
|
+
.query(mockData.getTxListRequest(backupKeyAddress))
|
|
675
|
+
.reply(200, mockData.getTxListResponse);
|
|
676
|
+
(0, nock_1.default)(baseUrl)
|
|
677
|
+
.get('/api')
|
|
678
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
679
|
+
.reply(200, mockData.getBalanceResponse);
|
|
680
|
+
(0, nock_1.default)(baseUrl)
|
|
681
|
+
.get('/api')
|
|
682
|
+
.query(mockData.getBalanceRequest(backupKeyAddress))
|
|
683
|
+
.reply(200, mockData.getBalanceResponse);
|
|
684
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
685
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
686
|
+
const transaction = (await basecoin.recover({
|
|
687
|
+
userKey: userXpub,
|
|
688
|
+
backupKey: backupXpub,
|
|
689
|
+
walletContractAddress: walletContractAddress,
|
|
690
|
+
recoveryDestination: sdk_test_1.TestBitGo.V2.TEST_ERC20_TOKEN_RECIPIENT,
|
|
691
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
692
|
+
replayProtectionOptions: { chain: 80002, hardfork: 'london' },
|
|
693
|
+
gasLimit: 500000,
|
|
694
|
+
}));
|
|
695
|
+
const txPrebuild = {
|
|
696
|
+
txHex: transaction.txHex,
|
|
697
|
+
};
|
|
698
|
+
const params = {
|
|
699
|
+
txPrebuild,
|
|
700
|
+
prv: userXprv,
|
|
701
|
+
};
|
|
702
|
+
// sign transaction once
|
|
703
|
+
const halfSigned = await basecoin.signTransaction(params);
|
|
704
|
+
const halfSignedParams = {
|
|
705
|
+
txPrebuild: halfSigned,
|
|
706
|
+
isLastSignature: true,
|
|
707
|
+
walletContractAddress: walletContractAddress,
|
|
708
|
+
prv: backupXprv,
|
|
709
|
+
};
|
|
710
|
+
const finalSigned = (await basecoin.signTransaction(halfSignedParams));
|
|
711
|
+
finalSigned.should.have.property('txHex');
|
|
712
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
713
|
+
txBuilder.from(finalSigned.txHex);
|
|
714
|
+
const rebuiltTx = await txBuilder.build();
|
|
715
|
+
rebuiltTx.signature.length.should.equal(2);
|
|
716
|
+
rebuiltTx.outputs.length.should.equal(1);
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
describe('Evm Based Cross Chain Recovery transaction:', function () {
|
|
720
|
+
const baseUrl = sdk_core_1.common.Environments.test.polygonscanBaseUrl;
|
|
721
|
+
const userXpub = 'xpub661MyMwAqRbcEeTc8789MK5PUGEYiPG4F4V17n2Rd2LoTATA1XoCnJT5FAYAShQxSxtFjpo5NHmcWwTp2LiWGBMwpUcAA3HywhxivgYfq7q';
|
|
722
|
+
const bitgoFeeAddress = '0x33a42faea3c6e87021347e51700b48aaf49aa1e7';
|
|
723
|
+
const destinationAddress = '0xd5adde17fed8baed3f32b84af05b8f2816f7b560';
|
|
724
|
+
const bitgoDestinationAddress = '0xe5986ce4490deb67d2950562ceb930ddf9be7a14';
|
|
725
|
+
it('should generate an unsigned recovery txn for cold wallet', async function () {
|
|
726
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
727
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
728
|
+
(0, nock_1.default)(baseUrl)
|
|
729
|
+
.get('/api')
|
|
730
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
731
|
+
.reply(200, mockData.getTxListResponse);
|
|
732
|
+
(0, nock_1.default)(baseUrl)
|
|
733
|
+
.get('/api')
|
|
734
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
735
|
+
.reply(200, mockData.getBalanceResponse);
|
|
736
|
+
(0, nock_1.default)(baseUrl)
|
|
737
|
+
.get('/api')
|
|
738
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
739
|
+
.reply(200, mockData.getBalanceResponse);
|
|
740
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
741
|
+
const transaction = (await basecoin.recover({
|
|
742
|
+
userKey: userXpub,
|
|
743
|
+
backupKey: '',
|
|
744
|
+
walletContractAddress: walletContractAddress,
|
|
745
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
746
|
+
recoveryDestination: destinationAddress,
|
|
747
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
748
|
+
gasLimit: 500000,
|
|
749
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
750
|
+
}));
|
|
751
|
+
should.exist(transaction);
|
|
752
|
+
transaction.should.have.property('txHex');
|
|
753
|
+
transaction.should.have.property('userKey');
|
|
754
|
+
transaction.should.have.property('coin');
|
|
755
|
+
transaction.should.have.property('contractSequenceId');
|
|
756
|
+
transaction.should.have.property('expireTime');
|
|
757
|
+
transaction.should.have.property('gasLimit');
|
|
758
|
+
transaction.gasLimit.should.equal('500000');
|
|
759
|
+
transaction.should.have.property('isEvmBasedCrossChainRecovery');
|
|
760
|
+
transaction.isEvmBasedCrossChainRecovery?.should.equal(true);
|
|
761
|
+
transaction.should.have.property('walletContractAddress');
|
|
762
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
763
|
+
transaction.should.have.property('recipients');
|
|
764
|
+
const recipient = transaction.recipients[0];
|
|
765
|
+
recipient.should.have.property('address');
|
|
766
|
+
recipient.address.should.equal(destinationAddress);
|
|
767
|
+
recipient.should.have.property('amount');
|
|
768
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
769
|
+
});
|
|
770
|
+
it('should generate an unsigned recovery txn for custody wallet', async function () {
|
|
771
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
772
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
773
|
+
(0, nock_1.default)(baseUrl)
|
|
774
|
+
.get('/api')
|
|
775
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
776
|
+
.reply(200, mockData.getTxListResponse);
|
|
777
|
+
(0, nock_1.default)(baseUrl)
|
|
778
|
+
.get('/api')
|
|
779
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
780
|
+
.reply(200, mockData.getBalanceResponse);
|
|
781
|
+
(0, nock_1.default)(baseUrl)
|
|
782
|
+
.get('/api')
|
|
783
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
784
|
+
.reply(200, mockData.getBalanceResponse);
|
|
785
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
786
|
+
const transaction = (await basecoin.recover({
|
|
787
|
+
userKey: '',
|
|
788
|
+
backupKey: '',
|
|
789
|
+
walletContractAddress: walletContractAddress,
|
|
790
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
791
|
+
recoveryDestination: destinationAddress,
|
|
792
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
793
|
+
gasLimit: 500000,
|
|
794
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
795
|
+
}));
|
|
796
|
+
should.exist(transaction);
|
|
797
|
+
transaction.should.have.property('txHex');
|
|
798
|
+
transaction.should.have.property('coin');
|
|
799
|
+
transaction.should.have.property('contractSequenceId');
|
|
800
|
+
transaction.should.have.property('expireTime');
|
|
801
|
+
transaction.should.have.property('gasLimit');
|
|
802
|
+
transaction.gasLimit.should.equal('500000');
|
|
803
|
+
transaction.should.have.property('isEvmBasedCrossChainRecovery');
|
|
804
|
+
transaction.isEvmBasedCrossChainRecovery?.should.equal(true);
|
|
805
|
+
transaction.should.have.property('walletContractAddress');
|
|
806
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
807
|
+
transaction.should.have.property('recipients');
|
|
808
|
+
const recipient = transaction.recipients[0];
|
|
809
|
+
recipient.should.have.property('address');
|
|
810
|
+
recipient.address.should.equal(destinationAddress);
|
|
811
|
+
recipient.should.have.property('amount');
|
|
812
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
813
|
+
});
|
|
814
|
+
it('should generate an unsigned recovery txn for hot wallet', async function () {
|
|
815
|
+
const userKey = '{"iv":"VFZ3jvXhxo1Z+Yaf2MtZnA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
816
|
+
':"ccm","adata":"","cipher":"aes","salt":"p+fkHuLa/8k=","ct":"hYG7pvljLIgCjZ\n' +
|
|
817
|
+
'53PBlCde5KZRmlUKKHLtDMk+HJfuU46hW+x+C9WsIAO4gFPnTCvFVmQ8x7czCtcNFub5AO2otOG\n' +
|
|
818
|
+
'OsX4GE2gXOEmCl1TpWwwNhm7yMUjGJUpgW6ZZgXSXdDitSKi4V/hk78SGSzjFOBSPYRa6I="}\n';
|
|
819
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
820
|
+
const walletPassphrase = sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE;
|
|
821
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
822
|
+
(0, nock_1.default)(baseUrl)
|
|
823
|
+
.get('/api')
|
|
824
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
825
|
+
.reply(200, mockData.getTxListResponse);
|
|
826
|
+
(0, nock_1.default)(baseUrl)
|
|
827
|
+
.get('/api')
|
|
828
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
829
|
+
.reply(200, mockData.getBalanceResponse);
|
|
830
|
+
(0, nock_1.default)(baseUrl)
|
|
831
|
+
.get('/api')
|
|
832
|
+
.query(mockData.getBalanceRequest(walletContractAddress))
|
|
833
|
+
.reply(200, mockData.getBalanceResponse);
|
|
834
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
835
|
+
const transaction = (await basecoin.recover({
|
|
836
|
+
userKey: userKey,
|
|
837
|
+
backupKey: '',
|
|
838
|
+
walletPassphrase: walletPassphrase,
|
|
839
|
+
walletContractAddress: walletContractAddress,
|
|
840
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
841
|
+
recoveryDestination: destinationAddress,
|
|
842
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
843
|
+
gasLimit: 500000,
|
|
844
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
845
|
+
}));
|
|
846
|
+
should.exist(transaction);
|
|
847
|
+
transaction.should.have.property('txHex');
|
|
848
|
+
transaction.should.have.property('coin');
|
|
849
|
+
transaction.should.have.property('contractSequenceId');
|
|
850
|
+
transaction.should.have.property('expireTime');
|
|
851
|
+
transaction.should.have.property('gasLimit');
|
|
852
|
+
transaction.gasLimit.should.equal('500000');
|
|
853
|
+
transaction.should.have.property('isEvmBasedCrossChainRecovery');
|
|
854
|
+
transaction.isEvmBasedCrossChainRecovery?.should.equal(true);
|
|
855
|
+
transaction.should.have.property('walletContractAddress');
|
|
856
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
857
|
+
transaction.should.have.property('recipients');
|
|
858
|
+
const recipient = transaction.recipients[0];
|
|
859
|
+
recipient.should.have.property('address');
|
|
860
|
+
recipient.address.should.equal(destinationAddress);
|
|
861
|
+
recipient.should.have.property('amount');
|
|
862
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
863
|
+
transaction.should.have.property('feesUsed');
|
|
864
|
+
transaction.feesUsed?.gasLimit.should.equal('500000');
|
|
865
|
+
transaction.should.have.property('halfSigned');
|
|
866
|
+
transaction.halfSigned?.should.have.property('txHex');
|
|
867
|
+
transaction.halfSigned?.should.have.property('recipients');
|
|
868
|
+
});
|
|
869
|
+
it('should generate an unsigned recovery txn of a token for cold wallet ', async function () {
|
|
870
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
871
|
+
const tokenContractAddress = '0x326c977e6efc84e512bb9c30f76e30c160ed06fb'; // tpolygon-link contract token address
|
|
872
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
873
|
+
(0, nock_1.default)(baseUrl)
|
|
874
|
+
.get('/api')
|
|
875
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
876
|
+
.reply(200, mockData.getTxListResponse);
|
|
877
|
+
(0, nock_1.default)(baseUrl)
|
|
878
|
+
.get('/api')
|
|
879
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
880
|
+
.reply(200, mockData.getBalanceResponse);
|
|
881
|
+
(0, nock_1.default)(baseUrl)
|
|
882
|
+
.get('/api')
|
|
883
|
+
.query(mockData.getTokenBalanceRequest(tokenContractAddress, walletContractAddress))
|
|
884
|
+
.reply(200, mockData.getBalanceResponse);
|
|
885
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
886
|
+
const transaction = (await basecoin.recover({
|
|
887
|
+
userKey: userXpub,
|
|
888
|
+
backupKey: '',
|
|
889
|
+
walletContractAddress: walletContractAddress,
|
|
890
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
891
|
+
recoveryDestination: destinationAddress,
|
|
892
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
893
|
+
gasLimit: 500000,
|
|
894
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
895
|
+
tokenContractAddress: tokenContractAddress,
|
|
896
|
+
}));
|
|
897
|
+
should.exist(transaction);
|
|
898
|
+
transaction.should.have.property('txHex');
|
|
899
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
900
|
+
txBuilder.from(transaction.txHex);
|
|
901
|
+
const rebuiltTx = await txBuilder.build();
|
|
902
|
+
const rebuiltTxJson = rebuiltTx.toJson();
|
|
903
|
+
rebuiltTxJson.should.have.property('data');
|
|
904
|
+
rebuiltTxJson.data.should.startWith('0x0dcd7a6c'); // sendMultiSigToken func
|
|
905
|
+
transaction.should.have.property('userKey');
|
|
906
|
+
transaction.should.have.property('coin');
|
|
907
|
+
transaction.coin.should.equal('tpolygon:link');
|
|
908
|
+
transaction.should.have.property('contractSequenceId');
|
|
909
|
+
transaction.should.have.property('expireTime');
|
|
910
|
+
transaction.should.have.property('gasLimit');
|
|
911
|
+
transaction.gasLimit.should.equal('500000');
|
|
912
|
+
transaction.should.have.property('isEvmBasedCrossChainRecovery');
|
|
913
|
+
transaction.isEvmBasedCrossChainRecovery?.should.equal(true);
|
|
914
|
+
transaction.should.have.property('walletContractAddress');
|
|
915
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
916
|
+
transaction.should.have.property('recipients');
|
|
917
|
+
const recipient = transaction.recipients[0];
|
|
918
|
+
recipient.should.have.property('address');
|
|
919
|
+
recipient.address.should.equal(destinationAddress);
|
|
920
|
+
recipient.should.have.property('amount');
|
|
921
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
922
|
+
});
|
|
923
|
+
it('should generate an unsigned recovery txn of a token for custody wallet', async function () {
|
|
924
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
925
|
+
const tokenContractAddress = '0x326c977e6efc84e512bb9c30f76e30c160ed06fb'; // tpolygon-link contract token address
|
|
926
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
927
|
+
(0, nock_1.default)(baseUrl)
|
|
928
|
+
.get('/api')
|
|
929
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
930
|
+
.reply(200, mockData.getTxListResponse);
|
|
931
|
+
(0, nock_1.default)(baseUrl)
|
|
932
|
+
.get('/api')
|
|
933
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
934
|
+
.reply(200, mockData.getBalanceResponse);
|
|
935
|
+
(0, nock_1.default)(baseUrl)
|
|
936
|
+
.get('/api')
|
|
937
|
+
.query(mockData.getTokenBalanceRequest(tokenContractAddress, walletContractAddress))
|
|
938
|
+
.reply(200, mockData.getBalanceResponse);
|
|
939
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
940
|
+
const transaction = (await basecoin.recover({
|
|
941
|
+
userKey: '',
|
|
942
|
+
backupKey: '',
|
|
943
|
+
walletContractAddress: walletContractAddress,
|
|
944
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
945
|
+
recoveryDestination: destinationAddress,
|
|
946
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
947
|
+
gasLimit: 500000,
|
|
948
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
949
|
+
tokenContractAddress: tokenContractAddress,
|
|
950
|
+
}));
|
|
951
|
+
should.exist(transaction);
|
|
952
|
+
transaction.should.have.property('txHex');
|
|
953
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
954
|
+
txBuilder.from(transaction.txHex);
|
|
955
|
+
const rebuiltTx = await txBuilder.build();
|
|
956
|
+
const rebuiltTxJson = rebuiltTx.toJson();
|
|
957
|
+
rebuiltTxJson.should.have.property('data');
|
|
958
|
+
rebuiltTxJson.data.should.startWith('0x0dcd7a6c'); // sendMultiSigToken func
|
|
959
|
+
transaction.should.have.property('coin');
|
|
960
|
+
transaction.coin.should.equal('tpolygon:link');
|
|
961
|
+
transaction.should.have.property('contractSequenceId');
|
|
962
|
+
transaction.should.have.property('expireTime');
|
|
963
|
+
transaction.should.have.property('gasLimit');
|
|
964
|
+
transaction.gasLimit.should.equal('500000');
|
|
965
|
+
transaction.should.have.property('isEvmBasedCrossChainRecovery');
|
|
966
|
+
transaction.isEvmBasedCrossChainRecovery?.should.equal(true);
|
|
967
|
+
transaction.should.have.property('walletContractAddress');
|
|
968
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
969
|
+
transaction.should.have.property('recipients');
|
|
970
|
+
const recipient = transaction.recipients[0];
|
|
971
|
+
recipient.should.have.property('address');
|
|
972
|
+
recipient.address.should.equal(destinationAddress);
|
|
973
|
+
recipient.should.have.property('amount');
|
|
974
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
975
|
+
});
|
|
976
|
+
it('should generate an unsigned recovery txn of a token for hot wallet', async function () {
|
|
977
|
+
const userKey = '{"iv":"VFZ3jvXhxo1Z+Yaf2MtZnA==","v":1,"iter":10000,"ks":256,"ts":64,"mode"\n' +
|
|
978
|
+
':"ccm","adata":"","cipher":"aes","salt":"p+fkHuLa/8k=","ct":"hYG7pvljLIgCjZ\n' +
|
|
979
|
+
'53PBlCde5KZRmlUKKHLtDMk+HJfuU46hW+x+C9WsIAO4gFPnTCvFVmQ8x7czCtcNFub5AO2otOG\n' +
|
|
980
|
+
'OsX4GE2gXOEmCl1TpWwwNhm7yMUjGJUpgW6ZZgXSXdDitSKi4V/hk78SGSzjFOBSPYRa6I="}\n';
|
|
981
|
+
const walletContractAddress = sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS;
|
|
982
|
+
const walletPassphrase = sdk_test_1.TestBitGo.V2.TEST_RECOVERY_PASSCODE;
|
|
983
|
+
const tokenContractAddress = '0x326c977e6efc84e512bb9c30f76e30c160ed06fb'; // tpolygon-link contract token address
|
|
984
|
+
const basecoin = bitgo.coin('tpolygon');
|
|
985
|
+
(0, nock_1.default)(baseUrl)
|
|
986
|
+
.get('/api')
|
|
987
|
+
.query(mockData.getTxListRequest(bitgoFeeAddress))
|
|
988
|
+
.reply(200, mockData.getTxListResponse);
|
|
989
|
+
(0, nock_1.default)(baseUrl)
|
|
990
|
+
.get('/api')
|
|
991
|
+
.query(mockData.getBalanceRequest(bitgoFeeAddress))
|
|
992
|
+
.reply(200, mockData.getBalanceResponse);
|
|
993
|
+
(0, nock_1.default)(baseUrl)
|
|
994
|
+
.get('/api')
|
|
995
|
+
.query(mockData.getTokenBalanceRequest(tokenContractAddress, walletContractAddress))
|
|
996
|
+
.reply(200, mockData.getBalanceResponse);
|
|
997
|
+
(0, nock_1.default)(baseUrl).get('/api').query(mockData.getContractCallRequest).reply(200, mockData.getContractCallResponse);
|
|
998
|
+
const transaction = (await basecoin.recover({
|
|
999
|
+
userKey: userKey,
|
|
1000
|
+
backupKey: '',
|
|
1001
|
+
walletPassphrase: walletPassphrase,
|
|
1002
|
+
walletContractAddress: walletContractAddress,
|
|
1003
|
+
bitgoFeeAddress: bitgoFeeAddress,
|
|
1004
|
+
recoveryDestination: destinationAddress,
|
|
1005
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
1006
|
+
gasLimit: 500000,
|
|
1007
|
+
bitgoDestinationAddress: bitgoDestinationAddress,
|
|
1008
|
+
tokenContractAddress: tokenContractAddress,
|
|
1009
|
+
}));
|
|
1010
|
+
should.exist(transaction);
|
|
1011
|
+
transaction.should.have.property('txHex');
|
|
1012
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('tpolygon');
|
|
1013
|
+
txBuilder.from(transaction.txHex);
|
|
1014
|
+
const rebuiltTx = await txBuilder.build();
|
|
1015
|
+
const rebuiltTxJson = rebuiltTx.toJson();
|
|
1016
|
+
rebuiltTxJson.should.have.property('data');
|
|
1017
|
+
rebuiltTxJson.data.should.startWith('0x0dcd7a6c'); // sendMultiSigToken func
|
|
1018
|
+
transaction.should.have.property('coin');
|
|
1019
|
+
transaction.coin.should.equal('tpolygon:link');
|
|
1020
|
+
transaction.should.have.property('contractSequenceId');
|
|
1021
|
+
transaction.should.have.property('expireTime');
|
|
1022
|
+
transaction.should.have.property('gasLimit');
|
|
1023
|
+
transaction.gasLimit.should.equal('500000');
|
|
1024
|
+
transaction.should.have.property('isEvmBasedCrossChainRecovery');
|
|
1025
|
+
transaction.isEvmBasedCrossChainRecovery?.should.equal(true);
|
|
1026
|
+
transaction.should.have.property('walletContractAddress');
|
|
1027
|
+
transaction.walletContractAddress.should.equal(sdk_test_1.TestBitGo.V2.TEST_ETH_WALLET_FIRST_ADDRESS);
|
|
1028
|
+
transaction.should.have.property('recipients');
|
|
1029
|
+
const recipient = transaction.recipients[0];
|
|
1030
|
+
recipient.should.have.property('address');
|
|
1031
|
+
recipient.address.should.equal(destinationAddress);
|
|
1032
|
+
recipient.should.have.property('amount');
|
|
1033
|
+
recipient.amount.should.equal('9999999999999999928');
|
|
1034
|
+
transaction.should.have.property('feesUsed');
|
|
1035
|
+
transaction.feesUsed?.gasLimit.should.equal('500000');
|
|
1036
|
+
transaction.should.have.property('halfSigned');
|
|
1037
|
+
transaction.halfSigned?.should.have.property('txHex');
|
|
1038
|
+
transaction.halfSigned?.should.have.property('recipients');
|
|
1039
|
+
});
|
|
1040
|
+
});
|
|
1041
|
+
describe('Non-BitGo Recovery for Hot Wallets (MPCv2)', function () {
|
|
1042
|
+
const baseUrl = sdk_core_1.common.Environments.test.polygonscanBaseUrl;
|
|
1043
|
+
it('should build a recovery transaction for MPCv2 kind of hot wallets', async function () {
|
|
1044
|
+
(0, nock_1.default)(baseUrl)
|
|
1045
|
+
.get('/api')
|
|
1046
|
+
.query(mockData.getTxListRequest(mockData.getNonBitGoRecoveryForHotWalletsMPCv2().bitgoFeeAddress))
|
|
1047
|
+
.reply(200, mockData.getTxListResponse);
|
|
1048
|
+
(0, nock_1.default)(baseUrl)
|
|
1049
|
+
.get('/api')
|
|
1050
|
+
.query(mockData.getBalanceRequest(mockData.getNonBitGoRecoveryForHotWalletsMPCv2().bitgoFeeAddress))
|
|
1051
|
+
.reply(200, mockData.getBalanceResponse);
|
|
1052
|
+
(0, nock_1.default)(baseUrl)
|
|
1053
|
+
.get('/api')
|
|
1054
|
+
.query(mockData.getBalanceRequest(mockData.getNonBitGoRecoveryForHotWalletsMPCv2().walletContractAddress))
|
|
1055
|
+
.reply(200, mockData.getBalanceResponse);
|
|
1056
|
+
const params = mockData.getNonBitGoRecoveryForHotWalletsMPCv2();
|
|
1057
|
+
const transaction = await basecoin.recover({
|
|
1058
|
+
userKey: params.userKey,
|
|
1059
|
+
backupKey: params.backupKey,
|
|
1060
|
+
walletPassphrase: params.walletPassphrase,
|
|
1061
|
+
walletContractAddress: params.walletContractAddress,
|
|
1062
|
+
bitgoFeeAddress: params.bitgoFeeAddress,
|
|
1063
|
+
recoveryDestination: params.recoveryDestination,
|
|
1064
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
1065
|
+
gasLimit: 500000,
|
|
1066
|
+
isTss: true,
|
|
1067
|
+
bitgoDestinationAddress: params.bitgoDestinationAddress,
|
|
1068
|
+
replayProtectionOptions: { chain: 80002, hardfork: 'london' },
|
|
1069
|
+
intendedChain: params.intendedChain,
|
|
1070
|
+
});
|
|
1071
|
+
should.exist(transaction);
|
|
1072
|
+
transaction.should.have.property('tx');
|
|
1073
|
+
});
|
|
1074
|
+
it('should throw an error for invalid user key', async function () {
|
|
1075
|
+
const params = mockData.getInvalidNonBitGoRecoveryParams();
|
|
1076
|
+
await assert_1.default.rejects(async () => {
|
|
1077
|
+
await basecoin.recover({
|
|
1078
|
+
userKey: params.userKey,
|
|
1079
|
+
backupKey: params.backupKey,
|
|
1080
|
+
walletPassphrase: params.walletPassphrase,
|
|
1081
|
+
walletContractAddress: params.walletContractAddress,
|
|
1082
|
+
bitgoFeeAddress: params.bitgoFeeAddress,
|
|
1083
|
+
recoveryDestination: params.recoveryDestination,
|
|
1084
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
1085
|
+
gasLimit: 500000,
|
|
1086
|
+
bitgoDestinationAddress: params.bitgoDestinationAddress,
|
|
1087
|
+
intendedChain: params.intendedChain,
|
|
1088
|
+
});
|
|
1089
|
+
}, Error, 'user key is invalid');
|
|
1090
|
+
});
|
|
1091
|
+
});
|
|
1092
|
+
describe('Build Unsigned Sweep for Self-Custody Cold Wallets (MPCv2)', function () {
|
|
1093
|
+
const baseUrl = sdk_core_1.common.Environments.test.polygonscanBaseUrl;
|
|
1094
|
+
it('should generate an unsigned sweep without derivation seed', async function () {
|
|
1095
|
+
(0, nock_1.default)(baseUrl)
|
|
1096
|
+
.get('/api')
|
|
1097
|
+
.query(mockData.getTxListRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
1098
|
+
.reply(200, mockData.getTxListResponse);
|
|
1099
|
+
(0, nock_1.default)(baseUrl)
|
|
1100
|
+
.get('/api')
|
|
1101
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().address))
|
|
1102
|
+
.reply(200, mockData.getBalanceResponse);
|
|
1103
|
+
(0, nock_1.default)(baseUrl)
|
|
1104
|
+
.get('/api')
|
|
1105
|
+
.query(mockData.getBalanceRequest(mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2().walletContractAddress))
|
|
1106
|
+
.reply(200, mockData.getBalanceResponse);
|
|
1107
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
1108
|
+
const sweepResult = await basecoin.recover({
|
|
1109
|
+
userKey: params.commonKeyChain,
|
|
1110
|
+
backupKey: params.commonKeyChain,
|
|
1111
|
+
recoveryDestination: params.recoveryDestination,
|
|
1112
|
+
gasLimit: 200000,
|
|
1113
|
+
eip1559: { maxFeePerGas: 20000000000, maxPriorityFeePerGas: 10000000000 },
|
|
1114
|
+
walletContractAddress: params.walletContractAddress,
|
|
1115
|
+
isTss: true,
|
|
1116
|
+
replayProtectionOptions: {
|
|
1117
|
+
chain: '137',
|
|
1118
|
+
hardfork: 'london',
|
|
1119
|
+
},
|
|
1120
|
+
});
|
|
1121
|
+
should.exist(sweepResult);
|
|
1122
|
+
const output = sweepResult;
|
|
1123
|
+
output.should.have.property('txRequests');
|
|
1124
|
+
output.txRequests.should.have.length(1);
|
|
1125
|
+
output.txRequests[0].should.have.property('transactions');
|
|
1126
|
+
output.txRequests[0].transactions.should.have.length(1);
|
|
1127
|
+
output.txRequests[0].should.have.property('walletCoin');
|
|
1128
|
+
output.txRequests[0].transactions[0].should.have.property('unsignedTx');
|
|
1129
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('serializedTxHex');
|
|
1130
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('signableHex');
|
|
1131
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('derivationPath');
|
|
1132
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('feeInfo');
|
|
1133
|
+
output.txRequests[0].transactions[0].unsignedTx.should.have.property('parsedTx');
|
|
1134
|
+
const parsedTx = output.txRequests[0].transactions[0].unsignedTx.parsedTx;
|
|
1135
|
+
parsedTx.should.have.property('spendAmount');
|
|
1136
|
+
output.txRequests[0].transactions[0].unsignedTx.parsedTx.should.have.property('outputs');
|
|
1137
|
+
});
|
|
1138
|
+
it('should throw an error for invalid address', async function () {
|
|
1139
|
+
const params = mockData.getBuildUnsignedSweepForSelfCustodyColdWalletsMPCv2();
|
|
1140
|
+
params.recoveryDestination = 'invalidAddress';
|
|
1141
|
+
params.userKey =
|
|
1142
|
+
'0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
|
|
1143
|
+
params.backupKey =
|
|
1144
|
+
'0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
|
|
1145
|
+
await assert_1.default.rejects(async () => {
|
|
1146
|
+
await basecoin.recover({
|
|
1147
|
+
recoveryDestination: params.recoveryDestination,
|
|
1148
|
+
gasLimit: 2000,
|
|
1149
|
+
eip1559: { maxFeePerGas: 200, maxPriorityFeePerGas: 10000 },
|
|
1150
|
+
userKey: params.userKey,
|
|
1151
|
+
backupKey: params.backupKey,
|
|
1152
|
+
walletContractAddress: params.walletContractAddress,
|
|
1153
|
+
isTss: true,
|
|
1154
|
+
replayProtectionOptions: {
|
|
1155
|
+
chain: '137',
|
|
1156
|
+
hardfork: 'london',
|
|
1157
|
+
},
|
|
1158
|
+
});
|
|
1159
|
+
}, Error, 'Error: invalid address');
|
|
1160
|
+
});
|
|
1161
|
+
});
|
|
1162
|
+
describe('Test isWalletAddress', function () {
|
|
1163
|
+
it('verify address for tpolygon', async function () {
|
|
1164
|
+
const keychains = [
|
|
1165
|
+
{
|
|
1166
|
+
id: '6920c05e0b195abd8ed0bb0a5df32cdc',
|
|
1167
|
+
source: 'user',
|
|
1168
|
+
type: 'tss',
|
|
1169
|
+
commonKeychain: '02f929f92c25eaccb0e3ebaa0f5ed900c5ad30ba94f8444dc89c94e12f01aa5371522d810b8918ecc9e41eb901352df1c7977420fbaf9b8617f61b780b32b2ccad',
|
|
1170
|
+
},
|
|
1171
|
+
{
|
|
1172
|
+
id: '6920c05e93c3b1c9e5006bf00a3cf016',
|
|
1173
|
+
source: 'backup',
|
|
1174
|
+
type: 'tss',
|
|
1175
|
+
commonKeychain: '02f929f92c25eaccb0e3ebaa0f5ed900c5ad30ba94f8444dc89c94e12f01aa5371522d810b8918ecc9e41eb901352df1c7977420fbaf9b8617f61b780b32b2ccad',
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
id: '6920c05d9ebee0100ec4a8aa7e300c02',
|
|
1179
|
+
source: 'bitgo',
|
|
1180
|
+
type: 'tss',
|
|
1181
|
+
commonKeychain: '02f929f92c25eaccb0e3ebaa0f5ed900c5ad30ba94f8444dc89c94e12f01aa5371522d810b8918ecc9e41eb901352df1c7977420fbaf9b8617f61b780b32b2ccad',
|
|
1182
|
+
},
|
|
1183
|
+
];
|
|
1184
|
+
const params = {
|
|
1185
|
+
address: '0x4e9fc44697f4135455157396485f6fe8f909752f',
|
|
1186
|
+
baseAddress: '0x8cf5ebd51585d159c4a1ca36178f9ad0fd7a594c',
|
|
1187
|
+
coinSpecific: {
|
|
1188
|
+
salt: '0xd',
|
|
1189
|
+
forwarderVersion: 4,
|
|
1190
|
+
feeAddress: '0x44dcb3504e323a3d70142036a99e2d4bba3f2270',
|
|
1191
|
+
},
|
|
1192
|
+
keychains,
|
|
1193
|
+
index: 13,
|
|
1194
|
+
walletVersion: 5,
|
|
1195
|
+
};
|
|
1196
|
+
const coin = bitgo.coin('tpolygon');
|
|
1197
|
+
const isWalletAddr = await coin.isWalletAddress(params);
|
|
1198
|
+
isWalletAddr.should.equal(true);
|
|
1199
|
+
});
|
|
1200
|
+
});
|
|
1201
|
+
});
|
|
1202
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9seWdvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9wb2x5Z29uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsZ0VBQXFDO0FBQ3JDLGlEQUErQztBQUMvQyxtREFBNEg7QUFDNUgsbURBQStEO0FBQy9ELHFEQUE4QztBQUM5QyxnREFBd0I7QUFDeEIscURBQXVDO0FBQ3ZDLCtDQUFpQztBQUNqQyxtQ0FBbUY7QUFDbkYsMkRBQTJIO0FBQzNILDhDQUEyQztBQUMzQyw4REFBZ0Q7QUFDaEQsdURBQXlDO0FBQ3pDLG9EQUE0QjtBQUU1QixjQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztBQUV4QixRQUFRLENBQUMsU0FBUyxFQUFFO0lBQ2xCLElBQUksS0FBbUIsQ0FBQztJQUN4QixJQUFJLFFBQVEsQ0FBQztJQUNiLElBQUksbUJBQW1CLENBQUM7SUFFeEIsTUFBTSxRQUFRLEdBQUcsNENBQTRDLENBQUM7SUFDOUQsTUFBTSxRQUFRLEdBQUcsNENBQTRDLENBQUM7SUFDOUQsTUFBTSxrQkFBa0IsR0FBRyw0Q0FBNEMsQ0FBQztJQUN4RSxNQUFNLHFCQUFxQixHQUFHLDRDQUE0QyxDQUFDO0lBQzNFLE1BQU0sS0FBSyxHQUNULDhOQUE4TixDQUFDO0lBQ2pPLE1BQU0sT0FBTyxHQUFHLG9FQUFvRSxDQUFDO0lBQ3JGLE1BQU0sVUFBVSxHQUNkLG9JQUFvSSxDQUFDO0lBRXZJLE1BQU0sQ0FBQztRQUNMLE1BQU0sWUFBWSxHQUNoQixpSEFBaUgsQ0FBQztRQUNwSCxNQUFNLFFBQVEsR0FBRyxpQkFBSyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDbkMsQ0FBQztRQUNELE1B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QkFBNkIsRUFBRSxLQUFLO1lBQ3JDLE1BQU0sU0FBUyxHQUFHO2dCQUNoQjtvQkFDRSxFQUFFLEVBQUUsa0NBQWtDO29CQUN0QyxNQUFNLEVBQUUsTUFBTTtvQkFDZCxJQUFJLEVBQUUsS0FBSztvQkFDWCxjQUFjLEVBQ1osb0lBQW9JO2lCQUN2STtnQkFDRDtvQkFDRSxFQUFFLEVBQUUsa0NBQWtDO29CQUN0QyxNQUFNLEVBQUUsUUFBUTtvQkFDaEIsSUFBSSxFQUFFLEtBQUs7b0JBQ1gsY0FBYyxFQUNaLG9JQUFvSTtpQkFDdkk7Z0JBQ0Q7b0JBQ0UsRUFBRSxFQUFFLGtDQUFrQztvQkFDdEMsTUFBTSxFQUFFLE9BQU87b0JBQ2YsSUFBSSxFQUFFLEtBQUs7b0JBQ1gsY0FBYyxFQUNaLG9JQUFvSTtpQkFDdkk7YUFDRixDQUFDO1lBRUYsTUFBTSxNQUFNLEdBQUc7Z0JBQ2IsT0FBTyxFQUFFLDRDQUE0QztnQkFDckQsV0FBVyxFQUFFLDRDQUE0QztnQkFDekQsWUFBWSxFQUFFO29CQUNaLElBQUksRUFBRSxLQUFLO29CQUNYLGdCQUFnQixFQUFFLENBQUM7b0JBQ25CLFVBQVUsRUFBRSw0Q0FBNEM7aUJBQ3pEO2dCQUNELFNBQVM7Z0JBQ1QsS0FBSyxFQUFFLEVBQUU7Z0JBQ1QsYUFBYSxFQUFFLENBQUM7YUFDakIsQ0FBQztZQUVGLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3hELFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWFwaSc7XG5pbXBvcnQgeyBjb21tb24sIEVDRFNBTWV0aG9kVHlwZXMsIEZ1bGx5U2lnbmVkVHJhbnNhY3Rpb24sIFJlY2lwaWVudCwgVHJhbnNhY3Rpb25UeXBlLCBXYWxsZXQgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvLWJldGEvc2VjcDI1NmsxJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0ICogYXMgc2VjcDI1NmsxIGZyb20gJ3NlY3AyNTZrMSc7XG5pbXBvcnQgKiBhcyBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCB7IFBvbHlnb24sIFRwb2x5Z29uLCBUcmFuc2FjdGlvbkJ1aWxkZXIsIFRyYW5zZmVyQnVpbGRlciB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBBYnN0cmFjdEV0aExpa2VOZXdDb2lucywgVW5zaWduZWRTd2VlcFR4TVBDdjIsIE9mZmxpbmVWYXVsdFR4SW5mbywgb3B0aW9uYWxEZXBzIH0gZnJvbSAnQGJpdGdvLWJldGEvYWJzdHJhY3QtZXRoJztcbmltcG9ydCB7IGdldEJ1aWxkZXIgfSBmcm9tICcuLi9nZXRCdWlsZGVyJztcbmltcG9ydCAqIGFzIG1vY2tEYXRhIGZyb20gJy4uL2ZpeHR1cmVzL3BvbHlnb24nO1xuaW1wb3J0ICogYXMgc2pjbCBmcm9tICdAYml0Z28tYmV0YS9zamNsJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0Jztcblxubm9jay5lbmFibGVOZXRDb25uZWN0KCk7XG5cbmRlc2NyaWJlKCdQb2x5Z29uJywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGJhc2Vjb2luO1xuICBsZXQgaG9wVHhCaXRnb1NpZ25hdHVyZTtcblxuICBjb25zdCBhZGRyZXNzMSA9ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnO1xuICBjb25zdCBhZGRyZXNzMiA9ICcweDdlODViZGMyN2MwNTBlMzkwNWViZjRiOGU2MzRkOWFkNmVkZDBkZTYnO1xuICBjb25zdCBob3BDb250cmFjdEFkZHJlc3MgPSAnMHg0N2NlN2NjODZlZmVmZWYxOWY4ZmI1MTZiMTE3MzVkMTgzZGE4NjM1JztcbiAgY29uc3QgaG9wRGVzdGluYXRpb25BZGRyZXNzID0gJzB4OWM3ZThjZTY4MjViRDQ4Mjc4QjNBYjU5MjI4RUUyNmY4QkU3OTI1Yic7XG4gIGNvbnN0IGhvcFR4ID1cbiAgICAnMHhmODZiODA4NTA0YTgxN2M4ZmY4MjUyZmY5NDljN2U4Y2U2ODI1YmQ0ODI3OGIzYWI1OTIyOGVlMjZmOGJlNzkyNWI4NzAzOGQ3ZWE0YzY4MDAwODAxY2EwMTFiYzIyYzY2NDU3MDEzM2RmY2E0ZjA4YTBiOGQwMjMzOWNmNDY3MDQ2ZDZhNDE1MmYwNGYzNjhkMGVhZjk5ZWEwMWQ2ZGM1Y2YwYzg5N2M4ZDRjM2UxZGY1M2QwZDA0Mjc4NGM0MjQ1MzZhNGNjNWI4MDI1NTJiN2Q2NGZlZThiNSc7XG4gIGNvbnN0IGhvcFR4aWQgPSAnMHg0YWY2NTE0M2JjNzdkYTJiNTBmMzViM2QxM2NhY2I0ZGIxOGYwMjZiZjg0YmMwNzQzNTUwYmM1N2I5YjUzMzUxJztcbiAgY29uc3QgdXNlclJlcVNpZyA9XG4gICAgJzB4NDA0ZGIzMDdmNjE0N2YwZDhjZDMzOGMzNGMxMzkwNmVmNDZhNmZhYTdlMGUxMTlkNTE5NGVmMDVhZWMxNmU2ZjNkNzEwZjliNzkwMTQ2MGY5N2U5MjQwNjZiNjJlZmQ3NDQ0M2JkMzQ0MDJjNmQ0MGI0OWMyMDNhNTU5ZmYyYzgnO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYml0Z29LZXlYcHJ2ID1cbiAgICAgICd4cHJ2OXMyMVpyUUgxNDNLM3RwV0JIV2UzMXNMb1hOUlE5QXZSWUpnaXRrS3hRNEFURlFNd3ZyN2hITnFZUlVuUzdQc2p6QjdhSzFWeHFITHVOUWpqMXNja0oySndvMnF4bXN2ZWp3RUNTcEZNZkMnO1xuICAgIGNvbnN0IGJpdGdvS2V5ID0gYmlwMzIuZnJvbUJhc2U1OChiaXRnb0tleVhwcnYpO1xuICAgIGlmICghYml0Z29LZXkucHJpdmF0ZUtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlS2V5Jyk7XG4gICAgfVxuICAgIGNvbnN0IGJpdGdvWHB1YiA9IGJpdGdvS2V5Lm5ldXRlcmVkKCkudG9CYXNlNTgoKTtcbiAgICBob3BUeEJpdGdvU2lnbmF0dXJlID1cbiAgICAgICcweGFhJyArXG4gICAgICBCdWZmZXIuZnJvbShzZWNwMjU2azEuZWNkc2FTaWduKEJ1ZmZlci5mcm9tKGhvcFR4aWQuc2xpY2UoMiksICdoZXgnKSwgYml0Z29LZXkucHJpdmF0ZUtleSkuc2lnbmF0dXJlKS50b1N0cmluZyhcbiAgICAgICAgJ2hleCdcbiAgICAgICk7XG5cbiAgICBjb25zdCBlbnYgPSAndGVzdCc7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52IH0pO1xuICAgIGNvbW1vbi5FbnZpcm9ubWVudHNbZW52XS5oc21YcHViID0gYml0Z29YcHViO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcigncG9seWdvbicsIFBvbHlnb24uY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcigndHBvbHlnb24nLCBUcG9seWdvbi5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0cG9seWdvbicpO1xuICB9KTtcblxuICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICB9KTtcblxuICAvKipcbiAgICogQnVpbGQgYW4gdW5zaWduZWQgYWNjb3VudC1saWIgbXVsdGktc2lnbmF0dXJlIHNlbmQgdHJhbnNhY3Rpbm9cbiAgICogQHBhcmFtIGRlc3RpbmF0aW9uIFRoZSBkZXN0aW5hdGlvbiBhZGRyZXNzIG9mIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gY29udHJhY3RBZGRyZXNzIFRoZSBhZGRyZXNzIG9mIHRoZSBzbWFydCBjb250cmFjdCBwcm9jZXNzaW5nIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gY29udHJhY3RTZXF1ZW5jZUlkIFRoZSBzZXF1ZW5jZSBpZCBvZiB0aGUgY29udHJhY3RcbiAgICogQHBhcmFtIG5vbmNlIFRoZSBub25jZSBvZiB0aGUgc2VuZGluZyBhZGRyZXNzXG4gICAqIEBwYXJhbSBleHBpcmVUaW1lIFRoZSBleHBpcmUgdGltZSBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGFtb3VudCBUaGUgYW1vdW50IHRvIHNlbmQgdG8gdGhlIHJlY2lwaWVudFxuICAgKiBAcGFyYW0gZ2FzUHJpY2UgVGhlIGdhcyBwcmljZSBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGdhc0xpbWl0IFRoZSBnYXMgbGltaXQgb2YgdGhlIHRyYW5zYWN0aW9uXG4gICAqL1xuICBjb25zdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoe1xuICAgIGRlc3RpbmF0aW9uLFxuICAgIGNvbnRyYWN0QWRkcmVzcyxcbiAgICBjb250cmFjdFNlcXVlbmNlSWQgPSAxLFxuICAgIG5vbmNlID0gMCxcbiAgICBleHBpcmVUaW1lID0gTWF0aC5mbG9vcihuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApLFxuICAgIGFtb3VudCA9ICcxMDAwMDAnLFxuICAgIGdhc1ByaWNlID0gJzEwMDAwJyxcbiAgICBnYXNMaW1pdCA9ICcyMDAwMCcsXG4gIH0pIHtcbiAgICBjb25zdCB0eEJ1aWxkZXI6IFRyYW5zYWN0aW9uQnVpbGRlciA9IGdldEJ1aWxkZXIoJ3Rwb2x5Z29uJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgIGZlZTogZ2FzUHJpY2UsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQsXG4gICAgfSk7XG4gICAgdHhCdWlsZGVyLmNvdW50ZXIobm9uY2UpO1xuICAgIHR4QnVpbGRlci5jb250cmFjdChjb250cmFjdEFkZHJlc3MpO1xuICAgIGNvbnN0IHRyYW5zZmVyQnVpbGRlciA9IHR4QnVpbGRlci50cmFuc2ZlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcblxuICAgIHRyYW5zZmVyQnVpbGRlclxuICAgICAgLmNvaW4oJ3Rwb2x5Z29uJylcbiAgICAgIC5leHBpcmF0aW9uVGltZShleHBpcmVUaW1lKVxuICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAudG8oZGVzdGluYXRpb24pXG4gICAgICAuY29udHJhY3RTZXF1ZW5jZUlkKGNvbnRyYWN0U2VxdWVuY2VJZCk7XG5cbiAgICByZXR1cm4gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIH07XG5cbiAgZGVzY3JpYmUoJ0luc3RhbnRpYXRlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgaW5zdGFudGlhdGUgdGhlIGNvaW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgbG9jYWxCYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3Rwb2x5Z29uJyk7XG4gICAgICBsb2NhbEJhc2Vjb2luLnNob3VsZC5iZS5hbi5pbnN0YW5jZW9mKFRwb2x5Z29uKTtcblxuICAgICAgbG9jYWxCYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3BvbHlnb24nKTtcbiAgICAgIGxvY2FsQmFzZWNvaW4uc2hvdWxkLmJlLmFuLmluc3RhbmNlb2YoUG9seWdvbik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFeHBsYWluIHRyYW5zYWN0aW9uOicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIG9wdGlvbnMgb2JqZWN0IGlzIG1pc3NpbmcgcGFyYW1ldGVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW5QYXJhbXMgPSB7XG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAxIH0sXG4gICAgICAgIHR4SGV4OiBudWxsLFxuICAgICAgfTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbihleHBsYWluUGFyYW1zKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2V4cGxhaW4gYSB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRlc3RpbmF0aW9uID0gJzB4ZmFhOGYxNGY0NmE5OWViNDM5YzUwZTBjM2I4MzVjYzIxZGFkNTFiNCc7XG4gICAgICBjb25zdCBjb250cmFjdEFkZHJlc3MgPSAnMHg5ZTJjNTcxMmFiNGNhZjQwMmE5OGM0YmY1OGM3OWEwZGZlNzE4YWQxJztcblxuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgICBjb250cmFjdEFkZHJlc3MsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZXhwbGFpblBhcmFtcyA9IHtcbiAgICAgICAgaGFsZlNpZ25lZDoge1xuICAgICAgICAgIHR4SGV4OiB1bnNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICAgIGZlZUluZm86IHsgZmVlOiAxIH0sXG4gICAgICB9O1xuICAgICAgY29uc3QgZXhwbGFuYXRpb24gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oZXhwbGFpblBhcmFtcyk7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwbGFuYXRpb24uaWQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiBUcmFuc2FjdGlvbicsICgpID0+IHtcbiAgICBjb25zdCBhY2NvdW50XzEgPSB7XG4gICAgICBhZGRyZXNzOiAnMHg4Q2U1OWMyZDE3MDI4NDRGOEVkRUQ0NTFBQTEwMzk2MWJDMzdCNGU4JyxcbiAgICAgIG93bmVyXzE6ICc0ZWUwODlhY2VhYmYzZGRiZjc0OGRiNzliMTA2NmMzM2I3ZDNlYTFhYjNlYjdlMzI1MTIxYmJhMmJmZjJmNWNhJyxcbiAgICAgIG93bmVyXzI6ICc1YzdlNGVmZmY3MzA0ZDRkZmZmNmQ1ZjE1OTE4NDRlYzZmMmFkZmE2YTQ3ZTlmZWNlNmEzYzFhNGQ3NTVmMWUzJyxcbiAgICAgIG93bmVyXzM6ICc0NDIxYWIyNWRkOTFlMWEzMTgwZDAzZDU3YzMyM2E3ODg2ZGNjMzEzZDNiM2E0YjQyNTZhNTc5MTU3MmJmNTk3JyxcbiAgICB9O1xuXG4gICAgY29uc3QgYWNjb3VudF8yID0ge1xuICAgICAgYWRkcmVzczogJzB4ZWVhZjBGMDVmMzc4OTFhYjRhMjEyMDhCMTA1QTA2ODdkMTJjNWFGNycsXG4gICAgICBvd25lcl8xOiAnNGVlMDg5YWNlYWJmM2RkYmY3NDhkYjc5YjEwNjZjMzNiN2QzZWExYWIzZWI3ZTMyNTEyMWJiYTJiZmYyZjVjYScsXG4gICAgICBvd25lcl8yOiAnNWNhMTE2ZDI1YWVjNWY3NjU0NjU0MzJjYzQyMWZmMjVlZjlmZmRjMzMwYjEwYmIzZDlhZDYxZTNiYWFkODhkNycsXG4gICAgICBvd25lcl8zOiAnMWZhZTk0NmNjODRhZjhiZDc0ZDYxMGE4ODUzN2UyNGUxOWMzMzQ5ZDQ3OGQ4NmZjNWJiNTliYTRjODhmYjljYycsXG4gICAgfTtcblxuICAgIGl0KCdzaG91bGQgc2lnbiBhbiB1bnNpZ25lZCB0ZXN0IHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGdldEJ1aWxkZXIoJ3Rwb2x5Z29uJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgICAgYnVpbGRlci5mZWUoe1xuICAgICAgICBmZWU6ICcyODAwMDAwMDAwMDAnLFxuICAgICAgICBnYXNMaW1pdDogJzcwMDAwMDAnLFxuICAgICAgfSk7XG4gICAgICBidWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgICBidWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgYnVpbGRlci5jb250cmFjdChhY2NvdW50XzEuYWRkcmVzcyk7XG4gICAgICBidWlsZGVyLnRyYW5zZmVyKCkuYW1vdW50KCcxJykudG8oYWNjb3VudF8yLmFkZHJlc3MpLmV4cGlyYXRpb25UaW1lKDEwMDAwKS5jb250cmFjdFNlcXVlbmNlSWQoMSk7XG5cbiAgICAgIGNvbnN0IHVuc2lnbmVkVHggPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB1bnNpZ25lZFR4Rm9yQnJvYWRjYXN0aW5nID0gdW5zaWduZWRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBjb25zdCBoYWxmU2lnbmVkUmF3VHggPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcsXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogYWNjb3VudF8xLm93bmVyXzIsXG4gICAgICB9KTtcblxuICAgICAgYnVpbGRlci50cmFuc2ZlcigpLmtleShhY2NvdW50XzEub3duZXJfMik7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHggPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcgPSBoYWxmU2lnbmVkVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQudHhIZXguc2hvdWxkLmVxdWFscyhoYWxmU2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcpO1xuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQucmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGhhbGZTaWduZWRSYXdUeC5oYWxmU2lnbmVkLnJlY2lwaWVudHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbHMoYWNjb3VudF8yLmFkZHJlc3MudG9Mb3dlckNhc2UoKSk7XG4gICAgICBoYWxmU2lnbmVkUmF3VHguaGFsZlNpZ25lZC5yZWNpcGllbnRzWzBdLmFtb3VudC50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbHMoJzEnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2lnbiBhbiB1bnNpZ25lZCB0ZXN0IHR4IHdpdGggZWlwMTU1OScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBnZXRCdWlsZGVyKCd0cG9seWdvbicpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICAgIGJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMjgwMDAwMDAwMDAwJyxcbiAgICAgICAgZ2FzTGltaXQ6ICc3MDAwMDAwJyxcbiAgICAgICAgZWlwMTU1OToge1xuICAgICAgICAgIG1heEZlZVBlckdhczogJzc1OTMxMjMnLFxuICAgICAgICAgIG1heFByaW9yaXR5RmVlUGVyR2FzOiAnMTUwJyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgYnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgYnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIGJ1aWxkZXIuY29udHJhY3QoYWNjb3VudF8xLmFkZHJlc3MpO1xuICAgICAgYnVpbGRlci50cmFuc2ZlcigpLmFtb3VudCgnMScpLnRvKGFjY291bnRfMi5hZGRyZXNzKS5leHBpcmF0aW9uVGltZSgxMDAwMCkuY29udHJhY3RTZXF1ZW5jZUlkKDEpO1xuXG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gYXdhaXQgYnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdW5zaWduZWRUeEZvckJyb2FkY2FzdGluZyA9IHVuc2lnbmVkVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgaGFsZlNpZ25lZFJhd1R4ID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiB1bnNpZ25lZFR4Rm9yQnJvYWRjYXN0aW5nLFxuICAgICAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgICAgIG1heEZlZVBlckdhczogJzc1OTMxMjMnLFxuICAgICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6ICcxNTAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHBydjogYWNjb3VudF8xLm93bmVyXzIsXG4gICAgICB9KTtcblxuICAgICAgYnVpbGRlci50cmFuc2ZlcigpLmtleShhY2NvdW50XzEub3duZXJfMik7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHggPSBhd2FpdCBidWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcgPSBoYWxmU2lnbmVkVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQudHhIZXguc2hvdWxkLmVxdWFscyhoYWxmU2lnbmVkVHhGb3JCcm9hZGNhc3RpbmcpO1xuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQucmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFscygxKTtcbiAgICAgIGhhbGZTaWduZWRSYXdUeC5oYWxmU2lnbmVkLnJlY2lwaWVudHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbHMoYWNjb3VudF8yLmFkZHJlc3MudG9Mb3dlckNhc2UoKSk7XG4gICAgICBoYWxmU2lnbmVkUmF3VHguaGFsZlNpZ25lZC5yZWNpcGllbnRzWzBdLmFtb3VudC50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbHMoJzEnKTtcbiAgICAgIGhhbGZTaWduZWRSYXdUeC5oYWxmU2lnbmVkLmVpcDE1NTkubWF4RmVlUGVyR2FzLnNob3VsZC5lcXVhbCgnNzU5MzEyMycpO1xuICAgICAgaGFsZlNpZ25lZFJhd1R4LmhhbGZTaWduZWQuZWlwMTU1OS5tYXhQcmlvcml0eUZlZVBlckdhcy5zaG91bGQuZXF1YWwoJzE1MCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBpbmNsdWRlIGlzQmF0Y2ggZmllbGQgaW4gaGFsZlNpZ25lZCB3aGVuIHNpZ25pbmcgYSBuYXRpdmUgYmF0Y2ggdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiYXRjaGVyQ29udHJhY3RBZGRyZXNzID0gJzB4YjFiN2U3Y2MxZWNhZmJmZDA3NzFhNWViNTQ1NGFiNWIwMzU2OTgwZCc7XG4gICAgICBjb25zdCByZWNpcGllbnRzOiBSZWNpcGllbnRbXSA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IGFjY291bnRfMi5hZGRyZXNzLFxuICAgICAgICAgIGFtb3VudDogJzUwMDAwMDAwMDAwMCcsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMHg3ZTg1YmRjMjdjMDUwZTM5MDVlYmY0YjhlNjM0ZDlhZDZlZGQwZGU2JyxcbiAgICAgICAgICBhbW91bnQ6ICc1MDAwMDAwMDAwMDAnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHRvdGFsQW1vdW50ID0gcmVjaXBpZW50cy5yZWR1Y2UoXG4gICAgICAgIChzdW0sIHJlY2lwaWVudCkgPT4gbmV3IEJpZ051bWJlcihzdW0pLnBsdXMocmVjaXBpZW50LmFtb3VudCkudG9TdHJpbmcoKSxcbiAgICAgICAgJzAnXG4gICAgICApO1xuICAgICAgY29uc3QgQkFUQ0hfTUVUSE9EX05BTUUgPSAnYmF0Y2gnO1xuICAgICAgY29uc3QgQkFUQ0hfTUVUSE9EX1RZUEVTID0gWydhZGRyZXNzW10nLCAndWludDI1NltdJ107XG5cbiAgICAgIGNvbnN0IGFkZHJlc3NlcyA9IHJlY2lwaWVudHMubWFwKChyKSA9PiByLmFkZHJlc3MpO1xuICAgICAgY29uc3QgYW1vdW50cyA9IHJlY2lwaWVudHMubWFwKChyKSA9PiByLmFtb3VudCk7XG4gICAgICBjb25zdCBiYXRjaEV4ZWN1dGlvbkluZm8gPSB7XG4gICAgICAgIHZhbHVlczogW2FkZHJlc3NlcywgYW1vdW50c10sXG4gICAgICAgIHRvdGFsQW1vdW50OiB0b3RhbEFtb3VudCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGV0aEFiaSA9IHJlcXVpcmUoJ2V0aGVyZXVtanMtYWJpJyk7XG4gICAgICBjb25zdCBldGhVdGlsID0gcmVxdWlyZSgnZXRoZXJldW1qcy11dGlsJyk7XG5cbiAgICAgIGNvbnN0IGdldE1ldGhvZENhbGxEYXRhID0gKGZ1bmN0aW9uTmFtZSwgdHlwZXMsIHZhbHVlcykgPT4ge1xuICAgICAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChbXG4gICAgICAgICAgLy8gZnVuY3Rpb24gc2lnbmF0dXJlXG4gICAgICAgICAgZXRoQWJpLm1ldGhvZElEKGZ1bmN0aW9uTmFtZSwgdHlwZXMpLFxuICAgICAgICAgIC8vIGZ1bmN0aW9uIGFyZ3VtZW50c1xuICAgICAgICAgIGV0aEFiaS5yYXdFbmNvZGUodHlwZXMsIHZhbHVlcyksXG4gICAgICAgIF0pO1xuICAgICAgfTtcblxuICAgICAgY29uc3QgYmF0Y2hEYXRhID0gZXRoVXRpbC5hZGRIZXhQcmVmaXgoXG4gICAgICAgIGdldE1ldGhvZENhbGxEYXRhKEJBVENIX01FVEhPRF9OQU1FLCBCQVRDSF9NRVRIT0RfVFlQRVMsIGJhdGNoRXhlY3V0aW9uSW5mby52YWx1ZXMpLnRvU3RyaW5nKCdoZXgnKVxuICAgICAgKTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndHBvbHlnb24nKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHtcbiAgICAgICAgZmVlOiAnMjgwMDAwMDAwMDAwJyxcbiAgICAgICAgZ2FzTGltaXQ6ICc3MDAwMDAwJyxcbiAgICAgIH0pO1xuICAgICAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICB0eEJ1aWxkZXIuY29udHJhY3QoYWNjb3VudF8xLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyXG4gICAgICAgIC50cmFuc2ZlcigpXG4gICAgICAgIC5hbW91bnQodG90YWxBbW91bnQpXG4gICAgICAgIC50byhiYXRjaGVyQ29udHJhY3RBZGRyZXNzKVxuICAgICAgICAuZGF0YShiYXRjaERhdGEpXG4gICAgICAgIC5leHBpcmF0aW9uVGltZSgxMDAwMClcbiAgICAgICAgLmNvbnRyYWN0U2VxdWVuY2VJZCgxKTtcblxuICAgICAgY29uc3QgdW5zaWduZWRUeCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdW5zaWduZWRUeEhleCA9IHVuc2lnbmVkVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHhIZXgsXG4gICAgICAgIGlzQmF0Y2g6IHRydWUsXG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhbW91bnQ6IHRvdGFsQW1vdW50LFxuICAgICAgICAgICAgYWRkcmVzczogYmF0Y2hlckNvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAxLFxuICAgICAgICBnYXNQcmljZTogMjgwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNzAwMDAwMCxcbiAgICAgICAgY29pbjogJ3Rwb2x5Z29uJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IGFjY291bnRfMS5hZGRyZXNzLFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2lnbmVkVHggPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICBwcnY6IGFjY291bnRfMS5vd25lcl8yLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzaWduZWRUeCk7XG4gICAgICBzaG91bGQuZXhpc3Qoc2lnbmVkVHguaGFsZlNpZ25lZCk7XG4gICAgICBzaWduZWRUeC5oYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0JhdGNoJywgdHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSBub3JtYWwgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgdGhhdCBtYXRjaGVzIHRoZSBjbGllbnQgdHhQYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3Rwb2x5Z29uJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIGhvcCB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB0aGF0IG1hdGNoZXMgdGhlIGNsaWVudCB0eFBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6IDEwMDAwMDAwMDAwMDAwMDAsIGFkZHJlc3M6IGhvcERlc3RpbmF0aW9uQWRkcmVzcyB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIGhvcDogdHJ1ZSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzUwMDAwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBob3BDb250cmFjdEFkZHJlc3MgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICd0cG9seWdvbicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6IGhvcFR4LFxuICAgICAgICAgIGlkOiBob3BUeGlkLFxuICAgICAgICAgIHNpZ25hdHVyZTogaG9wVHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgICBwYXltZW50SWQ6ICcyNzczOTI4MTk2JyxcbiAgICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICByZWNpcGllbnQ6IGhvcERlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgICBub25jZTogMCxcbiAgICAgICAgICB1c2VyUmVxU2lnOiB1c2VyUmVxU2lnLFxuICAgICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgd2hlbiBjbGllbnQgdHhQYXJhbXMgYXJlIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG51bGw7XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3Rwb2x5Z29uJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcGFyYW1zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCB0eFByZWJ1aWxkIHRoYXQgaXMgYm90aCBiYXRjaCBhbmQgaG9wJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9LFxuICAgICAgICAgIHsgYW1vdW50OiAnMjUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MyIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBob3A6IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICczNTAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogdHJ1ZSxcbiAgICAgICAgY29pbjogJ3Rwb2x5Z29uJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgICAgaG9wVHJhbnNhY3Rpb246IHtcbiAgICAgICAgICB0eDogaG9wVHgsXG4gICAgICAgICAgaWQ6IGhvcFR4aWQsXG4gICAgICAgICAgc2lnbmF0dXJlOiBob3BUeEJpdGdvU2lnbmF0dXJlLFxuICAgICAgICAgIHBheW1lbnRJZDogJzI3NzM5MjgxOTYnLFxuICAgICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICAgIHJlY2lwaWVudDogaG9wRGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICAgIG5vbmNlOiAwLFxuICAgICAgICAgIHVzZXJSZXFTaWc6IHVzZXJSZXFTaWcsXG4gICAgICAgICAgZ2FzUHJpY2VNYXg6IDUwMDAwMDAwMDAwMCxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3R4IGNhbm5vdCBiZSBib3RoIGEgYmF0Y2ggYW5kIGhvcCB0cmFuc2FjdGlvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSB0eFByZWJ1aWxkIHdpdGggbW9yZSB0aGFuIG9uZSByZWNpcGllbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyNTAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczIgfSxcbiAgICAgICAgXSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMiB9LFxuICAgICAgICBdLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IHRydWUsXG4gICAgICAgIGNvaW46ICd0cG9seWdvbicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIGB0cG9seWdvbiBkb2Vzbid0IHN1cHBvcnQgc2VuZGluZyB0byBtb3JlIHRoYW4gMSBkZXN0aW5hdGlvbiBhZGRyZXNzIHdpdGhpbiBhIHNpbmdsZSB0cmFuc2FjdGlvbi4gVHJ5IGFnYWluLCB1c2luZyBvbmx5IGEgc2luZ2xlIHJlY2lwaWVudC5gXG4gICAgICAgICk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSBob3AgdHhQcmVidWlsZCB0aGF0IGRvZXMgbm90IHNlbmQgdG8gaXRzIGhvcCBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBob3BEZXN0aW5hdGlvbkFkZHJlc3MgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBob3A6IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICc1MDAwMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICd0cG9seWdvbicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6IGhvcFR4LFxuICAgICAgICAgIGlkOiBob3BUeGlkLFxuICAgICAgICAgIHNpZ25hdHVyZTogaG9wVHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgICBwYXltZW50SWQ6ICcwJyxcbiAgICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICByZWNpcGllbnQ6IGhvcERlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgICBub25jZTogMCxcbiAgICAgICAgICB1c2VyUmVxU2lnOiB1c2VyUmVxU2lnLFxuICAgICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdyZWNpcGllbnQgYWRkcmVzcyBvZiB0eFByZWJ1aWxkIGRvZXMgbm90IG1hdGNoIGhvcCBhZGRyZXNzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBhIG5vcm1hbCB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB3aXRoIHRoZSB3cm9uZyBhbW91bnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6IGFkZHJlc3MxIH1dLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzIwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3Rwb2x5Z29uJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ25vcm1hbCB0cmFuc2FjdGlvbiBhbW91bnQgaW4gdHhQcmVidWlsZCByZWNlaXZlZCBmcm9tIEJpdEdvIHNlcnZlcnMgZG9lcyBub3QgbWF0Y2ggdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50J1xuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSBub3JtYWwgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgd2l0aCB0aGUgd3JvbmcgcmVjaXBpZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczIgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICd0cG9seWdvbicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICdkZXN0aW5hdGlvbiBhZGRyZXNzIGluIG5vcm1hbCB0eFByZWJ1aWxkIGRvZXMgbm90IG1hdGNoIHRoYXQgaW4gdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50J1xuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB3aXRoIHRoZSB3cm9uZyBjb2luJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZWNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiBhZGRyZXNzMSB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogYWRkcmVzczEgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICdidGMnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnY29pbiBpbiB0eFByZWJ1aWxkIGRpZCBub3QgbWF0Y2ggdGhhdCBpbiB0eFBhcmFtcyBzdXBwbGllZCBieSBjbGllbnQnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXIgdHJhbnNhY3Rpb246JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2VVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzLnRlc3QucG9seWdvbnNjYW5CYXNlVXJsIGFzIHN0cmluZztcbiAgICBjb25zdCB1c2VyWHB1YiA9XG4gICAgICAneHB1YjY2MU15TXdBcVJiY0VlVGM4Nzg5TUs1UFVHRVlpUEc0RjRWMTduMlJkMkxvVEFUQTFYb0NuSlQ1RkFZQVNoUXhTeHRGanBvNU5IbWNXd1RwMkxpV0dCTXdwVWNBQTNIeXdoeGl2Z1lmcTdxJztcbiAgICBjb25zdCB1c2VyWHBydiA9XG4gICAgICAneHBydjlzMjFaclFIMTQzSzJBUDkyNWI4ekI4ZXZFUTRKdllDc3FaUUtQY3A0Z29wYU44MVR6VXhFVzhiUHRWeURnam1kZEdoUlJFVG44eGkxY1ZBQjliZjFCeDlrR1JSRmdUWlh4SmF5WkxuYWcxJztcbiAgICBjb25zdCBiYWNrdXBYcHViID1cbiAgICAgICd4cHViNjYxTXlNd0FxUmJjRlpYMTV4cFpmNEVSQ0dIaVZTSm04cjVDNHloMXlYVjJHcmRaQ1VQWW80V1FyNnROOW9VeXdLWHNnU0hvN1Jpc2Y5cjIyR0g1am9WRDJoRUVFaHFuU0N2SzhxeTExd1cnO1xuICAgIGNvbnN0IGJhY2t1cFhwcnYgPVxuICAgICAgJ3hwcnY5czIxWnJRSDE0M0szNVNYeXdIWkh2SGdlRVRFNXlhdW1kOWJHYkhRUkJ4M1E0SlFldzVKRkdCdnpxaVpqQ1VrQmRCVVpuZnVNRFRHVVJSYXlOMWhGU1d4RUpRc0NFQU1tMUQzcGsxaDdKaic7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGFuIHVuc2lnbmVkIHN3ZWVwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0Q29udHJhY3RBZGRyZXNzID0gVGVzdEJpdEdvLlYyLlRFU1RfRVRIX1dBTExFVF9GSVJTVF9BRERSRVNTIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IGJhY2t1cEtleUFkZHJlc3MgPSAnMHg0ZjJjNDgzMGNjMzdmMjc4NWM2NDZmODlkZWQ4YTkxOTIxOWZhMGU5JztcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC50d2ljZSgpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUeExpc3RSZXF1ZXN0KGJhY2t1cEtleUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3Qod2FsbGV0Q29udHJhY3RBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChiYWNrdXBLZXlBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG4gICAgICBjb25zdCBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3Rwb2x5Z29uJykgYXMgUG9seWdvbjtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiB1c2VyWHB1YixcbiAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBYcHViLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHdhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogVGVzdEJpdEdvLlYyLlRFU1RfRVJDMjBfVE9LRU5fUkVDSVBJRU5UIGFzIHN0cmluZyxcbiAgICAgICAgZWlwMTU1OTogeyBtYXhGZWVQZXJHYXM6IDIwMDAwMDAwMDAwLCBtYXhQcmlvcml0eUZlZVBlckdhczogMTAwMDAwMDAwMDAgfSxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgIH0pKSBhcyBPZmZsaW5lVmF1bHRUeEluZm87XG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24pO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29udHJhY3RTZXF1ZW5jZUlkJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZXhwaXJlVGltZScpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2dhc0xpbWl0Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5nYXNMaW1pdC5zaG91bGQuZXF1YWwoJzUwMDAwMCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldENvbnRyYWN0QWRkcmVzcycpO1xuICAgICAgdHJhbnNhY3Rpb24ud2FsbGV0Q29udHJhY3RBZGRyZXNzLnNob3VsZC5lcXVhbChUZXN0Qml0R28uVjIuVEVTVF9FVEhfV0FMTEVUX0ZJUlNUX0FERFJFU1MpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnKTtcbiAgICAgIGNvbnN0IHJlY2lwaWVudCA9IHRyYW5zYWN0aW9uLnJlY2lwaWVudHNbMF07XG4gICAgICByZWNpcGllbnQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkZHJlc3MnKTtcbiAgICAgIHJlY2lwaWVudC5hZGRyZXNzLnNob3VsZC5lcXVhbChUZXN0Qml0R28uVjIuVEVTVF9FUkMyMF9UT0tFTl9SRUNJUElFTlQpO1xuICAgICAgcmVjaXBpZW50LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhbW91bnQnKTtcbiAgICAgIHJlY2lwaWVudC5hbW91bnQuc2hvdWxkLmVxdWFsKCc5OTk5OTk5OTk5OTk5OTk5OTI4Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNvbnN0cnVjdCBhIHJlY292ZXJ5IHRyYW5zYWN0aW9uIHdpdGhvdXQgQml0R28nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiYWNrdXBLZXlBZGRyZXNzID0gJzB4NmQyMmVmZGQ2MzQ5OTYyNDgxNzBjOTQ4ZTU3MjYwMDdmYzI1MWJiMyc7XG4gICAgICBjb25zdCB3YWxsZXRDb250cmFjdEFkZHJlc3MgPSBUZXN0Qml0R28uVjIuVEVTVF9FVEhfV0FMTEVUX0ZJUlNUX0FERFJFU1MgYXMgc3RyaW5nO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldFR4TGlzdFJlcXVlc3QoYmFja3VwS2V5QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldFR4TGlzdFJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdCh3YWxsZXRDb250cmFjdEFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KGJhY2t1cEtleUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKS5nZXQoJy9hcGknKS5xdWVyeShtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXF1ZXN0KS5yZXBseSgyMDAsIG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlc3BvbnNlKTtcbiAgICAgIGNvbnN0IGJhc2Vjb2luID0gYml0Z28uY29pbigndHBvbHlnb24nKSBhcyBQb2x5Z29uO1xuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6XG4gICAgICAgICAgJ3tcIml2XCI6XCJWRlozanZYaHhvMVorWWFmMk10Wm5BPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiXFxuJyArXG4gICAgICAgICAgJzpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcInArZmtIdUxhLzhrPVwiLFwiY3RcIjpcImhZRzdwdmxqTElnQ2paXFxuJyArXG4gICAgICAgICAgJzUzUEJsQ2RlNUtaUm1sVUtLSEx0RE1rK0hKZnVVNDZoVyt4K0M5V3NJQU80Z0ZQblRDdkZWbVE4eDdjekN0Y05GdWI1QU8yb3RPR1xcbicgK1xuICAgICAgICAgICdPc1g0R0UyZ1hPRW1DbDFUcFd3d05obTd5TVVqR0pVcGdXNlpaZ1hTWGREaXRTS2k0Vi9oazc4U0dTempGT0JTUFlSYTZJPVwifVxcbicsXG4gICAgICAgIGJhY2t1cEtleTpcbiAgICAgICAgICAne1wiaXZcIjpcIkFic0N0djFxd1BJaE9neXJDcE5hZ0E9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjI1NixcInRzXCI6NjQsXCJtb2RlXCJcXG4nICtcbiAgICAgICAgICAnOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwiNXZwVURCVWx6bTg9XCIsXCJjdFwiOlwiUGFwWVlDakJYUkxVS0FcXG4nICtcbiAgICAgICAgICAnSmJPc0IvRUo5QjhmVW1WUVR4TVBqVW5ReUFreTEybWU5SzY2R2lNRUF4VEQ3a2Q2YllBUUp1dVRrQVRYS1U3Qm5mN3ZLOUp4Tk93XFxuJyArXG4gICAgICAgICAgJ29qaTdIRjllRkgwYUQ0L2hYNVNXRmZIRjJRZmkrVG5YdjZoVnNNQW9pc0RaczMvRjY3L1pVYURZUjBac2RyUTRRL2NMRDA9XCJ9XFxuJyxcblxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHdhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogVGVzdEJpdEdvLlYyLlRFU1RfUkVDT1ZFUllfUEFTU0NPREUsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RCaXRHby5WMi5URVNUX0VSQzIwX1RPS0VOX1JFQ0lQSUVOVCBhcyBzdHJpbmcsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICB9KSkgYXMgT2ZmbGluZVZhdWx0VHhJbmZvO1xuICAgICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICBjb25zdCBkZWNvZGVkVHggPSBvcHRpb25hbERlcHMuRXRoVHguVHJhbnNhY3Rpb24uZnJvbVNlcmlhbGl6ZWRUeChvcHRpb25hbERlcHMuZXRoVXRpbC50b0J1ZmZlcih0cmFuc2FjdGlvbi50eCkpO1xuICAgICAgZGVjb2RlZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdnYXNQcmljZScpO1xuICAgICAgZGVjb2RlZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub25jZScpO1xuICAgICAgZGVjb2RlZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0bycpO1xuICAgIH0pO1xuXG4gICAgeGl0KCdzaG91bGQgY29uc3RydWN0IGEgcmVjb3ZlcnkgdHggd2l0aCBUU1MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiYWNrdXBLZXlBZGRyZXNzID0gJzB4ZTc0MDZkYzQzZDEzZjY5OGZiNDFhMzQ1Yzc3ODNkMzlhNGMyZDE5MSc7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiYWNrdXBLZXlBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KGJhY2t1cEtleUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3Rwb2x5Z29uJykgYXMgUG9seWdvbjtcbiAgICAgIGNvbnN0IHVzZXJLZXkgPSBtb2NrRGF0YS5rZXlTaGFyZXMudXNlcktleVNoYXJlO1xuICAgICAgY29uc3QgYmFja3VwS2V5ID0gbW9ja0RhdGEua2V5U2hhcmVzLmJhY2t1cEtleVNoYXJlO1xuICAgICAgY29uc3QgYml0Z29LZXkgPSBtb2NrRGF0YS5rZXlTaGFyZXMuYml0Z29LZXlTaGFyZTtcblxuICAgICAgY29uc3QgdXNlclNpZ25pbmdNYXRlcmlhbDogRUNEU0FNZXRob2RUeXBlcy5TaWduaW5nTWF0ZXJpYWwgPSB7XG4gICAgICAgIHBTaGFyZTogdXNlcktleS5wU2hhcmUsXG4gICAgICAgIGJhY2t1cE5TaGFyZTogYmFja3VwS2V5Lm5TaGFyZXNbMV0sXG4gICAgICAgIGJpdGdvTlNoYXJlOiBiaXRnb0tleS5uU2hhcmVzWzFdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgYmFja3VwU2lnbmluZ01hdGVyaWFsOiBFQ0RTQU1ldGhvZFR5cGVzLlNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICAgICAgcFNoYXJlOiBiYWNrdXBLZXkucFNoYXJlLFxuICAgICAgICB1c2VyTlNoYXJlOiB1c2VyS2V5Lm5TaGFyZXNbMl0sXG4gICAgICAgIGJpdGdvTlNoYXJlOiBiaXRnb0tleS5uU2hhcmVzWzJdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZW5jcnlwdGVkQmFja3VwU2lnbmluZ01hdGVyaWFsID0gc2pjbC5lbmNyeXB0KFxuICAgICAgICBUZXN0Qml0R28uVjIuVEVTVF9SRUNPVkVSWV9QQVNTQ09ERSxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoYmFja3VwU2lnbmluZ01hdGVyaWFsKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IGVuY3J5cHRlZFVzZXJTaWduaW5nTWF0ZXJpYWwgPSBzamNsLmVuY3J5cHQoXG4gICAgICAgIFRlc3RCaXRHby5WMi5URVNUX1JFQ09WRVJZX1BBU1NDT0RFLFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh1c2VyU2lnbmluZ01hdGVyaWFsKVxuICAgICAgKTtcblxuICAgICAgY29uc3QgcmVjb3ZlcnlQYXJhbXMgPSB7XG4gICAgICAgIHVzZXJLZXk6IGVuY3J5cHRlZFVzZXJTaWduaW5nTWF0ZXJpYWwsXG4gICAgICAgIGJhY2t1cEtleTogZW5jcnlwdGVkQmFja3VwU2lnbmluZ01hdGVyaWFsLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICcweGU3NDA2ZGM0M2QxM2Y2OThmYjQxYTM0NWM3NzgzZDM5YTRjMmQxOTEnLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiAnMHhhYzA1ZGE3ODQ2NDUyMGFhN2M5ZDRjMTliZDdhNDQwYjExMWIzMDU0JyxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogVGVzdEJpdEdvLlYyLlRFU1RfUkVDT1ZFUllfUEFTU0NPREUsXG4gICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHJlY292ZXJ5UGFyYW1zKTtcbiAgICAgIC8vIGlkIGFuZCB0eCB3aWxsIGFsd2F5cyBiZSBkaWZmZXJlbnQgYmVjYXVzZSBvZiBleHBpcmVUaW1lXG4gICAgICBzaG91bGQuZXhpc3QocmVjb3ZlcnkpO1xuICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHgnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBzZWNvbmQgc2lnbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyBhcyBzdHJpbmc7XG4gICAgICBjb25zdCBiYWNrdXBLZXlBZGRyZXNzID0gJzB4NGYyYzQ4MzBjYzM3ZjI3ODVjNjQ2Zjg5ZGVkOGE5MTkyMTlmYTBlOSc7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAudHdpY2UoKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiYWNrdXBLZXlBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KHdhbGxldENvbnRyYWN0QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYmFja3VwS2V5QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpLmdldCgnL2FwaScpLnF1ZXJ5KG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlcXVlc3QpLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVzcG9uc2UpO1xuICAgICAgY29uc3QgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0cG9seWdvbicpIGFzIFBvbHlnb247XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogdXNlclhwdWIsXG4gICAgICAgIGJhY2t1cEtleTogYmFja3VwWHB1YixcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFRlc3RCaXRHby5WMi5URVNUX0VSQzIwX1RPS0VOX1JFQ0lQSUVOVCBhcyBzdHJpbmcsXG4gICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7IGNoYWluOiA4MDAwMiwgaGFyZGZvcms6ICdsb25kb24nIH0sXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICB9KSkgYXMgT2ZmbGluZVZhdWx0VHhJbmZvO1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogdHJhbnNhY3Rpb24udHhIZXgsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UHJlYnVpbGQsXG4gICAgICAgIHBydjogdXNlclhwcnYsXG4gICAgICB9O1xuICAgICAgLy8gc2lnbiB0cmFuc2FjdGlvbiBvbmNlXG4gICAgICBjb25zdCBoYWxmU2lnbmVkID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHBhcmFtcyBhcyBhbnkpO1xuICAgICAgY29uc3QgaGFsZlNpZ25lZFBhcmFtcyA9IHtcbiAgICAgICAgdHhQcmVidWlsZDogaGFsZlNpZ25lZCxcbiAgICAgICAgaXNMYXN0U2lnbmF0dXJlOiB0cnVlLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHdhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgcHJ2OiBiYWNrdXBYcHJ2LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZmluYWxTaWduZWQgPSAoYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKGhhbGZTaWduZWRQYXJhbXMgYXMgYW55KSkgYXMgRnVsbHlTaWduZWRUcmFuc2FjdGlvbjtcbiAgICAgIGZpbmFsU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndHBvbHlnb24nKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICB0eEJ1aWxkZXIuZnJvbShmaW5hbFNpZ25lZC50eEhleCk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC5zaWduYXR1cmUubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHJlYnVpbHRUeC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFdm0gQmFzZWQgQ3Jvc3MgQ2hhaW4gUmVjb3ZlcnkgdHJhbnNhY3Rpb246JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2VVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzLnRlc3QucG9seWdvbnNjYW5CYXNlVXJsIGFzIHN0cmluZztcbiAgICBjb25zdCB1c2VyWHB1YiA9XG4gICAgICAneHB1YjY2MU15TXdBcVJiY0VlVGM4Nzg5TUs1UFVHRVlpUEc0RjRWMTduMlJkMkxvVEFUQTFYb0NuSlQ1RkFZQVNoUXhTeHRGanBvNU5IbWNXd1RwMkxpV0dCTXdwVWNBQTNIeXdoeGl2Z1lmcTdxJztcbiAgICBjb25zdCBiaXRnb0ZlZUFkZHJlc3MgPSAnMHgzM2E0MmZhZWEzYzZlODcwMjEzNDdlNTE3MDBiNDhhYWY0OWFhMWU3JztcbiAgICBjb25zdCBkZXN0aW5hdGlvbkFkZHJlc3MgPSAnMHhkNWFkZGUxN2ZlZDhiYWVkM2YzMmI4NGFmMDViOGYyODE2ZjdiNTYwJztcbiAgICBjb25zdCBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcyA9ICcweGU1OTg2Y2U0NDkwZGViNjdkMjk1MDU2MmNlYjkzMGRkZjliZTdhMTQnO1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgYW4gdW5zaWduZWQgcmVjb3ZlcnkgdHhuIGZvciBjb2xkIHdhbGxldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyBhcyBzdHJpbmc7XG5cbiAgICAgIGNvbnN0IGJhc2Vjb2luID0gYml0Z28uY29pbigndHBvbHlnb24nKSBhcyBQb2x5Z29uO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldFR4TGlzdFJlcXVlc3QoYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KGJpdGdvRmVlQWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3Qod2FsbGV0Q29udHJhY3RBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiB1c2VyWHB1YixcbiAgICAgICAgYmFja3VwS2V5OiAnJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIGJpdGdvRmVlQWRkcmVzczogYml0Z29GZWVBZGRyZXNzLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGJpdGdvRGVzdGluYXRpb25BZGRyZXNzOiBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgIH0pKSBhcyBPZmZsaW5lVmF1bHRUeEluZm87XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbik7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd1c2VyS2V5Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvbnRyYWN0U2VxdWVuY2VJZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2V4cGlyZVRpbWUnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdnYXNMaW1pdCcpO1xuICAgICAgdHJhbnNhY3Rpb24uZ2FzTGltaXQuc2hvdWxkLmVxdWFsKCc1MDAwMDAnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0V2bUJhc2VkQ3Jvc3NDaGFpblJlY292ZXJ5Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5pc0V2bUJhc2VkQ3Jvc3NDaGFpblJlY292ZXJ5Py5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0Q29udHJhY3RBZGRyZXNzJyk7XG4gICAgICB0cmFuc2FjdGlvbi53YWxsZXRDb250cmFjdEFkZHJlc3Muc2hvdWxkLmVxdWFsKFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycpO1xuICAgICAgY29uc3QgcmVjaXBpZW50ID0gdHJhbnNhY3Rpb24ucmVjaXBpZW50c1swXTtcbiAgICAgIHJlY2lwaWVudC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWRkcmVzcycpO1xuICAgICAgcmVjaXBpZW50LmFkZHJlc3Muc2hvdWxkLmVxdWFsKGRlc3RpbmF0aW9uQWRkcmVzcyk7XG4gICAgICByZWNpcGllbnQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Ftb3VudCcpO1xuICAgICAgcmVjaXBpZW50LmFtb3VudC5zaG91bGQuZXF1YWwoJzk5OTk5OTk5OTk5OTk5OTk5MjgnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgYW4gdW5zaWduZWQgcmVjb3ZlcnkgdHhuIGZvciBjdXN0b2R5IHdhbGxldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyBhcyBzdHJpbmc7XG5cbiAgICAgIGNvbnN0IGJhc2Vjb2luID0gYml0Z28uY29pbigndHBvbHlnb24nKSBhcyBQb2x5Z29uO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldFR4TGlzdFJlcXVlc3QoYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0VHhMaXN0UmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KGJpdGdvRmVlQWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3Qod2FsbGV0Q29udHJhY3RBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybCkuZ2V0KCcvYXBpJykucXVlcnkobW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVxdWVzdCkucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiAnJyxcbiAgICAgICAgYmFja3VwS2V5OiAnJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIGJpdGdvRmVlQWRkcmVzczogYml0Z29GZWVBZGRyZXNzLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGJpdGdvRGVzdGluYXRpb25BZGRyZXNzOiBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgIH0pKSBhcyBPZmZsaW5lVmF1bHRUeEluZm87XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbik7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29udHJhY3RTZXF1ZW5jZUlkJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZXhwaXJlVGltZScpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2dhc0xpbWl0Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5nYXNMaW1pdC5zaG91bGQuZXF1YWwoJzUwMDAwMCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lzRXZtQmFzZWRDcm9zc0NoYWluUmVjb3ZlcnknKTtcbiAgICAgIHRyYW5zYWN0aW9uLmlzRXZtQmFzZWRDcm9zc0NoYWluUmVjb3Zlcnk/LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd3YWxsZXRDb250cmFjdEFkZHJlc3MnKTtcbiAgICAgIHRyYW5zYWN0aW9uLndhbGxldENvbnRyYWN0QWRkcmVzcy5zaG91bGQuZXF1YWwoVGVzdEJpdEdvLlYyLlRFU1RfRVRIX1dBTExFVF9GSVJTVF9BRERSRVNTKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdyZWNpcGllbnRzJyk7XG4gICAgICBjb25zdCByZWNpcGllbnQgPSB0cmFuc2FjdGlvbi5yZWNpcGllbnRzWzBdO1xuICAgICAgcmVjaXBpZW50LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhZGRyZXNzJyk7XG4gICAgICByZWNpcGllbnQuYWRkcmVzcy5zaG91bGQuZXF1YWwoZGVzdGluYXRpb25BZGRyZXNzKTtcbiAgICAgIHJlY2lwaWVudC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYW1vdW50Jyk7XG4gICAgICByZWNpcGllbnQuYW1vdW50LnNob3VsZC5lcXVhbCgnOTk5OTk5OTk5OTk5OTk5OTkyOCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCByZWNvdmVyeSB0eG4gZm9yIGhvdCB3YWxsZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1c2VyS2V5ID1cbiAgICAgICAgJ3tcIml2XCI6XCJWRlozanZYaHhvMVorWWFmMk10Wm5BPT1cIixcInZcIjoxLFwiaXRlclwiOjEwMDAwLFwia3NcIjoyNTYsXCJ0c1wiOjY0LFwibW9kZVwiXFxuJyArXG4gICAgICAgICc6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJwK2ZrSHVMYS84az1cIixcImN0XCI6XCJoWUc3cHZsakxJZ0NqWlxcbicgK1xuICAgICAgICAnNTNQQmxDZGU1S1pSbWxVS0tITHRETWsrSEpmdVU0NmhXK3grQzlXc0lBTzRnRlBuVEN2RlZtUTh4N2N6Q3RjTkZ1YjVBTzJvdE9HXFxuJyArXG4gICAgICAgICdPc1g0R0UyZ1hPRW1DbDFUcFd3d05obTd5TVVqR0pVcGdXNlpaZ1hTWGREaXRTS2k0Vi9oazc4U0dTempGT0JTUFlSYTZJPVwifVxcbic7XG4gICAgICBjb25zdCB3YWxsZXRDb250cmFjdEFkZHJlc3MgPSBUZXN0Qml0R28uVjIuVEVTVF9FVEhfV0FMTEVUX0ZJUlNUX0FERFJFU1MgYXMgc3RyaW5nO1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9IFRlc3RCaXRHby5WMi5URVNUX1JFQ09WRVJZX1BBU1NDT0RFIGFzIHN0cmluZztcblxuICAgICAgY29uc3QgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0cG9seWdvbicpIGFzIFBvbHlnb247XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdCh3YWxsZXRDb250cmFjdEFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKS5nZXQoJy9hcGknKS5xdWVyeShtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXF1ZXN0KS5yZXBseSgyMDAsIG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IHVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogJycsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogd2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICBiaXRnb0ZlZUFkZHJlc3M6IGJpdGdvRmVlQWRkcmVzcyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwMDAwMDAwMDAsIG1heFByaW9yaXR5RmVlUGVyR2FzOiAxMDAwMDAwMDAwMCB9LFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzczogYml0Z29EZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICB9KSkgYXMgT2ZmbGluZVZhdWx0VHhJbmZvO1xuXG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24pO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvbnRyYWN0U2VxdWVuY2VJZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2V4cGlyZVRpbWUnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdnYXNMaW1pdCcpO1xuICAgICAgdHJhbnNhY3Rpb24uZ2FzTGltaXQuc2hvdWxkLmVxdWFsKCc1MDAwMDAnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0V2bUJhc2VkQ3Jvc3NDaGFpblJlY292ZXJ5Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5pc0V2bUJhc2VkQ3Jvc3NDaGFpblJlY292ZXJ5Py5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0Q29udHJhY3RBZGRyZXNzJyk7XG4gICAgICB0cmFuc2FjdGlvbi53YWxsZXRDb250cmFjdEFkZHJlc3Muc2hvdWxkLmVxdWFsKFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycpO1xuICAgICAgY29uc3QgcmVjaXBpZW50ID0gdHJhbnNhY3Rpb24ucmVjaXBpZW50c1swXTtcbiAgICAgIHJlY2lwaWVudC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWRkcmVzcycpO1xuICAgICAgcmVjaXBpZW50LmFkZHJlc3Muc2hvdWxkLmVxdWFsKGRlc3RpbmF0aW9uQWRkcmVzcyk7XG4gICAgICByZWNpcGllbnQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Ftb3VudCcpO1xuICAgICAgcmVjaXBpZW50LmFtb3VudC5zaG91bGQuZXF1YWwoJzk5OTk5OTk5OTk5OTk5OTk5MjgnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVzVXNlZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uZmVlc1VzZWQ/Lmdhc0xpbWl0LnNob3VsZC5lcXVhbCgnNTAwMDAwJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaGFsZlNpZ25lZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uaGFsZlNpZ25lZD8uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5oYWxmU2lnbmVkPy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCByZWNvdmVyeSB0eG4gb2YgYSB0b2tlbiBmb3IgY29sZCB3YWxsZXQgJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0Q29udHJhY3RBZGRyZXNzID0gVGVzdEJpdEdvLlYyLlRFU1RfRVRIX1dBTExFVF9GSVJTVF9BRERSRVNTIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IHRva2VuQ29udHJhY3RBZGRyZXNzID0gJzB4MzI2Yzk3N2U2ZWZjODRlNTEyYmI5YzMwZjc2ZTMwYzE2MGVkMDZmYic7IC8vIHRwb2x5Z29uLWxpbmsgY29udHJhY3QgdG9rZW4gYWRkcmVzc1xuXG4gICAgICBjb25zdCBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3Rwb2x5Z29uJykgYXMgUG9seWdvbjtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUeExpc3RSZXF1ZXN0KGJpdGdvRmVlQWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldFR4TGlzdFJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChiaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldFRva2VuQmFsYW5jZVJlcXVlc3QodG9rZW5Db250cmFjdEFkZHJlc3MsIHdhbGxldENvbnRyYWN0QWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldEJhbGFuY2VSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpLmdldCgnL2FwaScpLnF1ZXJ5KG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlcXVlc3QpLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0Q29udHJhY3RDYWxsUmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogdXNlclhwdWIsXG4gICAgICAgIGJhY2t1cEtleTogJycsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogd2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICBiaXRnb0ZlZUFkZHJlc3M6IGJpdGdvRmVlQWRkcmVzcyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwMDAwMDAwMDAsIG1heFByaW9yaXR5RmVlUGVyR2FzOiAxMDAwMDAwMDAwMCB9LFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzczogYml0Z29EZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiB0b2tlbkNvbnRyYWN0QWRkcmVzcyxcbiAgICAgIH0pKSBhcyBPZmZsaW5lVmF1bHRUeEluZm87XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbik7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndHBvbHlnb24nKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICB0eEJ1aWxkZXIuZnJvbSh0cmFuc2FjdGlvbi50eEhleCk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeEpzb24gPSByZWJ1aWx0VHgudG9Kc29uKCk7XG4gICAgICByZWJ1aWx0VHhKc29uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdkYXRhJyk7XG4gICAgICByZWJ1aWx0VHhKc29uLmRhdGEuc2hvdWxkLnN0YXJ0V2l0aCgnMHgwZGNkN2E2YycpOyAvLyBzZW5kTXVsdGlTaWdUb2tlbiBmdW5jXG5cbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd1c2VyS2V5Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicpO1xuICAgICAgdHJhbnNhY3Rpb24uY29pbi5zaG91bGQuZXF1YWwoJ3Rwb2x5Z29uOmxpbmsnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb250cmFjdFNlcXVlbmNlSWQnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdleHBpcmVUaW1lJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZ2FzTGltaXQnKTtcbiAgICAgIHRyYW5zYWN0aW9uLmdhc0xpbWl0LnNob3VsZC5lcXVhbCgnNTAwMDAwJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeScpO1xuICAgICAgdHJhbnNhY3Rpb24uaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeT8uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldENvbnRyYWN0QWRkcmVzcycpO1xuICAgICAgdHJhbnNhY3Rpb24ud2FsbGV0Q29udHJhY3RBZGRyZXNzLnNob3VsZC5lcXVhbChUZXN0Qml0R28uVjIuVEVTVF9FVEhfV0FMTEVUX0ZJUlNUX0FERFJFU1MpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnKTtcbiAgICAgIGNvbnN0IHJlY2lwaWVudCA9IHRyYW5zYWN0aW9uLnJlY2lwaWVudHNbMF07XG4gICAgICByZWNpcGllbnQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkZHJlc3MnKTtcbiAgICAgIHJlY2lwaWVudC5hZGRyZXNzLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbkFkZHJlc3MpO1xuICAgICAgcmVjaXBpZW50LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhbW91bnQnKTtcbiAgICAgIHJlY2lwaWVudC5hbW91bnQuc2hvdWxkLmVxdWFsKCc5OTk5OTk5OTk5OTk5OTk5OTI4Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGFuIHVuc2lnbmVkIHJlY292ZXJ5IHR4biBvZiBhIHRva2VuIGZvciBjdXN0b2R5IHdhbGxldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyBhcyBzdHJpbmc7XG4gICAgICBjb25zdCB0b2tlbkNvbnRyYWN0QWRkcmVzcyA9ICcweDMyNmM5NzdlNmVmYzg0ZTUxMmJiOWMzMGY3NmUzMGMxNjBlZDA2ZmInOyAvLyB0cG9seWdvbi1saW5rIGNvbnRyYWN0IHRva2VuIGFkZHJlc3NcblxuICAgICAgY29uc3QgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0cG9seWdvbicpIGFzIFBvbHlnb247XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUb2tlbkJhbGFuY2VSZXF1ZXN0KHRva2VuQ29udHJhY3RBZGRyZXNzLCB3YWxsZXRDb250cmFjdEFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKS5nZXQoJy9hcGknKS5xdWVyeShtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXF1ZXN0KS5yZXBseSgyMDAsIG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6ICcnLFxuICAgICAgICBiYWNrdXBLZXk6ICcnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHdhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgYml0Z29GZWVBZGRyZXNzOiBiaXRnb0ZlZUFkZHJlc3MsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgZWlwMTU1OTogeyBtYXhGZWVQZXJHYXM6IDIwMDAwMDAwMDAwLCBtYXhQcmlvcml0eUZlZVBlckdhczogMTAwMDAwMDAwMDAgfSxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgYml0Z29EZXN0aW5hdGlvbkFkZHJlc3M6IGJpdGdvRGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogdG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgICB9KSkgYXMgT2ZmbGluZVZhdWx0VHhJbmZvO1xuXG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24pO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ3Rwb2x5Z29uJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgICAgdHhCdWlsZGVyLmZyb20odHJhbnNhY3Rpb24udHhIZXgpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCByZWJ1aWx0VHhKc29uID0gcmVidWlsdFR4LnRvSnNvbigpO1xuICAgICAgcmVidWlsdFR4SnNvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZGF0YScpO1xuICAgICAgcmVidWlsdFR4SnNvbi5kYXRhLnNob3VsZC5zdGFydFdpdGgoJzB4MGRjZDdhNmMnKTsgLy8gc2VuZE11bHRpU2lnVG9rZW4gZnVuY1xuXG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicpO1xuICAgICAgdHJhbnNhY3Rpb24uY29pbi5zaG91bGQuZXF1YWwoJ3Rwb2x5Z29uOmxpbmsnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb250cmFjdFNlcXVlbmNlSWQnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdleHBpcmVUaW1lJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZ2FzTGltaXQnKTtcbiAgICAgIHRyYW5zYWN0aW9uLmdhc0xpbWl0LnNob3VsZC5lcXVhbCgnNTAwMDAwJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeScpO1xuICAgICAgdHJhbnNhY3Rpb24uaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeT8uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldENvbnRyYWN0QWRkcmVzcycpO1xuICAgICAgdHJhbnNhY3Rpb24ud2FsbGV0Q29udHJhY3RBZGRyZXNzLnNob3VsZC5lcXVhbChUZXN0Qml0R28uVjIuVEVTVF9FVEhfV0FMTEVUX0ZJUlNUX0FERFJFU1MpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnKTtcbiAgICAgIGNvbnN0IHJlY2lwaWVudCA9IHRyYW5zYWN0aW9uLnJlY2lwaWVudHNbMF07XG4gICAgICByZWNpcGllbnQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkZHJlc3MnKTtcbiAgICAgIHJlY2lwaWVudC5hZGRyZXNzLnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbkFkZHJlc3MpO1xuICAgICAgcmVjaXBpZW50LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhbW91bnQnKTtcbiAgICAgIHJlY2lwaWVudC5hbW91bnQuc2hvdWxkLmVxdWFsKCc5OTk5OTk5OTk5OTk5OTk5OTI4Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGFuIHVuc2lnbmVkIHJlY292ZXJ5IHR4biBvZiBhIHRva2VuIGZvciBob3Qgd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdXNlcktleSA9XG4gICAgICAgICd7XCJpdlwiOlwiVkZaM2p2WGh4bzFaK1lhZjJNdFpuQT09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MjU2LFwidHNcIjo2NCxcIm1vZGVcIlxcbicgK1xuICAgICAgICAnOlwiY2NtXCIsXCJhZGF0YVwiOlwiXCIsXCJjaXBoZXJcIjpcImFlc1wiLFwic2FsdFwiOlwicCtma0h1TGEvOGs9XCIsXCJjdFwiOlwiaFlHN3B2bGpMSWdDalpcXG4nICtcbiAgICAgICAgJzUzUEJsQ2RlNUtaUm1sVUtLSEx0RE1rK0hKZnVVNDZoVyt4K0M5V3NJQU80Z0ZQblRDdkZWbVE4eDdjekN0Y05GdWI1QU8yb3RPR1xcbicgK1xuICAgICAgICAnT3NYNEdFMmdYT0VtQ2wxVHBXd3dOaG03eU1VakdKVXBnVzZaWmdYU1hkRGl0U0tpNFYvaGs3OFNHU3pqRk9CU1BZUmE2ST1cIn1cXG4nO1xuICAgICAgY29uc3Qgd2FsbGV0Q29udHJhY3RBZGRyZXNzID0gVGVzdEJpdEdvLlYyLlRFU1RfRVRIX1dBTExFVF9GSVJTVF9BRERSRVNTIGFzIHN0cmluZztcbiAgICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSBUZXN0Qml0R28uVjIuVEVTVF9SRUNPVkVSWV9QQVNTQ09ERSBhcyBzdHJpbmc7XG4gICAgICBjb25zdCB0b2tlbkNvbnRyYWN0QWRkcmVzcyA9ICcweDMyNmM5NzdlNmVmYzg0ZTUxMmJiOWMzMGY3NmUzMGMxNjBlZDA2ZmInOyAvLyB0cG9seWdvbi1saW5rIGNvbnRyYWN0IHRva2VuIGFkZHJlc3NcblxuICAgICAgY29uc3QgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0cG9seWdvbicpIGFzIFBvbHlnb247XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0VHhMaXN0UmVxdWVzdChiaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkobW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUb2tlbkJhbGFuY2VSZXF1ZXN0KHRva2VuQ29udHJhY3RBZGRyZXNzLCB3YWxsZXRDb250cmFjdEFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuICAgICAgbm9jayhiYXNlVXJsKS5nZXQoJy9hcGknKS5xdWVyeShtb2NrRGF0YS5nZXRDb250cmFjdENhbGxSZXF1ZXN0KS5yZXBseSgyMDAsIG1vY2tEYXRhLmdldENvbnRyYWN0Q2FsbFJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IHVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogJycsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogd2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgICBiaXRnb0ZlZUFkZHJlc3M6IGJpdGdvRmVlQWRkcmVzcyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwMDAwMDAwMDAsIG1heFByaW9yaXR5RmVlUGVyR2FzOiAxMDAwMDAwMDAwMCB9LFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzczogYml0Z29EZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiB0b2tlbkNvbnRyYWN0QWRkcmVzcyxcbiAgICAgIH0pKSBhcyBPZmZsaW5lVmF1bHRUeEluZm87XG5cbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbik7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhIZXgnKTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcigndHBvbHlnb24nKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICB0eEJ1aWxkZXIuZnJvbSh0cmFuc2FjdGlvbi50eEhleCk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeEpzb24gPSByZWJ1aWx0VHgudG9Kc29uKCk7XG4gICAgICByZWJ1aWx0VHhKc29uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdkYXRhJyk7XG4gICAgICByZWJ1aWx0VHhKc29uLmRhdGEuc2hvdWxkLnN0YXJ0V2l0aCgnMHgwZGNkN2E2YycpOyAvLyBzZW5kTXVsdGlTaWdUb2tlbiBmdW5jXG5cbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJyk7XG4gICAgICB0cmFuc2FjdGlvbi5jb2luLnNob3VsZC5lcXVhbCgndHBvbHlnb246bGluaycpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvbnRyYWN0U2VxdWVuY2VJZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ2V4cGlyZVRpbWUnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdnYXNMaW1pdCcpO1xuICAgICAgdHJhbnNhY3Rpb24uZ2FzTGltaXQuc2hvdWxkLmVxdWFsKCc1MDAwMDAnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0V2bUJhc2VkQ3Jvc3NDaGFpblJlY292ZXJ5Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5pc0V2bUJhc2VkQ3Jvc3NDaGFpblJlY292ZXJ5Py5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0Q29udHJhY3RBZGRyZXNzJyk7XG4gICAgICB0cmFuc2FjdGlvbi53YWxsZXRDb250cmFjdEFkZHJlc3Muc2hvdWxkLmVxdWFsKFRlc3RCaXRHby5WMi5URVNUX0VUSF9XQUxMRVRfRklSU1RfQUREUkVTUyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycpO1xuICAgICAgY29uc3QgcmVjaXBpZW50ID0gdHJhbnNhY3Rpb24ucmVjaXBpZW50c1swXTtcbiAgICAgIHJlY2lwaWVudC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWRkcmVzcycpO1xuICAgICAgcmVjaXBpZW50LmFkZHJlc3Muc2hvdWxkLmVxdWFsKGRlc3RpbmF0aW9uQWRkcmVzcyk7XG4gICAgICByZWNpcGllbnQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Ftb3VudCcpO1xuICAgICAgcmVjaXBpZW50LmFtb3VudC5zaG91bGQuZXF1YWwoJzk5OTk5OTk5OTk5OTk5OTk5MjgnKTtcbiAgICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVzVXNlZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uZmVlc1VzZWQ/Lmdhc0xpbWl0LnNob3VsZC5lcXVhbCgnNTAwMDAwJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaGFsZlNpZ25lZCcpO1xuICAgICAgdHJhbnNhY3Rpb24uaGFsZlNpZ25lZD8uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICB0cmFuc2FjdGlvbi5oYWxmU2lnbmVkPy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncmVjaXBpZW50cycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnTm9uLUJpdEdvIFJlY292ZXJ5IGZvciBIb3QgV2FsbGV0cyAoTVBDdjIpJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2VVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzLnRlc3QucG9seWdvbnNjYW5CYXNlVXJsIGFzIHN0cmluZztcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSByZWNvdmVyeSB0cmFuc2FjdGlvbiBmb3IgTVBDdjIga2luZCBvZiBob3Qgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRUeExpc3RSZXF1ZXN0KG1vY2tEYXRhLmdldE5vbkJpdEdvUmVjb3ZlcnlGb3JIb3RXYWxsZXRzTVBDdjIoKS5iaXRnb0ZlZUFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRUeExpc3RSZXNwb25zZSk7XG5cbiAgICAgIG5vY2soYmFzZVVybClcbiAgICAgICAgLmdldCgnL2FwaScpXG4gICAgICAgIC5xdWVyeShtb2NrRGF0YS5nZXRCYWxhbmNlUmVxdWVzdChtb2NrRGF0YS5nZXROb25CaXRHb1JlY292ZXJ5Rm9ySG90V2FsbGV0c01QQ3YyKCkuYml0Z29GZWVBZGRyZXNzKSlcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcblxuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KG1vY2tEYXRhLmdldE5vbkJpdEdvUmVjb3ZlcnlGb3JIb3RXYWxsZXRzTVBDdjIoKS53YWxsZXRDb250cmFjdEFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSBtb2NrRGF0YS5nZXROb25CaXRHb1JlY292ZXJ5Rm9ySG90V2FsbGV0c01QQ3YyKCk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gYXdhaXQgKGJhc2Vjb2luIGFzIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zKS5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogcGFyYW1zLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogcGFyYW1zLmJhY2t1cEtleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogcGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgYml0Z29GZWVBZGRyZXNzOiBwYXJhbXMuYml0Z29GZWVBZGRyZXNzLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgZWlwMTU1OTogeyBtYXhGZWVQZXJHYXM6IDIwMDAwMDAwMDAwLCBtYXhQcmlvcml0eUZlZVBlckdhczogMTAwMDAwMDAwMDAgfSxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICAgIGJpdGdvRGVzdGluYXRpb25BZGRyZXNzOiBwYXJhbXMuYml0Z29EZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7IGNoYWluOiA4MDAwMiwgaGFyZGZvcms6ICdsb25kb24nIH0sXG4gICAgICAgIGludGVuZGVkQ2hhaW46IHBhcmFtcy5pbnRlbmRlZENoYWluLFxuICAgICAgfSk7XG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24pO1xuICAgICAgdHJhbnNhY3Rpb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBmb3IgaW52YWxpZCB1c2VyIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IG1vY2tEYXRhLmdldEludmFsaWROb25CaXRHb1JlY292ZXJ5UGFyYW1zKCk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgKGJhc2Vjb2luIGFzIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zKS5yZWNvdmVyKHtcbiAgICAgICAgICAgIHVzZXJLZXk6IHBhcmFtcy51c2VyS2V5LFxuICAgICAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LFxuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgICAgICBiaXRnb0ZlZUFkZHJlc3M6IHBhcmFtcy5iaXRnb0ZlZUFkZHJlc3MsXG4gICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICAgIGVpcDE1NTk6IHsgbWF4RmVlUGVyR2FzOiAyMDAwMDAwMDAwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwMDAwMDAwIH0sXG4gICAgICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICAgICAgYml0Z29EZXN0aW5hdGlvbkFkZHJlc3M6IHBhcmFtcy5iaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcyxcbiAgICAgICAgICAgIGludGVuZGVkQ2hhaW46IHBhcmFtcy5pbnRlbmRlZENoYWluLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBFcnJvcixcbiAgICAgICAgJ3VzZXIga2V5IGlzIGludmFsaWQnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQnVpbGQgVW5zaWduZWQgU3dlZXAgZm9yIFNlbGYtQ3VzdG9keSBDb2xkIFdhbGxldHMgKE1QQ3YyKScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiYXNlVXJsID0gY29tbW9uLkVudmlyb25tZW50cy50ZXN0LnBvbHlnb25zY2FuQmFzZVVybCBhcyBzdHJpbmc7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGFuIHVuc2lnbmVkIHN3ZWVwIHdpdGhvdXQgZGVyaXZhdGlvbiBzZWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldFR4TGlzdFJlcXVlc3QobW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCkuYWRkcmVzcykpXG4gICAgICAgIC5yZXBseSgyMDAsIG1vY2tEYXRhLmdldFR4TGlzdFJlc3BvbnNlKTtcblxuICAgICAgbm9jayhiYXNlVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpJylcbiAgICAgICAgLnF1ZXJ5KG1vY2tEYXRhLmdldEJhbGFuY2VSZXF1ZXN0KG1vY2tEYXRhLmdldEJ1aWxkVW5zaWduZWRTd2VlcEZvclNlbGZDdXN0b2R5Q29sZFdhbGxldHNNUEN2MigpLmFkZHJlc3MpKVxuICAgICAgICAucmVwbHkoMjAwLCBtb2NrRGF0YS5nZXRCYWxhbmNlUmVzcG9uc2UpO1xuXG4gICAgICBub2NrKGJhc2VVcmwpXG4gICAgICAgIC5nZXQoJy9hcGknKVxuICAgICAgICAucXVlcnkoXG4gICAgICAgICAgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlcXVlc3QoXG4gICAgICAgICAgICBtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKS53YWxsZXRDb250cmFjdEFkZHJlc3NcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGEuZ2V0QmFsYW5jZVJlc3BvbnNlKTtcblxuICAgICAgY29uc3QgcGFyYW1zID0gbW9ja0RhdGEuZ2V0QnVpbGRVbnNpZ25lZFN3ZWVwRm9yU2VsZkN1c3RvZHlDb2xkV2FsbGV0c01QQ3YyKCk7XG4gICAgICBjb25zdCBzd2VlcFJlc3VsdCA9IGF3YWl0IChiYXNlY29pbiBhcyBBYnN0cmFjdEV0aExpa2VOZXdDb2lucykucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IHBhcmFtcy5jb21tb25LZXlDaGFpbixcbiAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuY29tbW9uS2V5Q2hhaW4sXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICBnYXNMaW1pdDogMjAwMDAwLFxuICAgICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogMjAwMDAwMDAwMDAsIG1heFByaW9yaXR5RmVlUGVyR2FzOiAxMDAwMDAwMDAwMCB9LFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczoge1xuICAgICAgICAgIGNoYWluOiAnMTM3JyxcbiAgICAgICAgICBoYXJkZm9yazogJ2xvbmRvbicsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHN3ZWVwUmVzdWx0KTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IHN3ZWVwUmVzdWx0IGFzIFVuc2lnbmVkU3dlZXBUeE1QQ3YyO1xuICAgICAgb3V0cHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eFJlcXVlc3RzJyk7XG4gICAgICBvdXRwdXQudHhSZXF1ZXN0cy5zaG91bGQuaGF2ZS5sZW5ndGgoMSk7XG4gICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHJhbnNhY3Rpb25zJyk7XG4gICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDEpO1xuICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3dhbGxldENvaW4nKTtcbiAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndW5zaWduZWRUeCcpO1xuICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NlcmlhbGl6ZWRUeEhleCcpO1xuICAgICAgb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hYmxlSGV4Jyk7XG4gICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZGVyaXZhdGlvblBhdGgnKTtcbiAgICAgIG91dHB1dC50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVJbmZvJyk7XG4gICAgICBvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncGFyc2VkVHgnKTtcbiAgICAgIGNvbnN0IHBhcnNlZFR4ID0gb3V0cHV0LnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHgucGFyc2VkVHggYXMgeyBzcGVuZEFtb3VudDogc3RyaW5nIH07XG4gICAgICBwYXJzZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3BlbmRBbW91bnQnKTtcbiAgICAgIChvdXRwdXQudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeCBhcyB7IG91dHB1dHM6IGFueVtdIH0pLnNob3VsZC5oYXZlLnByb3BlcnR5KCdvdXRwdXRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGZvciBpbnZhbGlkIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSBtb2NrRGF0YS5nZXRCdWlsZFVuc2lnbmVkU3dlZXBGb3JTZWxmQ3VzdG9keUNvbGRXYWxsZXRzTVBDdjIoKTtcbiAgICAgIHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uID0gJ2ludmFsaWRBZGRyZXNzJztcblxuICAgICAgcGFyYW1zLnVzZXJLZXkgPVxuICAgICAgICAnMDIzNGViMzliMjJmZWQ1MjNlY2U3Yzc4ZGEyOWJhMWYxZGU1YjY0YTZlNDgwMTNlMDkxNGRlNzkzYmMxZGYwNTcwZTc3OWRlMDQ3NTg3MzI3MzRkOTdlNTRiNzgyYzhiMzM2MjgzODExYWY2YTJjNTdiZDgxNDM4Nzk4ZTFjMjQ0Nic7XG4gICAgICBwYXJhbXMuYmFja3VwS2V5ID1cbiAgICAgICAgJzAyMzRlYjM5YjIyZmVkNTIzZWNlN2M3OGRhMjliYTFmMWRlNWI2NGE2ZTQ4MDEzZTA5MTRkZTc5M2JjMWRmMDU3MGU3NzlkZTA0NzU4NzMyNzM0ZDk3ZTU0Yjc4MmM4YjMzNjI4MzgxMWFmNmEyYzU3YmQ4MTQzODc5OGUxYzI0NDYnO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IChiYXNlY29pbiBhcyBBYnN0cmFjdEV0aExpa2VOZXdDb2lucykucmVjb3Zlcih7XG4gICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgICAgIGdhc0xpbWl0OiAyMDAwLFxuICAgICAgICAgICAgZWlwMTU1OTogeyBtYXhGZWVQZXJHYXM6IDIwMCwgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IDEwMDAwIH0sXG4gICAgICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgICAgIGJhY2t1cEtleTogcGFyYW1zLmJhY2t1cEtleSxcbiAgICAgICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogcGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyxcbiAgICAgICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgICAgICAgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgY2hhaW46ICcxMzcnLFxuICAgICAgICAgICAgICBoYXJkZm9yazogJ2xvbmRvbicsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBFcnJvcixcbiAgICAgICAgJ0Vycm9yOiBpbnZhbGlkIGFkZHJlc3MnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVGVzdCBpc1dhbGxldEFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3ZlcmlmeSBhZGRyZXNzIGZvciB0cG9seWdvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnNjkyMGMwNWUwYjE5NWFiZDhlZDBiYjBhNWRmMzJjZGMnLFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOlxuICAgICAgICAgICAgJzAyZjkyOWY5MmMyNWVhY2NiMGUzZWJhYTBmNWVkOTAwYzVhZDMwYmE5NGY4NDQ0ZGM4OWM5NGUxMmYwMWFhNTM3MTUyMmQ4MTBiODkxOGVjYzllNDFlYjkwMTM1MmRmMWM3OTc3NDIwZmJhZjliODYxN2Y2MWI3ODBiMzJiMmNjYWQnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICc2OTIwYzA1ZTkzYzNiMWM5ZTUwMDZiZjAwYTNjZjAxNicsXG4gICAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICcwMmY5MjlmOTJjMjVlYWNjYjBlM2ViYWEwZjVlZDkwMGM1YWQzMGJhOTRmODQ0NGRjODljOTRlMTJmMDFhYTUzNzE1MjJkODEwYjg5MThlY2M5ZTQxZWI5MDEzNTJkZjFjNzk3NzQyMGZiYWY5Yjg2MTdmNjFiNzgwYjMyYjJjY2FkJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnNjkyMGMwNWQ5ZWJlZTAxMDBlYzRhOGFhN2UzMDBjMDInLFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjpcbiAgICAgICAgICAgICcwMmY5MjlmOTJjMjVlYWNjYjBlM2ViYWEwZjVlZDkwMGM1YWQzMGJhOTRmODQ0NGRjODljOTRlMTJmMDFhYTUzNzE1MjJkODEwYjg5MThlY2M5ZTQxZWI5MDEzNTJkZjFjNzk3NzQyMGZiYWY5Yjg2MTdmNjFiNzgwYjMyYjJjY2FkJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgYWRkcmVzczogJzB4NGU5ZmM0NDY5N2Y0MTM1NDU1MTU3Mzk2NDg1ZjZmZThmOTA5NzUyZicsXG4gICAgICAgIGJhc2VBZGRyZXNzOiAnMHg4Y2Y1ZWJkNTE1ODVkMTU5YzRhMWNhMzYxNzhmOWFkMGZkN2E1OTRjJyxcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgc2FsdDogJzB4ZCcsXG4gICAgICAgICAgZm9yd2FyZGVyVmVyc2lvbjogNCxcbiAgICAgICAgICBmZWVBZGRyZXNzOiAnMHg0NGRjYjM1MDRlMzIzYTNkNzAxNDIwMzZhOTllMmQ0YmJhM2YyMjcwJyxcbiAgICAgICAgfSxcbiAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICBpbmRleDogMTMsXG4gICAgICAgIHdhbGxldFZlcnNpb246IDUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBjb2luID0gYml0Z28uY29pbigndHBvbHlnb24nKTtcbiAgICAgIGNvbnN0IGlzV2FsbGV0QWRkciA9IGF3YWl0IGNvaW4uaXNXYWxsZXRBZGRyZXNzKHBhcmFtcyk7XG4gICAgICBpc1dhbGxldEFkZHIuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|