@bitgo-beta/sdk-coin-hbar 2.0.73-alpha.13 → 2.0.73-alpha.131

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.
Files changed (50) hide show
  1. package/dist/src/hbar.d.ts +20 -3
  2. package/dist/src/hbar.d.ts.map +1 -1
  3. package/dist/src/hbar.js +183 -6
  4. package/dist/src/lib/index.d.ts +1 -0
  5. package/dist/src/lib/index.d.ts.map +1 -1
  6. package/dist/src/lib/index.js +1 -1
  7. package/dist/test/fixtures/hbar.d.ts +6 -0
  8. package/dist/test/fixtures/hbar.d.ts.map +1 -0
  9. package/dist/test/fixtures/hbar.js +9 -0
  10. package/dist/test/resources/hbar.d.ts +67 -0
  11. package/dist/test/resources/hbar.d.ts.map +1 -0
  12. package/dist/test/resources/hbar.js +73 -0
  13. package/dist/test/unit/fixtures/hbarBackupKey.d.ts +4 -0
  14. package/dist/test/unit/fixtures/hbarBackupKey.d.ts.map +1 -0
  15. package/dist/test/unit/fixtures/hbarBackupKey.js +10 -0
  16. package/dist/test/unit/getBuilderFactory.d.ts +3 -0
  17. package/dist/test/unit/getBuilderFactory.d.ts.map +1 -0
  18. package/dist/test/unit/getBuilderFactory.js +10 -0
  19. package/dist/test/unit/hbar.d.ts +2 -0
  20. package/dist/test/unit/hbar.d.ts.map +1 -0
  21. package/dist/test/unit/hbar.js +1437 -0
  22. package/dist/test/unit/hbarToken.d.ts +2 -0
  23. package/dist/test/unit/hbarToken.d.ts.map +1 -0
  24. package/dist/test/unit/hbarToken.js +34 -0
  25. package/dist/test/unit/keyPair.d.ts +2 -0
  26. package/dist/test/unit/keyPair.d.ts.map +1 -0
  27. package/dist/test/unit/keyPair.js +179 -0
  28. package/dist/test/unit/transaction.d.ts +2 -0
  29. package/dist/test/unit/transaction.d.ts.map +1 -0
  30. package/dist/test/unit/transaction.js +94 -0
  31. package/dist/test/unit/transactionBuilder/tokenAssociateBuilder.d.ts +2 -0
  32. package/dist/test/unit/transactionBuilder/tokenAssociateBuilder.d.ts.map +1 -0
  33. package/dist/test/unit/transactionBuilder/tokenAssociateBuilder.js +215 -0
  34. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
  35. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
  36. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +329 -0
  37. package/dist/test/unit/transactionBuilder/transferBuilder.d.ts +2 -0
  38. package/dist/test/unit/transactionBuilder/transferBuilder.d.ts.map +1 -0
  39. package/dist/test/unit/transactionBuilder/transferBuilder.js +353 -0
  40. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +2 -0
  41. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
  42. package/dist/test/unit/transactionBuilder/walletInitialization.js +214 -0
  43. package/dist/test/unit/utils.d.ts +2 -0
  44. package/dist/test/unit/utils.d.ts.map +1 -0
  45. package/dist/test/unit/utils.js +275 -0
  46. package/dist/tsconfig.tsbuildinfo +1 -0
  47. package/package.json +13 -10
  48. package/.eslintignore +0 -5
  49. package/.mocharc.yml +0 -8
  50. package/CHANGELOG.md +0 -743
@@ -0,0 +1,1437 @@
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 assert_1 = __importDefault(require("assert"));
40
+ const _ = __importStar(require("lodash"));
41
+ const nock_1 = __importDefault(require("nock"));
42
+ const sinon_1 = __importDefault(require("sinon"));
43
+ const crypto_1 = require("crypto");
44
+ const bignumber_js_1 = require("bignumber.js");
45
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
46
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
47
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
48
+ const TestData = __importStar(require("../fixtures/hbar"));
49
+ const src_1 = require("../../src");
50
+ const getBuilderFactory_1 = require("./getBuilderFactory");
51
+ const hbarBackupKey_1 = require("./fixtures/hbarBackupKey");
52
+ describe('Hedera Hashgraph:', function () {
53
+ let bitgo;
54
+ let basecoin;
55
+ let token;
56
+ before(function () {
57
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
58
+ bitgo.safeRegister('thbar', src_1.Thbar.createInstance);
59
+ bitgo.safeRegister('hbar', src_1.Hbar.createInstance);
60
+ src_1.HbarToken.createTokenConstructors().forEach(({ name, coinConstructor }) => {
61
+ bitgo.safeRegister(name, coinConstructor);
62
+ });
63
+ bitgo.initializeTestVars();
64
+ basecoin = bitgo.coin('thbar');
65
+ token = bitgo.coin('thbar:usdc');
66
+ });
67
+ it('should instantiate the coin', function () {
68
+ const basecoin = bitgo.coin('hbar');
69
+ basecoin.should.be.an.instanceof(src_1.Hbar);
70
+ });
71
+ it('should check valid addresses', async function () {
72
+ const badAddresses = [
73
+ '',
74
+ '0.0',
75
+ 'YZ09fd-',
76
+ '0.0.0.a',
77
+ 'sadasdfggg',
78
+ '0.2.a.b',
79
+ '0.0.100?=sksjd',
80
+ '0.0.41098?memoId=',
81
+ ];
82
+ const goodAddresses = [
83
+ '0',
84
+ '0.0.0',
85
+ '0.0.41098',
86
+ '0.0.0?memoId=84',
87
+ '0.0.41098',
88
+ '0.0.41098?memoId=2aaaaa',
89
+ '0.0.41098?memoId=1',
90
+ ];
91
+ badAddresses.map((addr) => {
92
+ basecoin.isValidAddress(addr).should.equal(false);
93
+ });
94
+ goodAddresses.map((addr) => {
95
+ basecoin.isValidAddress(addr).should.equal(true);
96
+ });
97
+ const hexAddress = '0x23C3E227BE97281A70A549c7dDB8d5Caad3E7C84';
98
+ basecoin.isValidAddress(hexAddress).should.equal(false);
99
+ });
100
+ it('should explain a transaction', async function () {
101
+ const tx = JSON.parse(TestData.rawTransactionForExplain);
102
+ const explain = await basecoin.explainTransaction(tx);
103
+ explain.id.should.equal('0.0.43285@1600529800.643093586');
104
+ explain.outputAmount.should.equal('2200000000');
105
+ explain.timestamp.should.equal('1600529800.643093586');
106
+ explain.expiration.should.equal('180');
107
+ explain.outputs[0].amount.should.equal('2200000000');
108
+ explain.outputs[0].address.should.equal('0.0.43283');
109
+ explain.outputs[0].memo.should.equal('1');
110
+ explain.fee.should.equal(1160407);
111
+ explain.changeAmount.should.equal('0');
112
+ });
113
+ it('should explain a token transfer transaction', async function () {
114
+ const tokenTransferParam = {
115
+ txHex: TestData.UNSIGNED_TOKEN_TRANSFER,
116
+ feeInfo: {
117
+ size: 1000,
118
+ fee: 1160407,
119
+ feeRate: 1160407,
120
+ },
121
+ };
122
+ const explain = await basecoin.explainTransaction(tokenTransferParam);
123
+ explain.id.should.equal('0.0.81320@1596110493.372646570');
124
+ explain.outputAmount.should.equal('0');
125
+ explain.timestamp.should.equal('1596110493.372646570');
126
+ explain.expiration.should.equal('180');
127
+ explain.outputs[0].amount.should.equal('10');
128
+ explain.outputs[0].address.should.equal('0.0.75861');
129
+ explain.outputs[0].memo.should.equal('');
130
+ explain.outputs[0].tokenName.should.equal('thbar:usdc');
131
+ explain.fee.should.equal(1160407);
132
+ explain.changeAmount.should.equal('0');
133
+ });
134
+ it('should explain a multirecipients transfer transaction', async function () {
135
+ const multiTransferParam = {
136
+ txHex: TestData.UNSIGNED_MULTI_TRANSFER,
137
+ feeInfo: {
138
+ size: 1000,
139
+ fee: 1160407,
140
+ feeRate: 1160407,
141
+ },
142
+ };
143
+ const explain = await basecoin.explainTransaction(multiTransferParam);
144
+ explain.id.should.equal('0.0.81320@1596110493.372646570');
145
+ explain.outputAmount.should.equal('25');
146
+ explain.expiration.should.equal('180');
147
+ explain.outputs[0].amount.should.equal('10');
148
+ explain.outputs[0].address.should.equal('0.0.75861');
149
+ explain.outputs[0].memo.should.equal('');
150
+ explain.outputs[1].amount.should.equal('15');
151
+ explain.outputs[1].address.should.equal('0.0.78963');
152
+ explain.fee.should.equal(1160407);
153
+ explain.changeAmount.should.equal('0');
154
+ });
155
+ it('should explain a multirecipients token transfer transaction', async function () {
156
+ const tokenMultiTransferParam = {
157
+ txHex: TestData.UNSIGNED_TOKEN_MULTI_TRANSFER,
158
+ feeInfo: {
159
+ size: 1000,
160
+ fee: 1160407,
161
+ feeRate: 1160407,
162
+ },
163
+ };
164
+ const explain = await basecoin.explainTransaction(tokenMultiTransferParam);
165
+ explain.id.should.equal('0.0.81320@1596110493.372646570');
166
+ explain.outputAmount.should.equal('0');
167
+ explain.timestamp.should.equal('1596110493.372646570');
168
+ explain.expiration.should.equal('180');
169
+ explain.outputs[0].amount.should.equal('10');
170
+ explain.outputs[0].address.should.equal('0.0.75861');
171
+ explain.outputs[0].memo.should.equal('');
172
+ explain.outputs[0].tokenName.should.equal('thbar:usdc');
173
+ explain.outputs[1].amount.should.equal('15');
174
+ explain.outputs[1].address.should.equal('0.0.78963');
175
+ explain.outputs[1].tokenName.should.equal('thbar:usdc');
176
+ explain.fee.should.equal(1160407);
177
+ explain.changeAmount.should.equal('0');
178
+ });
179
+ it('should explain a token associate transaction', async function () {
180
+ const tokenAssociateParam = {
181
+ txHex: TestData.UNSIGNED_TOKEN_ASSOCIATE,
182
+ feeInfo: {
183
+ size: 1000,
184
+ fee: 1160407,
185
+ feeRate: 1160407,
186
+ },
187
+ };
188
+ const explain = await basecoin.explainTransaction(tokenAssociateParam);
189
+ explain.id.should.equal('0.0.81320@1596110493.372646570');
190
+ explain.outputAmount.should.equal('0');
191
+ explain.timestamp.should.equal('1596110493.372646570');
192
+ explain.expiration.should.equal('180');
193
+ explain.outputs[0].amount.should.equal('0');
194
+ explain.outputs[0].address.should.equal('0.0.81320');
195
+ explain.outputs[0].memo.should.equal('');
196
+ explain.outputs[0].tokenName.should.equal('thbar:usdc');
197
+ explain.fee.should.equal(1160407);
198
+ explain.changeAmount.should.equal('0');
199
+ });
200
+ it('should verify isWalletAddress', async function () {
201
+ const baseAddress = '0.0.41098';
202
+ const validAddress1 = '0.0.41098?memoId=1';
203
+ const validAddress2 = '0.0.41098?memoId=2';
204
+ const unrelatedValidAddress = '0.1.41098?memoId=1';
205
+ const invalidAddress = '0.0.0.a';
206
+ (await basecoin.isWalletAddress({ address: validAddress1, baseAddress })).should.true();
207
+ (await basecoin.isWalletAddress({ address: validAddress2, baseAddress })).should.true();
208
+ (await basecoin.isWalletAddress({ address: validAddress2, baseAddress: validAddress1 })).should.true();
209
+ (await basecoin.isWalletAddress({ address: unrelatedValidAddress, baseAddress })).should.false();
210
+ assert_1.default.rejects(async () => basecoin.isWalletAddress({ address: invalidAddress, baseAddress }), `invalid address ${invalidAddress}`);
211
+ });
212
+ describe('Keypairs:', () => {
213
+ it('should generate a keypair from random seed', function () {
214
+ const keyPair = basecoin.generateKeyPair();
215
+ keyPair.should.have.property('pub');
216
+ keyPair.should.have.property('prv');
217
+ basecoin.isValidPub(keyPair.pub).should.equal(true);
218
+ });
219
+ it('should generate a keypair from a seed', function () {
220
+ const seedText = '80350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f';
221
+ const seed = Buffer.from(seedText, 'hex');
222
+ const keyPair = basecoin.generateKeyPair(seed);
223
+ keyPair.prv.should.equal('302e020100300506032b65700422042080350b4208d381fbfe2276a326603049fe500731c46d3c9936b5ce036b51377f');
224
+ keyPair.pub.should.equal('302a300506032b65700321009cc402b5c75214269c2826e3c6119377cab6c367601338661c87a4e07c6e0333');
225
+ });
226
+ it('should validate a stellar seed', function () {
227
+ basecoin.isStellarSeed('SBMWLNV75BPI2VB4G27RWOMABVRTSSF7352CCYGVELZDSHCXWCYFKXIX').should.ok();
228
+ });
229
+ it('should convert a stellar seed to an hbar prv', function () {
230
+ const seed = basecoin.convertFromStellarSeed('SBMWLNV75BPI2VB4G27RWOMABVRTSSF7352CCYGVELZDSHCXWCYFKXIX');
231
+ seed.should.equal('302e020100300506032b6570042204205965b6bfe85e8d543c36bf1b39800d633948bfdf742160d522f2391c57b0b055');
232
+ });
233
+ });
234
+ describe('Verify Transaction:', () => {
235
+ let newTxPrebuild;
236
+ let newTxParams;
237
+ let newTxParamsWithError;
238
+ let newTxParamsWithExtraData;
239
+ const txPrebuild = {
240
+ recipients: [
241
+ {
242
+ address: 'lionteste212',
243
+ amount: '1000',
244
+ },
245
+ ],
246
+ txHex: TestData.UNSIGNED_MULTI_TRANSFER,
247
+ txid: '586c5b59b10b134d04c16ac1b273fe3c5529f34aef75db4456cd469c5cdac7e2',
248
+ isVotingTransaction: false,
249
+ coin: 'thbar',
250
+ feeInfo: {
251
+ size: 1000,
252
+ fee: 1160407,
253
+ feeRate: 1160407,
254
+ },
255
+ };
256
+ const txParams = {
257
+ txPrebuild,
258
+ recipients: [
259
+ {
260
+ address: '0.0.75861',
261
+ amount: '10',
262
+ },
263
+ {
264
+ address: '0.0.78963',
265
+ amount: '15',
266
+ },
267
+ ],
268
+ };
269
+ const memo = { value: '' };
270
+ const txParamsWithError = {
271
+ txPrebuild,
272
+ recipients: [
273
+ {
274
+ address: '0.0.75861',
275
+ amount: '1000',
276
+ },
277
+ ],
278
+ };
279
+ const txParamsWithExtraData = {
280
+ txPrebuild,
281
+ recipients: [
282
+ {
283
+ address: '0.0.75861',
284
+ amount: '10',
285
+ data: undefined,
286
+ },
287
+ {
288
+ address: '0.0.78963',
289
+ amount: '15',
290
+ data: undefined,
291
+ },
292
+ ],
293
+ };
294
+ const walletData = {
295
+ id: '5b34252f1bf349930e34020a00000000',
296
+ coin: 'thbar',
297
+ keys: [
298
+ '5b3424f91bf349930e34017500000000',
299
+ '5b3424f91bf349930e34017600000000',
300
+ '5b3424f91bf349930e34017700000000',
301
+ ],
302
+ coinSpecific: {
303
+ baseAddress: '0.0.2935',
304
+ },
305
+ multisigType: 'onchain',
306
+ };
307
+ const walletObj = new sdk_core_1.Wallet(bitgo, basecoin, walletData);
308
+ before(function () {
309
+ newTxPrebuild = () => {
310
+ return _.cloneDeep(txPrebuild);
311
+ };
312
+ newTxParams = () => {
313
+ return _.cloneDeep(txParams);
314
+ };
315
+ newTxParamsWithError = () => {
316
+ return _.cloneDeep(txParamsWithError);
317
+ };
318
+ newTxParamsWithExtraData = () => {
319
+ return _.cloneDeep(txParamsWithExtraData);
320
+ };
321
+ });
322
+ it('should verify native transfer transactions', async function () {
323
+ const txParams = newTxParams();
324
+ const txPrebuild = newTxPrebuild();
325
+ const validTransaction = await basecoin.verifyTransaction({
326
+ txParams,
327
+ txPrebuild,
328
+ memo,
329
+ wallet: walletObj,
330
+ });
331
+ validTransaction.should.equal(true);
332
+ });
333
+ it('should fail verify when input `recipients` is absent', async function () {
334
+ const txParams = newTxParams();
335
+ txParams.recipients = undefined;
336
+ const txPrebuild = newTxPrebuild();
337
+ await basecoin
338
+ .verifyTransaction({ txParams, txPrebuild, memo: memo, wallet: walletObj })
339
+ .should.be.rejectedWith('missing required tx params property recipients');
340
+ });
341
+ it('should fail verify transactions when have different recipients', async function () {
342
+ const txParams = newTxParamsWithError();
343
+ const txPrebuild = newTxPrebuild();
344
+ await basecoin
345
+ .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
346
+ .should.be.rejectedWith('Tx outputs does not match with expected txParams recipients');
347
+ });
348
+ it('should succeed to verify transactions when recipients has extra data', async function () {
349
+ const txParams = newTxParamsWithExtraData();
350
+ const txPrebuild = newTxPrebuild();
351
+ const validTransaction = await basecoin.verifyTransaction({
352
+ txParams,
353
+ txPrebuild,
354
+ memo,
355
+ wallet: walletObj,
356
+ });
357
+ validTransaction.should.equal(true);
358
+ });
359
+ it('should verify create associated token account transaction', async function () {
360
+ const txParams = newTxParams();
361
+ const txPrebuild = newTxPrebuild();
362
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
363
+ txParams.type = 'enabletoken';
364
+ txParams.recipients = [
365
+ {
366
+ address: '0.0.81320',
367
+ amount: '0',
368
+ tokenName: 'thbar:usdc',
369
+ },
370
+ ];
371
+ const validTransaction = await basecoin.verifyTransaction({
372
+ txParams,
373
+ txPrebuild,
374
+ memo,
375
+ wallet: walletObj,
376
+ verification: { verifyTokenEnablement: true },
377
+ });
378
+ validTransaction.should.equal(true);
379
+ });
380
+ it('should fail verify create associated token account transaction with mismatch recipients', async function () {
381
+ const txParams = newTxParams();
382
+ const txPrebuild = newTxPrebuild();
383
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
384
+ txParams.type = 'enabletoken';
385
+ txParams.recipients = [
386
+ {
387
+ address: '0.0.81321',
388
+ amount: '0',
389
+ tokenName: 'thbar:usdc',
390
+ },
391
+ ];
392
+ await basecoin
393
+ .verifyTransaction({
394
+ txParams,
395
+ txPrebuild,
396
+ memo,
397
+ wallet: walletObj,
398
+ verification: { verifyTokenEnablement: true },
399
+ })
400
+ .should.be.rejectedWith('Invalid token enablement transaction: Expected account 0.0.81321, got 0.0.81320');
401
+ });
402
+ it('should verify token transfer transaction', async function () {
403
+ const txParams = newTxParams();
404
+ const txPrebuild = newTxPrebuild();
405
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
406
+ txParams.recipients = [
407
+ {
408
+ address: '0.0.75861',
409
+ amount: '10',
410
+ tokenName: 'thbar:usdc',
411
+ },
412
+ {
413
+ address: '0.0.78963',
414
+ amount: '15',
415
+ tokenName: 'thbar:usdc',
416
+ },
417
+ ];
418
+ const validTransaction = await token.verifyTransaction({
419
+ txParams,
420
+ txPrebuild,
421
+ memo,
422
+ wallet: walletObj,
423
+ });
424
+ validTransaction.should.equal(true);
425
+ });
426
+ it('should verify token transfer transaction with any token name on token base coin', async function () {
427
+ const txParams = newTxParams();
428
+ const txPrebuild = newTxPrebuild();
429
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
430
+ txParams.recipients = [
431
+ {
432
+ address: '0.0.75861',
433
+ amount: '10',
434
+ tokenName: 'thbar:usdc',
435
+ },
436
+ {
437
+ address: '0.0.78963',
438
+ amount: '15',
439
+ },
440
+ ];
441
+ (await token.verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })).should.equal(true);
442
+ });
443
+ it('should fail to verify token transfer with mismatched recipients', async function () {
444
+ const txParams = newTxParams();
445
+ const txPrebuild = newTxPrebuild();
446
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
447
+ txParams.recipients = [
448
+ {
449
+ address: '0.0.75861',
450
+ amount: '11',
451
+ tokenName: 'thbar:usdc',
452
+ },
453
+ {
454
+ address: '0.0.78963',
455
+ amount: '15',
456
+ },
457
+ ];
458
+ await token
459
+ .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
460
+ .should.be.rejectedWith('Tx outputs does not match with expected txParams recipients');
461
+ });
462
+ it('should fail to verify token transfer with incorrect token name', async function () {
463
+ const txParams = newTxParams();
464
+ const txPrebuild = newTxPrebuild();
465
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_MULTI_TRANSFER;
466
+ txParams.recipients = [
467
+ {
468
+ address: '0.0.75861',
469
+ amount: '11',
470
+ tokenName: 'thbar:usdc',
471
+ },
472
+ {
473
+ address: '0.0.78963',
474
+ amount: '15',
475
+ tokenName: 'invalidtoken',
476
+ },
477
+ ];
478
+ await token
479
+ .verifyTransaction({ txParams, txPrebuild, memo, wallet: walletObj })
480
+ .should.be.rejectedWith('Incorrect token name specified in recipients');
481
+ });
482
+ it('should success to verify transfer having address with memo id', async function () {
483
+ const txParams = newTxParams();
484
+ const txPrebuild = newTxPrebuild();
485
+ txPrebuild.txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
486
+ txParams.type = 'enabletoken';
487
+ txParams.recipients = [
488
+ {
489
+ address: '0.0.81320?memoId=1',
490
+ amount: '0',
491
+ tokenName: 'thbar:usdc',
492
+ },
493
+ ];
494
+ const validTransaction = await basecoin.verifyTransaction({
495
+ txParams,
496
+ txPrebuild,
497
+ memo,
498
+ wallet: walletObj,
499
+ verification: { verifyTokenEnablement: true },
500
+ });
501
+ validTransaction.should.equal(true);
502
+ });
503
+ });
504
+ describe('Verify Token Enablement Transaction:', () => {
505
+ it('should verify a valid token enablement transaction with tokenName', async function () {
506
+ const txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
507
+ const expectedToken = { tokenName: 'thbar:usdc' };
508
+ const expectedAccountId = '0.0.81320';
509
+ await basecoin.verifyTokenEnablementTransaction(txHex, expectedToken, expectedAccountId);
510
+ });
511
+ it('should verify a valid token enablement transaction with tokenId', async function () {
512
+ const txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
513
+ const expectedToken = { tokenId: '0.0.429274' }; // Actual tokenId for thbar:usdc
514
+ const expectedAccountId = '0.0.81320';
515
+ await basecoin.verifyTokenEnablementTransaction(txHex, expectedToken, expectedAccountId);
516
+ });
517
+ it('should fail when txHex is missing', async function () {
518
+ await basecoin
519
+ .verifyTokenEnablementTransaction('', { tokenName: 'thbar:usdc' }, '0.0.81320')
520
+ .should.be.rejectedWith('Missing required parameters: txHex');
521
+ });
522
+ it('should fail when expectedAccountId is missing', async function () {
523
+ await basecoin
524
+ .verifyTokenEnablementTransaction(TestData.UNSIGNED_TOKEN_ASSOCIATE, { tokenName: 'thbar:usdc' }, '')
525
+ .should.be.rejectedWith('Missing required parameters: expectedAccountId');
526
+ });
527
+ it('should fail when wallet platform sends spoofed transaction hex for token enablement', async function () {
528
+ // Create a valid transaction response structure from wallet platform with spoofed txHex
529
+ // The txHex looks like valid hex but contains malicious/invalid transaction data
530
+ const spoofedTxHex = '0a0c0a080800100018a8fb0410130a0c0a080800100018d5d0041014'; // Valid hex but invalid transaction
531
+ // Mock the API endpoints that will be called during token enablement
532
+ const bgUrl = sdk_core_1.common.Environments['mock'].uri;
533
+ // Mock the key endpoint needed for signing
534
+ (0, nock_1.default)(bgUrl)
535
+ .post('/api/v2/thbar/key/5b3424f91bf34993006eae94')
536
+ .reply(200, [
537
+ {
538
+ encryptedPrv: 'fakePrv',
539
+ },
540
+ ]);
541
+ // Mock the prebuild API response to return spoofed txHex
542
+ (0, nock_1.default)(bgUrl)
543
+ .post('/api/v2/thbar/wallet/5b34252f1bf34993006eae96/tx/build')
544
+ .reply(200, {
545
+ txHex: spoofedTxHex,
546
+ txid: '586c5b59b10b134d04c16ac1b273fe3c5529f34aef75db4456cd469c5cdac7e2',
547
+ recipients: [
548
+ {
549
+ address: '0.0.81320',
550
+ amount: '0', // Valid amount for token enablement
551
+ },
552
+ ],
553
+ coin: 'thbar',
554
+ feeInfo: {
555
+ size: 1000,
556
+ fee: 1160407,
557
+ feeRate: 1160407,
558
+ },
559
+ });
560
+ // This should fail because the spoofed transaction hex contains invalid transaction data
561
+ // The verification logic should catch this when trying to validate the transaction
562
+ await assert_1.default.rejects(async () => {
563
+ // Test the verification directly instead of going through the wallet flow
564
+ await basecoin.verifyTokenEnablementTransaction(spoofedTxHex, { tokenName: 'thbar:usdc' }, '0.0.81320');
565
+ }, (error) => {
566
+ // The error should indicate that the transaction is invalid
567
+ return error.message.includes('Invalid token enablement transaction');
568
+ });
569
+ });
570
+ it('should fail when both tokenId and tokenName are missing', async function () {
571
+ await basecoin
572
+ .verifyTokenEnablementTransaction(TestData.UNSIGNED_TOKEN_ASSOCIATE, {}, '0.0.81320')
573
+ .should.be.rejectedWith('Missing required parameters: expectedToken.tokenId|tokenName');
574
+ });
575
+ it('should fail when token name does not match', async function () {
576
+ await basecoin
577
+ .verifyTokenEnablementTransaction(TestData.UNSIGNED_TOKEN_ASSOCIATE, { tokenName: 'thbar:wrongtoken' }, '0.0.81320')
578
+ .should.be.rejectedWith(/Expected token name thbar:wrongtoken, got thbar:usdc/);
579
+ });
580
+ it('should fail when account ID does not match', async function () {
581
+ await basecoin
582
+ .verifyTokenEnablementTransaction(TestData.UNSIGNED_TOKEN_ASSOCIATE, { tokenName: 'thbar:usdc' }, '0.0.99999')
583
+ .should.be.rejectedWith(/Expected account 0.0.99999, got 0.0.81320/);
584
+ });
585
+ it('should fail when transaction is not a token enablement (has non-zero amount)', async function () {
586
+ // Use a regular transfer transaction which has non-zero amount
587
+ await basecoin
588
+ .verifyTokenEnablementTransaction(TestData.UNSIGNED_TOKEN_TRANSFER, { tokenName: 'thbar:usdc' }, '0.0.81320')
589
+ .should.be.rejectedWith(/Expected output amount '0'/);
590
+ });
591
+ it('should fail when transaction type is not tokenAssociate', async function () {
592
+ // Use a regular transfer transaction which is not tokenAssociate
593
+ // This will fail on amount validation first, but that's expected behavior
594
+ await basecoin
595
+ .verifyTokenEnablementTransaction(TestData.UNSIGNED_TOKEN_TRANSFER, { tokenName: 'thbar:usdc' }, '0.0.81320')
596
+ .should.be.rejectedWith(/Expected output amount '0'/);
597
+ });
598
+ it('should validate transaction type for valid token associate transaction', async function () {
599
+ // This test ensures the transaction type validation works for valid token associate transactions
600
+ const txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
601
+ const expectedToken = { tokenName: 'thbar:usdc' };
602
+ const expectedAccountId = '0.0.81320';
603
+ await basecoin.verifyTokenEnablementTransaction(txHex, expectedToken, expectedAccountId);
604
+ });
605
+ it('should fail with invalid transaction hex', async function () {
606
+ await basecoin
607
+ .verifyTokenEnablementTransaction('invalid_hex', { tokenName: 'thbar:usdc' }, '0.0.81320')
608
+ .should.be.rejectedWith(/Invalid token enablement transaction/);
609
+ });
610
+ it('should fail when txHex contains wrong tokenId compared to expected', async function () {
611
+ // This test ensures direct txHex validation catches spoofed tokenIds
612
+ const txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
613
+ const wrongTokenId = '0.0.999999'; // Wrong tokenId
614
+ const expectedAccountId = '0.0.81320';
615
+ await basecoin
616
+ .verifyTokenEnablementTransaction(txHex, { tokenId: wrongTokenId }, expectedAccountId)
617
+ .should.be.rejectedWith(new RegExp(`Expected tokenId ${_.escapeRegExp(wrongTokenId)}, but transaction contains tokenId`));
618
+ });
619
+ it('should fail when txHex contains wrong accountId compared to expected', async function () {
620
+ // This test ensures direct txHex validation catches spoofed accountIds
621
+ const txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
622
+ const expectedToken = { tokenName: 'thbar:usdc' };
623
+ const wrongAccountId = '0.0.999999'; // Wrong accountId
624
+ await basecoin
625
+ .verifyTokenEnablementTransaction(txHex, expectedToken, wrongAccountId)
626
+ .should.be.rejectedWith(new RegExp(`Expected account ${_.escapeRegExp(wrongAccountId)}, got`));
627
+ });
628
+ it('should pass verification for valid token enablement transaction without throwing error', async function () {
629
+ // This test ensures that a valid token enablement transaction passes all validations
630
+ const txHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
631
+ const expectedToken = { tokenName: 'thbar:usdc' };
632
+ const expectedAccountId = '0.0.81320';
633
+ // This should complete without throwing any errors
634
+ await basecoin.verifyTokenEnablementTransaction(txHex, expectedToken, expectedAccountId);
635
+ // If we reach this point, the test passed
636
+ assert_1.default.ok(true, 'Valid token enablement transaction should not throw any errors');
637
+ });
638
+ it('should successfully complete sendTokenEnablements with valid transaction response from wallet platform', async function () {
639
+ const validTxHex = TestData.UNSIGNED_TOKEN_ASSOCIATE;
640
+ const wallet = {
641
+ id: () => '5b34252f1bf34993006eae96',
642
+ coin: () => 'thbar',
643
+ prebuildTransaction: async () => ({
644
+ txHex: validTxHex, // Valid token associate transaction
645
+ txid: '586c5b59b10b134d04c16ac1b273fe3c5529f34aef75db4456cd469c5cdac7e2',
646
+ recipients: [{ address: '0.0.81320', amount: '0' }],
647
+ coin: 'thbar',
648
+ feeInfo: { size: 1000, fee: 1160407, feeRate: 1160407 },
649
+ }),
650
+ sendTokenEnablements: async (params) => {
651
+ const txPrebuild = await wallet.prebuildTransaction();
652
+ await basecoin.verifyTransaction({
653
+ txParams: {
654
+ type: 'enabletoken',
655
+ recipients: [{ address: '0.0.81320', amount: '0', tokenName: 'thbar:usdc' }],
656
+ },
657
+ txPrebuild,
658
+ verification: { verifyTokenEnablement: true },
659
+ });
660
+ return {
661
+ success: [{ txid: txPrebuild.txid, status: 'success' }],
662
+ failure: [],
663
+ };
664
+ },
665
+ };
666
+ await wallet.sendTokenEnablements({
667
+ recipients: [{ address: '0.0.81320', tokenName: 'thbar:usdc' }],
668
+ });
669
+ assert_1.default.ok(true, 'Valid token enablement transaction should complete successfully through sendTokenEnablements flow');
670
+ });
671
+ it('should detect spoofed transaction hex through sendTokenEnablements flow', async function () {
672
+ // Use a valid transfer transaction hex instead of a token associate transaction
673
+ // This will parse correctly but fail validation because it's not a token associate transaction
674
+ const spoofedTxHex = TestData.UNSIGNED_TOKEN_TRANSFER; // Valid transfer transaction, not token associate
675
+ // Create a wallet mock for the sendTokenEnablements flow
676
+ const wallet = {
677
+ id: () => '5b34252f1bf34993006eae96',
678
+ coin: () => 'thbar',
679
+ prebuildTransaction: async () => ({
680
+ txHex: spoofedTxHex,
681
+ txid: '586c5b59b10b134d04c16ac1b273fe3c5529f34aef75db4456cd469c5cdac7e2',
682
+ recipients: [{ address: '0.0.81320', amount: '0' }],
683
+ coin: 'thbar',
684
+ feeInfo: { size: 1000, fee: 1160407, feeRate: 1160407 },
685
+ }),
686
+ sendTokenEnablements: async (params) => {
687
+ // This should trigger the verification and fail
688
+ const txPrebuild = await wallet.prebuildTransaction();
689
+ return basecoin.verifyTransaction({
690
+ txParams: {
691
+ type: 'enabletoken',
692
+ recipients: [{ address: '0.0.81320', amount: '0', tokenName: 'thbar:usdc' }],
693
+ },
694
+ txPrebuild,
695
+ verification: { verifyTokenEnablement: true },
696
+ });
697
+ },
698
+ };
699
+ // This should fail because the spoofed transaction hex contains a transfer transaction, not a token associate
700
+ await assert_1.default.rejects(async () => {
701
+ await wallet.sendTokenEnablements({
702
+ recipients: [{ address: '0.0.81320', tokenName: 'thbar:usdc' }],
703
+ });
704
+ }, (error) => {
705
+ // The error should indicate that the transaction is invalid for token enablement
706
+ return (error.message.includes('Invalid token enablement transaction') ||
707
+ error.message.includes('Token enablement transaction missing tokenId') ||
708
+ error.message.includes("Expected output amount '0'") ||
709
+ error.message.includes('Transaction is not a TokenAssociate transaction'));
710
+ });
711
+ });
712
+ });
713
+ describe('Sign Message', () => {
714
+ it('should be performed', async () => {
715
+ const keyPair = new src_1.KeyPair();
716
+ const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
717
+ const signature = await basecoin.signMessage(keyPair.getKeys(), messageToSign);
718
+ keyPair.verifySignature(messageToSign, Uint8Array.from(Buffer.from(signature, 'hex'))).should.equals(true);
719
+ });
720
+ it('should fail with missing private key', async () => {
721
+ const keyPair = new src_1.KeyPair({
722
+ pub: '302a300506032b6570032100d8fd745361df270776a3ab1b55d5590ec00a26ab45eea37197dc9894a81fcb82',
723
+ }).getKeys();
724
+ const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
725
+ await basecoin.signMessage(keyPair, messageToSign).should.be.rejectedWith('Invalid key pair options');
726
+ });
727
+ });
728
+ describe('Sign transaction:', () => {
729
+ const destination = '0.0.129369';
730
+ const source = '0.0.1234';
731
+ const amount = '100000';
732
+ /**
733
+ * Build an unsigned account-lib multi-signature send transaction
734
+ * @param destination The destination address of the transaction
735
+ * @param source The account sending thist ransaction
736
+ * @param amount The amount to send to the recipient
737
+ */
738
+ const buildUnsignedTransaction = async function ({ destination, source, amount = '100000' }) {
739
+ const factory = (0, getBuilderFactory_1.getBuilderFactory)('thbar');
740
+ const txBuilder = factory.getTransferBuilder();
741
+ txBuilder.fee({
742
+ fee: '100000',
743
+ });
744
+ txBuilder.source({ address: source });
745
+ txBuilder.send({ address: destination, amount });
746
+ return await txBuilder.build();
747
+ };
748
+ it('should sign transaction', async function () {
749
+ const key = new src_1.KeyPair();
750
+ const unsignedTransaction = await buildUnsignedTransaction({
751
+ destination,
752
+ source,
753
+ amount,
754
+ });
755
+ const tx = await basecoin.signTransaction({
756
+ prv: key.getKeys().prv.toString(),
757
+ txPrebuild: {
758
+ txHex: unsignedTransaction.toBroadcastFormat(),
759
+ },
760
+ });
761
+ const factory = (0, getBuilderFactory_1.getBuilderFactory)('thbar');
762
+ const txBuilder = factory.from(tx.halfSigned.txHex);
763
+ const signedTx = await txBuilder.build();
764
+ const txJson = signedTx.toJson();
765
+ txJson.should.have.properties('to', 'amount');
766
+ txJson.to?.should.equal(destination);
767
+ txJson.from.should.equal(source);
768
+ txJson.amount?.should.equal(amount);
769
+ txJson.instructionsData.params.recipients[0].should.deepEqual({
770
+ address: destination,
771
+ amount,
772
+ });
773
+ signedTx.signature.length.should.equal(1);
774
+ });
775
+ it('should fully sign transaction with root key', async function () {
776
+ const key1 = basecoin.generateRootKeyPair();
777
+ const key2 = basecoin.generateRootKeyPair();
778
+ const unsignedTransaction = await buildUnsignedTransaction({
779
+ destination,
780
+ source,
781
+ amount,
782
+ });
783
+ const txHalfSigned = await basecoin.signTransaction({
784
+ prv: key1.prv,
785
+ txPrebuild: {
786
+ txHex: unsignedTransaction.toBroadcastFormat(),
787
+ },
788
+ });
789
+ const factory = (0, getBuilderFactory_1.getBuilderFactory)('thbar');
790
+ const txBuilderHalfSigned = factory.from(txHalfSigned.halfSigned.txHex);
791
+ const halfSignedTx = await txBuilderHalfSigned.build();
792
+ const halfSignedTxJson = halfSignedTx.toJson();
793
+ halfSignedTxJson.should.have.properties('to', 'amount');
794
+ halfSignedTxJson.to?.should.equal(destination);
795
+ halfSignedTxJson.from.should.equal(source);
796
+ halfSignedTxJson.amount?.should.equal(amount);
797
+ halfSignedTxJson.instructionsData.params.recipients[0].should.deepEqual({
798
+ address: destination,
799
+ amount,
800
+ });
801
+ halfSignedTx.signature.length.should.equal(1);
802
+ const txSigned = await basecoin.signTransaction({
803
+ prv: key2.prv,
804
+ txPrebuild: {
805
+ txHex: halfSignedTx.toBroadcastFormat(),
806
+ },
807
+ });
808
+ const txBuilderSigned = factory.from(txSigned.txHex);
809
+ const signedTx = await txBuilderSigned.build();
810
+ const signedTxJson = signedTx.toJson();
811
+ signedTxJson.should.have.properties('to', 'amount');
812
+ signedTxJson.to?.should.equal(destination);
813
+ signedTxJson.from.should.equal(source);
814
+ signedTxJson.amount?.should.equal(amount);
815
+ signedTxJson.instructionsData.params.recipients[0].should.deepEqual({
816
+ address: destination,
817
+ amount,
818
+ });
819
+ signedTx.signature.length.should.equal(2);
820
+ });
821
+ });
822
+ describe('Recovery', function () {
823
+ const defaultValidDuration = '180';
824
+ const defaultFee = 10000000;
825
+ const defaultNodeId = '0.0.3';
826
+ const userKey = '{"iv":"WlPuJOejRWgj/NTd3UMgrw==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"6yAVFvreHSQ=","ct":"8j/lBVkFByKlVhaS9JWmmLja5yTokjaIiLDxMIDjMojVEim9T36WAm5qW6v1V0A7QcEuGiVl3PKMDa+Gr6tI/HT58DW5RE+pHzya9MUQpAgNrJr8VEWjrXWqZECVtra1/bKCyB+mozc="}';
827
+ const userPub = '302a300506032b6570032100ddd53a1591d72b181109bd3e57b18603740490b9ab4d37bc7fa27480e6b8c911';
828
+ const backupKey = '{"iv":"D5DVDozQx9B02JeFV0/OVA==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"7FUNF8M35bo=","ct":"ZiPsu5Qe/AIS4JQXt+rrusHnYCy4CqurM16R5wJrd4CEx7u85y3yy5ErnsdyYYcc3txyNmUIQ2/CBq/LKoKO/VIeU++CnKxzGuHGcNI47BPk3RQK42a66uIQn/yTR++XgdK1KhvUL3U="}';
829
+ const backupPub = '302a300506032b65700321006293e4ec9bf1b2d8fae631119107248a65e2207a05d32a11f42cc3d9a3005d4a';
830
+ const rootAddress = '0.0.7671186';
831
+ const walletPassphrase = 'TestPasswordPleaseIgnore';
832
+ const recoveryDestination = '0.0.7651908';
833
+ const bitgoKey = '5a93b01ea87e963f61c974a89d62e3841392f1ba020fbbcc65a8089ca025abbb';
834
+ const memo = '4';
835
+ const balance = '1000000000';
836
+ const formatBalanceResponse = (balance) => new bignumber_js_1.BigNumber(balance).dividedBy(basecoin.getBaseFactor()).toFixed(9) + ' ℏ';
837
+ const tokenId = '0.0.429274';
838
+ describe('Non-BitGo', async function () {
839
+ const sandBox = sinon_1.default.createSandbox();
840
+ afterEach(function () {
841
+ sandBox.verifyAndRestore();
842
+ });
843
+ it('should build and sign the recovery tx', async function () {
844
+ const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
845
+ const getBalanceStub = sandBox
846
+ .stub(src_1.Hbar.prototype, 'getAccountBalance')
847
+ .resolves({ hbars: formatBalanceResponse(balance), tokens: [] });
848
+ const recovery = await basecoin.recover({
849
+ userKey,
850
+ backupKey,
851
+ rootAddress,
852
+ walletPassphrase,
853
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
854
+ });
855
+ recovery.should.not.be.undefined();
856
+ recovery.should.have.property('id');
857
+ recovery.should.have.property('tx');
858
+ recovery.should.have.property('coin', 'thbar');
859
+ recovery.should.have.property('nodeId', defaultNodeId);
860
+ getBalanceStub.callCount.should.equal(1);
861
+ const txBuilder = basecoin.getBuilderFactory().from(recovery.tx);
862
+ const tx = await txBuilder.build();
863
+ tx.toBroadcastFormat().should.equal(recovery.tx);
864
+ const txJson = tx.toJson();
865
+ txJson.amount.should.equal(expectedAmount);
866
+ txJson.to.should.equal(recoveryDestination);
867
+ txJson.from.should.equal(rootAddress);
868
+ txJson.fee.should.equal(defaultFee);
869
+ txJson.node.should.equal(defaultNodeId);
870
+ txJson.memo.should.equal(memo);
871
+ txJson.validDuration.should.equal(defaultValidDuration);
872
+ txJson.should.have.property('startTime');
873
+ recovery.should.have.property('startTime', txJson.startTime);
874
+ recovery.should.have.property('id', rootAddress + '@' + txJson.startTime);
875
+ });
876
+ it('should throw for invalid rootAddress', async function () {
877
+ const invalidRootAddress = 'randomstring';
878
+ await assert_1.default.rejects(async () => {
879
+ await basecoin.recover({
880
+ userKey,
881
+ backupKey,
882
+ rootAddress: 'randomstring',
883
+ walletPassphrase,
884
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
885
+ });
886
+ }, { message: 'invalid rootAddress, got: ' + invalidRootAddress });
887
+ });
888
+ it('should throw for invalid recoveryDestination', async function () {
889
+ const invalidRecoveryDestination = 'randomstring';
890
+ await assert_1.default.rejects(async () => {
891
+ await basecoin.recover({
892
+ userKey,
893
+ backupKey,
894
+ rootAddress,
895
+ walletPassphrase,
896
+ recoveryDestination: 'randomstring',
897
+ });
898
+ }, { message: 'invalid recoveryDestination, got: ' + invalidRecoveryDestination });
899
+ });
900
+ it('should throw for invalid nodeId', async function () {
901
+ const invalidNodeId = 'a.2.3';
902
+ await assert_1.default.rejects(async () => {
903
+ await basecoin.recover({
904
+ userKey,
905
+ backupKey,
906
+ rootAddress,
907
+ walletPassphrase,
908
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
909
+ nodeId: invalidNodeId,
910
+ });
911
+ }, { message: 'invalid nodeId, got: ' + invalidNodeId });
912
+ });
913
+ it('should throw for invalid maxFee', async function () {
914
+ const invalidMaxFee = '-32';
915
+ await assert_1.default.rejects(async () => {
916
+ await basecoin.recover({
917
+ userKey,
918
+ backupKey,
919
+ rootAddress,
920
+ walletPassphrase,
921
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
922
+ maxFee: invalidMaxFee,
923
+ });
924
+ }, { message: 'invalid maxFee, got: ' + invalidMaxFee });
925
+ });
926
+ it('should throw if there is no enough balance to recover', async function () {
927
+ const getBalanceStub = sandBox
928
+ .stub(src_1.Hbar.prototype, 'getAccountBalance')
929
+ .resolves({ hbars: formatBalanceResponse('100'), tokens: [] });
930
+ await assert_1.default.rejects(async () => {
931
+ await basecoin.recover({
932
+ userKey,
933
+ backupKey,
934
+ rootAddress,
935
+ walletPassphrase,
936
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
937
+ });
938
+ }, { message: 'Insufficient balance to recover, got balance: 100 fee: 10000000' });
939
+ getBalanceStub.callCount.should.equal(1);
940
+ });
941
+ it('should throw if the walletPassphrase is undefined', async function () {
942
+ await assert_1.default.rejects(async () => {
943
+ await basecoin.recover({
944
+ userKey,
945
+ backupKey,
946
+ rootAddress,
947
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
948
+ });
949
+ }, { message: 'walletPassphrase is required for non-bitgo recovery' });
950
+ });
951
+ it('should throw if the walletPassphrase is wrong', async function () {
952
+ await assert_1.default.rejects(async () => {
953
+ await basecoin.recover({
954
+ userKey,
955
+ backupKey,
956
+ rootAddress,
957
+ walletPassphrase: 'randompassword',
958
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
959
+ });
960
+ }, {
961
+ message: "unable to decrypt userKey or backupKey with the walletPassphrase provided, got error: password error - ccm: tag doesn't match",
962
+ });
963
+ });
964
+ it('should build and sign the recovery tx for tokens', async function () {
965
+ const balance = '100';
966
+ const data = {
967
+ hbars: '1',
968
+ tokens: [{ tokenId: tokenId, balance: balance, decimals: 6 }],
969
+ };
970
+ const getBalanceStub = sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
971
+ const recovery = await basecoin.recover({
972
+ userKey,
973
+ backupKey,
974
+ rootAddress,
975
+ walletPassphrase,
976
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
977
+ tokenId: tokenId,
978
+ });
979
+ recovery.should.not.be.undefined();
980
+ recovery.should.have.property('id');
981
+ recovery.should.have.property('tx');
982
+ recovery.should.have.property('coin', 'thbar');
983
+ recovery.should.have.property('nodeId', defaultNodeId);
984
+ getBalanceStub.callCount.should.equal(1);
985
+ const txBuilder = basecoin.getBuilderFactory().from(recovery.tx);
986
+ const tx = await txBuilder.build();
987
+ tx.toBroadcastFormat().should.equal(recovery.tx);
988
+ const txJson = tx.toJson();
989
+ txJson.amount.should.equal(balance);
990
+ txJson.to.should.equal(recoveryDestination);
991
+ txJson.from.should.equal(rootAddress);
992
+ txJson.fee.should.equal(defaultFee);
993
+ txJson.node.should.equal(defaultNodeId);
994
+ txJson.memo.should.equal(memo);
995
+ txJson.validDuration.should.equal(defaultValidDuration);
996
+ txJson.should.have.property('startTime');
997
+ recovery.should.have.property('startTime', txJson.startTime);
998
+ recovery.should.have.property('id', rootAddress + '@' + txJson.startTime);
999
+ });
1000
+ it('should throw error for non supported invalid tokenId', async function () {
1001
+ const invalidTokenId = 'randomstring';
1002
+ const data = {
1003
+ hbars: '1',
1004
+ tokens: [{ tokenId: tokenId, balance: '100', decimals: 6 }],
1005
+ };
1006
+ sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
1007
+ await assert_1.default.rejects(async () => {
1008
+ await basecoin.recover({
1009
+ userKey,
1010
+ backupKey,
1011
+ rootAddress: rootAddress,
1012
+ walletPassphrase,
1013
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1014
+ tokenId: invalidTokenId,
1015
+ });
1016
+ }, { message: 'Unsupported token: ' + invalidTokenId });
1017
+ });
1018
+ it('should throw error for insufficient balance for tokenId if token balance not exist', async function () {
1019
+ const data = {
1020
+ hbars: '100',
1021
+ tokens: [{ tokenId: 'randomString', balance: '100', decimals: 6 }],
1022
+ };
1023
+ sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
1024
+ await assert_1.default.rejects(async () => {
1025
+ await basecoin.recover({
1026
+ userKey,
1027
+ backupKey,
1028
+ rootAddress: rootAddress,
1029
+ walletPassphrase,
1030
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1031
+ tokenId: tokenId,
1032
+ });
1033
+ }, { message: 'Insufficient balance to recover token: ' + tokenId + ' for account: ' + rootAddress });
1034
+ });
1035
+ it('should throw error for insufficient balance for tokenId if token balance exist with 0 amount', async function () {
1036
+ const data = {
1037
+ hbars: '100',
1038
+ tokens: [{ tokenId: 'randomString', balance: '0', decimals: 6 }],
1039
+ };
1040
+ sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
1041
+ await assert_1.default.rejects(async () => {
1042
+ await basecoin.recover({
1043
+ userKey,
1044
+ backupKey,
1045
+ rootAddress: rootAddress,
1046
+ walletPassphrase,
1047
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1048
+ tokenId: tokenId,
1049
+ });
1050
+ }, { message: 'Insufficient balance to recover token: ' + tokenId + ' for account: ' + rootAddress });
1051
+ });
1052
+ it('should throw error for insufficient native balance for token transfer', async function () {
1053
+ const data = {
1054
+ hbars: '0.01',
1055
+ tokens: [{ tokenId: tokenId, balance: '10', decimals: 6 }],
1056
+ };
1057
+ sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
1058
+ await assert_1.default.rejects(async () => {
1059
+ await basecoin.recover({
1060
+ userKey,
1061
+ backupKey,
1062
+ rootAddress: rootAddress,
1063
+ walletPassphrase,
1064
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1065
+ tokenId: tokenId,
1066
+ });
1067
+ }, { message: 'Insufficient native balance to recover tokens, got native balance: 1000000 fee: ' + defaultFee });
1068
+ });
1069
+ });
1070
+ describe('Unsigned Sweep', function () {
1071
+ const sandBox = sinon_1.default.createSandbox();
1072
+ let getBalanceStub;
1073
+ afterEach(function () {
1074
+ sandBox.verifyAndRestore();
1075
+ });
1076
+ it('should build unsigned sweep tx', async function () {
1077
+ getBalanceStub = sandBox
1078
+ .stub(src_1.Hbar.prototype, 'getAccountBalance')
1079
+ .resolves({ hbars: formatBalanceResponse(balance), tokens: [] });
1080
+ const startTime = (Date.now() / 1000 + 10).toFixed(); // timestamp in seconds, 10 seconds from now
1081
+ const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
1082
+ const recovery = await basecoin.recover({
1083
+ userKey: userPub,
1084
+ backupKey: backupPub,
1085
+ rootAddress,
1086
+ bitgoKey,
1087
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1088
+ startTime,
1089
+ });
1090
+ getBalanceStub.callCount.should.equal(1);
1091
+ recovery.should.not.be.undefined();
1092
+ recovery.should.have.property('txHex');
1093
+ recovery.should.have.property('id', rootAddress + '@' + startTime + '.0');
1094
+ recovery.should.have.property('userKey', userPub);
1095
+ recovery.should.have.property('backupKey', backupPub);
1096
+ recovery.should.have.property('bitgoKey', bitgoKey);
1097
+ recovery.should.have.property('address', rootAddress);
1098
+ recovery.should.have.property('coin', 'thbar');
1099
+ recovery.should.have.property('maxFee', defaultFee.toString());
1100
+ recovery.should.have.property('recipients', [{ address: recoveryDestination, amount: expectedAmount }]);
1101
+ recovery.should.have.property('amount', expectedAmount);
1102
+ recovery.should.have.property('validDuration', defaultValidDuration);
1103
+ recovery.should.have.property('nodeId', defaultNodeId);
1104
+ recovery.should.have.property('memo', memo);
1105
+ recovery.should.have.property('startTime', startTime + '.0');
1106
+ const txBuilder = basecoin.getBuilderFactory().from(recovery.txHex);
1107
+ const tx = await txBuilder.build();
1108
+ const txJson = tx.toJson();
1109
+ txJson.id.should.equal(rootAddress + '@' + startTime + '.0');
1110
+ txJson.amount.should.equal(expectedAmount);
1111
+ txJson.to.should.equal(recoveryDestination);
1112
+ txJson.from.should.equal(rootAddress);
1113
+ txJson.fee.should.equal(defaultFee);
1114
+ txJson.node.should.equal(defaultNodeId);
1115
+ txJson.memo.should.equal(memo);
1116
+ txJson.validDuration.should.equal(defaultValidDuration);
1117
+ txJson.startTime.should.equal(startTime + '.0');
1118
+ txJson.validDuration.should.equal(defaultValidDuration);
1119
+ });
1120
+ it('should build unsigned sweep tx for tokens', async function () {
1121
+ const balance = '100';
1122
+ const data = {
1123
+ hbars: '1',
1124
+ tokens: [{ tokenId: tokenId, balance: balance, decimals: 6 }],
1125
+ };
1126
+ getBalanceStub = sandBox.stub(src_1.Hbar.prototype, 'getAccountBalance').resolves(data);
1127
+ const startTime = (Date.now() / 1000 + 10).toFixed(); // timestamp in seconds, 10 seconds from now
1128
+ const recovery = await basecoin.recover({
1129
+ userKey: userPub,
1130
+ backupKey: backupPub,
1131
+ rootAddress,
1132
+ bitgoKey,
1133
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1134
+ startTime,
1135
+ tokenId: tokenId,
1136
+ });
1137
+ getBalanceStub.callCount.should.equal(1);
1138
+ recovery.should.not.be.undefined();
1139
+ recovery.should.have.property('txHex');
1140
+ recovery.should.have.property('id', rootAddress + '@' + startTime + '.0');
1141
+ recovery.should.have.property('userKey', userPub);
1142
+ recovery.should.have.property('backupKey', backupPub);
1143
+ recovery.should.have.property('bitgoKey', bitgoKey);
1144
+ recovery.should.have.property('address', rootAddress);
1145
+ recovery.should.have.property('coin', 'thbar');
1146
+ recovery.should.have.property('maxFee', defaultFee.toString());
1147
+ recovery.should.have.property('recipients', [
1148
+ { address: recoveryDestination, amount: balance, tokenName: 'thbar:usdc' },
1149
+ ]);
1150
+ recovery.should.have.property('amount', balance);
1151
+ recovery.should.have.property('validDuration', defaultValidDuration);
1152
+ recovery.should.have.property('nodeId', defaultNodeId);
1153
+ recovery.should.have.property('memo', memo);
1154
+ recovery.should.have.property('startTime', startTime + '.0');
1155
+ const txBuilder = basecoin.getBuilderFactory().from(recovery.txHex);
1156
+ const tx = await txBuilder.build();
1157
+ const txJson = tx.toJson();
1158
+ txJson.id.should.equal(rootAddress + '@' + startTime + '.0');
1159
+ txJson.amount.should.equal(balance);
1160
+ txJson.to.should.equal(recoveryDestination);
1161
+ txJson.from.should.equal(rootAddress);
1162
+ txJson.fee.should.equal(defaultFee);
1163
+ txJson.node.should.equal(defaultNodeId);
1164
+ txJson.memo.should.equal(memo);
1165
+ txJson.validDuration.should.equal(defaultValidDuration);
1166
+ txJson.startTime.should.equal(startTime + '.0');
1167
+ txJson.validDuration.should.equal(defaultValidDuration);
1168
+ });
1169
+ it('should throw if startTime is undefined', async function () {
1170
+ const startTime = undefined;
1171
+ await assert_1.default.rejects(async () => {
1172
+ await basecoin.recover({
1173
+ userKey: userPub,
1174
+ backupKey: backupPub,
1175
+ rootAddress,
1176
+ bitgoKey,
1177
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1178
+ startTime,
1179
+ });
1180
+ }, { message: 'start time is required for unsigned sweep' });
1181
+ });
1182
+ it('should throw for invalid userKey', async function () {
1183
+ const startTime = (Date.now() / 1000 + 10).toFixed();
1184
+ const invalidUserPub = '302a300506032b6570032100randomstring';
1185
+ await assert_1.default.rejects(async () => {
1186
+ await basecoin.recover({
1187
+ userKey: invalidUserPub,
1188
+ backupKey: backupPub,
1189
+ bitgoKey,
1190
+ rootAddress,
1191
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1192
+ startTime,
1193
+ });
1194
+ }, { message: 'invalid userKey, got: ' + invalidUserPub });
1195
+ });
1196
+ it('should throw for invalid backupKey', async function () {
1197
+ const invalidBackupPub = '302a300506032b6570032100randomstring';
1198
+ const startTime = (Date.now() / 1000 + 10).toFixed();
1199
+ await assert_1.default.rejects(async () => {
1200
+ await basecoin.recover({
1201
+ userKey: userPub,
1202
+ backupKey: invalidBackupPub,
1203
+ bitgoKey,
1204
+ rootAddress,
1205
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1206
+ startTime,
1207
+ });
1208
+ }, { message: 'invalid backupKey, got: ' + invalidBackupPub });
1209
+ });
1210
+ it('should throw if startTime is a valid timestamp', async function () {
1211
+ const startTime = 'asd';
1212
+ await assert_1.default.rejects(async () => {
1213
+ await basecoin.recover({
1214
+ userKey: userPub,
1215
+ backupKey: backupPub,
1216
+ rootAddress,
1217
+ bitgoKey,
1218
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1219
+ startTime,
1220
+ });
1221
+ }, { message: 'invalid startTime, got: ' + startTime });
1222
+ });
1223
+ it('should throw if startTime is not a future date', async function () {
1224
+ const startTime = (Date.now() / 1000 - 1).toString(); // timestamp in seconds, 1 second ago
1225
+ await assert_1.default.rejects(async () => {
1226
+ await basecoin.recover({
1227
+ userKey: userPub,
1228
+ backupKey: backupPub,
1229
+ rootAddress,
1230
+ bitgoKey,
1231
+ recoveryDestination: recoveryDestination + '?memoId=' + memo,
1232
+ startTime,
1233
+ });
1234
+ }, { message: 'startTime must be a future timestamp, got: ' + startTime });
1235
+ });
1236
+ });
1237
+ describe('Recovery with root keys', function () {
1238
+ const sandBox = sinon_1.default.createSandbox();
1239
+ let getBalanceStub;
1240
+ const walletPassphrase = 'testbtcpassword1999';
1241
+ const userEddsaRootXPrv = '{"iv":"lHOTkiuucR2JWFD1x1gqpQ==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"HkFrDVH++d8=","ct":"NBtbYdFEK84oH9uxwl/UrhRsW5nGJPnMSpRAo8Blrc7WTSPxGXmVS/EpUYEV03HG06/EnyBR0/Y6bjLQz4gkL6cGJD9hgyKqDvc9RtKHagEbo75oxPr0zP+r1HMUGBW38Ttgor674gBeb1Myew69xcS9KgguNxwz77X6fdeBhrfogLY22vcuLA=="}';
1242
+ const userEddsaRootPub = 'd9cb9c9c617cfa0b715849516bb054a2b5d78c0e3eeef011176fb8bc0108c531';
1243
+ const backupEddsaRootXprv = '{"iv":"sBoEFBBNoi2YVICPf16/BQ==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"HkFrDVH++d8=","ct":"GscOqJC+Iq+Lr39plQp5ZCamVlpJHOltGTZ7/UnUunIhFmZWMBLxjEVnMOtPreb0NZ4/SFqO/N3mZvq6JbB7vWRxJuqkBIiVcIRwkSWdW55cboKx2ec3ajg8+uO2pbvNDs26Q+9NtZ4jZnKNqSUXiCmtJXLRHQ32oyD+olKRpIR2NQo2+7kIEw=="}';
1244
+ const backupEddsaRootPub = 'f163b1b8ee4c3343a97ac1d2470b967e967ac7b4e3731cacf02f28a1434a2f99';
1245
+ const rootAddress = '0.0.3644667';
1246
+ const memoId = '0';
1247
+ beforeEach(function () {
1248
+ getBalanceStub = sandBox
1249
+ .stub(src_1.Hbar.prototype, 'getAccountBalance')
1250
+ .resolves({ hbars: formatBalanceResponse(balance), tokens: [] });
1251
+ });
1252
+ afterEach(function () {
1253
+ sandBox.verifyAndRestore();
1254
+ });
1255
+ it('should build and sign non-bitgo recovery tx with root keys', async function () {
1256
+ const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
1257
+ const recovery = await basecoin.recover({
1258
+ userKey: userEddsaRootXPrv,
1259
+ backupKey: backupEddsaRootXprv,
1260
+ rootAddress,
1261
+ walletPassphrase,
1262
+ recoveryDestination: recoveryDestination + '?memoId=' + memoId,
1263
+ });
1264
+ getBalanceStub.callCount.should.equal(1);
1265
+ recovery.should.not.be.undefined();
1266
+ recovery.should.have.property('id');
1267
+ recovery.should.have.property('tx');
1268
+ recovery.should.have.property('coin', 'thbar');
1269
+ recovery.should.have.property('nodeId', defaultNodeId);
1270
+ getBalanceStub.callCount.should.equal(1);
1271
+ const txBuilder = basecoin.getBuilderFactory().from(recovery.tx);
1272
+ const tx = await txBuilder.build();
1273
+ tx.toBroadcastFormat().should.equal(recovery.tx);
1274
+ const txJson = tx.toJson();
1275
+ txJson.amount.should.equal(expectedAmount);
1276
+ txJson.to.should.equal(recoveryDestination);
1277
+ txJson.from.should.equal(rootAddress);
1278
+ txJson.fee.should.equal(defaultFee);
1279
+ txJson.node.should.equal(defaultNodeId);
1280
+ txJson.memo.should.equal(memoId);
1281
+ txJson.validDuration.should.equal(defaultValidDuration);
1282
+ txJson.should.have.property('startTime');
1283
+ recovery.should.have.property('startTime', txJson.startTime);
1284
+ recovery.should.have.property('id', rootAddress + '@' + txJson.startTime);
1285
+ });
1286
+ it('should build unsigned sweep tx', async function () {
1287
+ const startTime = (Date.now() / 1000 + 10).toFixed(); // timestamp in seconds, 10 seconds from now
1288
+ const expectedAmount = new bignumber_js_1.BigNumber(balance).minus(defaultFee).toString();
1289
+ const recovery = await basecoin.recover({
1290
+ userKey: userEddsaRootPub,
1291
+ backupKey: backupEddsaRootPub,
1292
+ rootAddress,
1293
+ bitgoKey,
1294
+ recoveryDestination: recoveryDestination + '?memoId=' + memoId,
1295
+ startTime,
1296
+ });
1297
+ getBalanceStub.callCount.should.equal(1);
1298
+ recovery.should.not.be.undefined();
1299
+ recovery.should.have.property('txHex');
1300
+ recovery.should.have.property('id', rootAddress + '@' + startTime + '.0');
1301
+ recovery.should.have.property('userKey', userEddsaRootPub);
1302
+ recovery.should.have.property('backupKey', backupEddsaRootPub);
1303
+ recovery.should.have.property('bitgoKey', bitgoKey);
1304
+ recovery.should.have.property('address', rootAddress);
1305
+ recovery.should.have.property('coin', 'thbar');
1306
+ recovery.should.have.property('maxFee', defaultFee.toString());
1307
+ recovery.should.have.property('recipients', [{ address: recoveryDestination, amount: expectedAmount }]);
1308
+ recovery.should.have.property('amount', expectedAmount);
1309
+ recovery.should.have.property('validDuration', defaultValidDuration);
1310
+ recovery.should.have.property('nodeId', defaultNodeId);
1311
+ recovery.should.have.property('memo', memoId);
1312
+ recovery.should.have.property('startTime', startTime + '.0');
1313
+ const txBuilder = basecoin.getBuilderFactory().from(recovery.txHex);
1314
+ const tx = await txBuilder.build();
1315
+ const txJson = tx.toJson();
1316
+ txJson.id.should.equal(rootAddress + '@' + startTime + '.0');
1317
+ txJson.amount.should.equal(expectedAmount);
1318
+ txJson.to.should.equal(recoveryDestination);
1319
+ txJson.from.should.equal(rootAddress);
1320
+ txJson.fee.should.equal(defaultFee);
1321
+ txJson.node.should.equal(defaultNodeId);
1322
+ txJson.memo.should.equal(memoId);
1323
+ txJson.validDuration.should.equal(defaultValidDuration);
1324
+ txJson.startTime.should.equal(startTime + '.0');
1325
+ txJson.validDuration.should.equal(defaultValidDuration);
1326
+ });
1327
+ });
1328
+ });
1329
+ describe('broadcastTransaction', function () {
1330
+ const sandBox = sinon_1.default.createSandbox();
1331
+ afterEach(function () {
1332
+ sandBox.verifyAndRestore();
1333
+ });
1334
+ it('should succeed if the startTime and serializedSignedTransaction are valid', async function () {
1335
+ const startTime = (Date.now() / 1000 - 3).toFixed(); // timestamp in seconds, -3 seconds from now so it's valid after 2 seconds
1336
+ const expectedResponse = { txId: '0.0.7668465@' + startTime + '.0', status: 'SUCCESS' };
1337
+ const broadcastStub = sandBox.stub(src_1.Hbar.prototype, 'clientBroadcastTransaction').resolves(expectedResponse);
1338
+ const serializedSignedTransaction = '1acc010a640a20592a4fbb7263c59d450e651df96620dc9208ee7c7d9d6f2fdcb91c53f88312611a40105b7d250c81f3705bc0b85168ce3fd00330131bb7701378681c8c2e6a09a91828715e7334f4ef28d20ff09887c6e87c0a5c693e23824c26f3ba161fce0448050a640a20a6905095616c3cfaa1bf61b53de30e938ce4112c3cc4d25393ec6b9bf4dea0631a40bf98c5b89b7a08544edaa1f4c08a0dfa6ec3f78b7e2fd27049283984050f38ccf0303ee57a377cc0a725ffd99d69e9fd914770ab0949ba556d84b3b00cb07e0d22500a130a0608cea8c1ad0612090800100018f185d40312060800100018031880c2d72f220308b40132013472240a220a0f0a090800100018f185d40310d3b0510a0f0a090800100018c484d30310d4b051';
1339
+ const result = await basecoin.broadcastTransaction({ serializedSignedTransaction, startTime });
1340
+ broadcastStub.callCount.should.equal(1);
1341
+ result.should.deepEqual(expectedResponse);
1342
+ });
1343
+ it('should throw if the startTime is expired', async function () {
1344
+ const startTime = (Date.now() / 1000 - 2000).toFixed(); // timestamp in seconds, 2000 seconds from now
1345
+ const serializedSignedTransaction = '1acc010a640a20592a4fbb7263c59d450e651df96620dc9208ee7c7d9d6f2fdcb91c53f88312611a40105b7d250c81f3705bc0b85168ce3fd00330131bb7701378681c8c2e6a09a91828715e7334f4ef28d20ff09887c6e87c0a5c693e23824c26f3ba161fce0448050a640a20a6905095616c3cfaa1bf61b53de30e938ce4112c3cc4d25393ec6b9bf4dea0631a40bf98c5b89b7a08544edaa1f4c08a0dfa6ec3f78b7e2fd27049283984050f38ccf0303ee57a377cc0a725ffd99d69e9fd914770ab0949ba556d84b3b00cb07e0d22500a130a0608cea8c1ad0612090800100018f185d40312060800100018031880c2d72f220308b40132013472240a220a0f0a090800100018f185d40310d3b0510a0f0a090800100018c484d30310d4b051';
1346
+ await assert_1.default.rejects(async () => {
1347
+ await basecoin.broadcastTransaction({ serializedSignedTransaction, startTime });
1348
+ }, (error) => {
1349
+ assert_1.default.ok(error.message.includes('Failed to broadcast transaction, error: startTime window expired'));
1350
+ return true;
1351
+ });
1352
+ });
1353
+ it('should throw if the serializedSignedTransaction is invalid', async function () {
1354
+ const startTime = (Date.now() / 1000 - 10).toFixed(); // timestamp in seconds, 10 seconds from now
1355
+ const serializedSignedTransaction = 'randomstring';
1356
+ await assert_1.default.rejects(async () => {
1357
+ await basecoin.broadcastTransaction({ serializedSignedTransaction, startTime });
1358
+ });
1359
+ });
1360
+ it('should throw if the startTime in the tx is invalid', async function () {
1361
+ const expectedResponse = 'transaction 0.0.7668465@1706056301.000000000 failed precheck with status INVALID_TRANSACTION_START';
1362
+ sandBox.stub(src_1.Hbar.prototype, 'clientBroadcastTransaction').rejects(new Error(expectedResponse));
1363
+ const serializedSignedTransaction = '1acc010a640a20592a4fbb7263c59d450e651df96620dc9208ee7c7d9d6f2fdcb91c53f88312611a40105b7d250c81f3705bc0b85168ce3fd00330131bb7701378681c8c2e6a09a91828715e7334f4ef28d20ff09887c6e87c0a5c693e23824c26f3ba161fce0448050a640a20a6905095616c3cfaa1bf61b53de30e938ce4112c3cc4d25393ec6b9bf4dea0631a40bf98c5b89b7a08544edaa1f4c08a0dfa6ec3f78b7e2fd27049283984050f38ccf0303ee57a377cc0a725ffd99d69e9fd914770ab0949ba556d84b3b00cb07e0d22500a130a0608cea8c1ad0612090800100018f185d40312060800100018031880c2d72f220308b40132013472240a220a0f0a090800100018f185d40310d3b0510a0f0a090800100018c484d30310d4b051';
1364
+ await assert_1.default.rejects(async () => {
1365
+ await basecoin.broadcastTransaction({ serializedSignedTransaction });
1366
+ }, { message: expectedResponse });
1367
+ });
1368
+ });
1369
+ describe('deriveKeyWithSeed', function () {
1370
+ it('should derive key with seed', function () {
1371
+ (() => {
1372
+ basecoin.deriveKeyWithSeed('test');
1373
+ }).should.throw('method deriveKeyWithSeed not supported for eddsa curve');
1374
+ });
1375
+ });
1376
+ describe('Generate wallet Root key pair: ', () => {
1377
+ it('should generate key pair', () => {
1378
+ const kp = basecoin.generateRootKeyPair();
1379
+ basecoin.isValidPub(kp.pub).should.equal(true);
1380
+ const keypair = new src_1.KeyPair({ prv: kp.prv }).getKeys(true);
1381
+ keypair.should.have.property('prv');
1382
+ keypair.prv?.should.equal(kp.prv.slice(0, 64));
1383
+ keypair.pub.should.equal(kp.pub);
1384
+ });
1385
+ it('should generate key pair from seed', () => {
1386
+ const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
1387
+ const kp = basecoin.generateRootKeyPair(seed);
1388
+ basecoin.isValidPub(kp.pub).should.equal(true);
1389
+ kp.pub.should.equal('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a');
1390
+ kp.prv.should.equal('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a');
1391
+ const keypair = new src_1.KeyPair({ prv: kp.prv }).getKeys(true);
1392
+ keypair.should.have.property('prv');
1393
+ keypair.prv?.should.equal(kp.prv.slice(0, 64));
1394
+ keypair.pub.should.equal(kp.pub);
1395
+ });
1396
+ });
1397
+ describe('AuditKey', () => {
1398
+ const { key } = hbarBackupKey_1.hbarBackupKey;
1399
+ const walletPassphrase = 'kAm[EFQ6o=SxlcLFDw%,';
1400
+ it('should return for valid inputs', () => {
1401
+ basecoin.assertIsValidKey({
1402
+ coinName: 'hbar',
1403
+ encryptedPrv: key,
1404
+ walletPassphrase,
1405
+ });
1406
+ });
1407
+ it('should throw error if the walletPassphrase is incorrect', () => {
1408
+ assert_1.default.throws(() => basecoin.assertIsValidKey({
1409
+ coinName: 'hbar',
1410
+ encryptedPrv: key,
1411
+ walletPassphrase: 'foo',
1412
+ }), { message: "failed to decrypt prv: ccm: tag doesn't match" });
1413
+ });
1414
+ it('should throw error if the key is altered', () => {
1415
+ const alteredKey = key.replace(/[0-9]/g, '0');
1416
+ assert_1.default.throws(() => basecoin.assertIsValidKey({
1417
+ coinName: 'hbar',
1418
+ encryptedPrv: alteredKey,
1419
+ walletPassphrase,
1420
+ }), {
1421
+ message: 'failed to decrypt prv: json decrypt: invalid parameters',
1422
+ });
1423
+ });
1424
+ it('should throw error if the key is not a valid key', () => {
1425
+ const invalidKey = '#@)$#($*@)#($*';
1426
+ const encryptedPrv = (0, sdk_api_1.encrypt)(walletPassphrase, invalidKey);
1427
+ assert_1.default.throws(() => basecoin.assertIsValidKey({
1428
+ coinName: 'hbar',
1429
+ encryptedPrv,
1430
+ walletPassphrase,
1431
+ }), {
1432
+ message: 'Invalid private key: Invalid private key length. Must be a hex and multiple of 2',
1433
+ });
1434
+ });
1435
+ });
1436
+ });
1437
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGJhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9oYmFyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQTRCO0FBRTVCLDBDQUE0QjtBQUM1QixnREFBd0I7QUFDeEIsa0RBQXlDO0FBQ3pDLG1DQUFxQztBQUNyQywrQ0FBeUM7QUFDekMsbURBQStEO0FBQy9ELGlEQUF3RDtBQUN4RCxtREFBc0Q7QUFHdEQsMkRBQTZDO0FBQzdDLG1DQUE0RDtBQUM1RCwyREFBd0Q7QUFDeEQsNERBQXlEO0FBRXpELFFBQVEsQ0FBQyxtQkFBbUIsRUFBRTtJQUM1QixJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFRLENBQUM7SUFDYixJQUFJLEtBQUssQ0FBQztJQUVWLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsV0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2xELEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFVBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNoRCxlQUFTLENBQUMsdUJBQXVCLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsRUFBRSxFQUFFO1lBQ3hFLEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQzVDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDL0IsS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMs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c3NlcnQgZnJvbSAnYXNzZXJ0JztcblxuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgU2lub24sIHsgU2lub25TdHViIH0gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgQmlnTnVtYmVyIH0gZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IFRlc3RCaXRHbywgVGVzdEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R29BUEksIGVuY3J5cHQgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstYXBpJztcbmltcG9ydCB7IGNvbW1vbiwgV2FsbGV0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgVHhEYXRhLCBUcmFuc2ZlciB9IGZyb20gJy4uLy4uL3NyYy9saWIvaWZhY2UnO1xuXG5pbXBvcnQgKiBhcyBUZXN0RGF0YSBmcm9tICcuLi9maXh0dXJlcy9oYmFyJztcbmltcG9ydCB7IEhiYXIsIFRoYmFyLCBLZXlQYWlyLCBIYmFyVG9rZW4gfSBmcm9tICcuLi8uLi9zcmMnO1xuaW1wb3J0IHsgZ2V0QnVpbGRlckZhY3RvcnkgfSBmcm9tICcuL2dldEJ1aWxkZXJGYWN0b3J5JztcbmltcG9ydCB7IGhiYXJCYWNrdXBLZXkgfSBmcm9tICcuL2ZpeHR1cmVzL2hiYXJCYWNrdXBLZXknO1xuXG5kZXNjcmliZSgnSGVkZXJhIEhhc2hncmFwaDonLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgYmFzZWNvaW47XG4gIGxldCB0b2tlbjtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcigndGhiYXInLCBUaGJhci5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCdoYmFyJywgSGJhci5jcmVhdGVJbnN0YW5jZSk7XG4gICAgSGJhclRva2VuLmNyZWF0ZVRva2VuQ29uc3RydWN0b3JzKCkuZm9yRWFjaCgoeyBuYW1lLCBjb2luQ29uc3RydWN0b3IgfSkgPT4ge1xuICAgICAgYml0Z28uc2FmZVJlZ2lzdGVyKG5hbWUsIGNvaW5Db25zdHJ1Y3Rvcik7XG4gICAgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYmFzZWNvaW4gPSBiaXRnby5jb2luKCd0aGJhcicpO1xuICAgIHRva2VuID0gYml0Z28uY29pbigndGhiYXI6dXNkYycpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGluc3RhbnRpYXRlIHRoZSBjb2luJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJhc2Vjb2luID0gYml0Z28uY29pbignaGJhcicpO1xuICAgIGJhc2Vjb2luLnNob3VsZC5iZS5hbi5pbnN0YW5jZW9mKEhiYXIpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGNoZWNrIHZhbGlkIGFkZHJlc3NlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiYWRBZGRyZXNzZXMgPSBbXG4gICAgICAnJyxcbiAgICAgICcwLjAnLFxuICAgICAgJ1laMDlmZC0nLFxuICAgICAgJzAuMC4wLmEnLFxuICAgICAgJ3NhZGFzZGZnZ2cnLFxuICAgICAgJzAuMi5hLmInLFxuICAgICAgJzAuMC4xMDA/PXNrc2pkJyxcbiAgICAgICcwLjAuNDEwOTg/bWVtb0lkPScsXG4gICAgXTtcbiAgICBjb25zdCBnb29kQWRkcmVzc2VzID0gW1xuICAgICAgJzAnLFxuICAgICAgJzAuMC4wJyxcbiAgICAgICcwLjAuNDEwOTgnLFxuICAgICAgJzAuMC4wP21lbW9JZD04NCcsXG4gICAgICAnMC4wLjQxMDk4JyxcbiAgICAgICcwLjAuNDEwOTg/bWVtb0lkPTJhYWFhYScsXG4gICAgICAnMC4wLjQxMDk4P21lbW9JZD0xJyxcbiAgICBdO1xuXG4gICAgYmFkQWRkcmVzc2VzLm1hcCgoYWRkcikgPT4ge1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcikuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICB9KTtcbiAgICBnb29kQWRkcmVzc2VzLm1hcCgoYWRkcikgPT4ge1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgaGV4QWRkcmVzcyA9ICcweDIzQzNFMjI3QkU5NzI4MUE3MEE1NDljN2REQjhkNUNhYWQzRTdDODQnO1xuICAgIGJhc2Vjb2luLmlzVmFsaWRBZGRyZXNzKGhleEFkZHJlc3MpLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgZXhwbGFpbiBhIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4ID0gSlNPTi5wYXJzZShUZXN0RGF0YS5yYXdUcmFuc2FjdGlvbkZvckV4cGxhaW4pO1xuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24odHgpO1xuXG4gICAgZXhwbGFpbi5pZC5zaG91bGQuZXF1YWwoJzAuMC40MzI4NUAxNjAwNTI5ODAwLjY0MzA5MzU4NicpO1xuICAgIGV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCgnMjIwMDAwMDAwMCcpO1xuICAgIGV4cGxhaW4udGltZXN0YW1wLnNob3VsZC5lcXVhbCgnMTYwMDUyOTgwMC42NDMwOTM1ODYnKTtcbiAgICBleHBsYWluLmV4cGlyYXRpb24uc2hvdWxkLmVxdWFsKCcxODAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbCgnMjIwMDAwMDAwMCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCgnMC4wLjQzMjgzJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8uc2hvdWxkLmVxdWFsKCcxJyk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDExNjA0MDcpO1xuICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSB0b2tlbiB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0b2tlblRyYW5zZmVyUGFyYW0gPSB7XG4gICAgICB0eEhleDogVGVzdERhdGEuVU5TSUdORURfVE9LRU5fVFJBTlNGRVIsXG4gICAgICBmZWVJbmZvOiB7XG4gICAgICAgIHNpemU6IDEwMDAsXG4gICAgICAgIGZlZTogMTE2MDQwNyxcbiAgICAgICAgZmVlUmF0ZTogMTE2MDQwNyxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHRva2VuVHJhbnNmZXJQYXJhbSk7XG5cbiAgICBleHBsYWluLmlkLnNob3VsZC5lcXVhbCgnMC4wLjgxMzIwQDE1OTYxMTA0OTMuMzcyNjQ2NTcwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gICAgZXhwbGFpbi50aW1lc3RhbXAuc2hvdWxkLmVxdWFsKCcxNTk2MTEwNDkzLjM3MjY0NjU3MCcpO1xuICAgIGV4cGxhaW4uZXhwaXJhdGlvbi5zaG91bGQuZXF1YWwoJzE4MCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKCcxMCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCgnMC4wLjc1ODYxJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLm1lbW8uc2hvdWxkLmVxdWFsKCcnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0udG9rZW5OYW1lLnNob3VsZC5lcXVhbCgndGhiYXI6dXNkYycpO1xuICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMTYwNDA3KTtcbiAgICBleHBsYWluLmNoYW5nZUFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBleHBsYWluIGEgbXVsdGlyZWNpcGllbnRzIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IG11bHRpVHJhbnNmZXJQYXJhbSA9IHtcbiAgICAgIHR4SGV4OiBUZXN0RGF0YS5VTlNJR05FRF9NVUxUSV9UUkFOU0ZFUixcbiAgICAgIGZlZUluZm86IHtcbiAgICAgICAgc2l6ZTogMTAwMCxcbiAgICAgICAgZmVlOiAxMTYwNDA3LFxuICAgICAgICBmZWVSYXRlOiAxMTYwNDA3LFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGV4cGxhaW4gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24obXVsdGlUcmFuc2ZlclBhcmFtKTtcblxuICAgIGV4cGxhaW4uaWQuc2hvdWxkLmVxdWFsKCcwLjAuODEzMjBAMTU5NjExMDQ5My4zNzI2NDY1NzAnKTtcbiAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzI1Jyk7XG4gICAgZXhwbGFpbi5leHBpcmF0aW9uLnNob3VsZC5lcXVhbCgnMTgwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoJzEwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNzU4NjEnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0ubWVtby5zaG91bGQuZXF1YWwoJycpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1sxXS5hbW91bnQuc2hvdWxkLmVxdWFsKCcxNScpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1sxXS5hZGRyZXNzLnNob3VsZC5lcXVhbCgnMC4wLjc4OTYzJyk7XG4gICAgZXhwbGFpbi5mZWUuc2hvdWxkLmVxdWFsKDExNjA0MDcpO1xuICAgIGV4cGxhaW4uY2hhbmdlQW1vdW50LnNob3VsZC5lcXVhbCgnMCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBtdWx0aXJlY2lwaWVudHMgdG9rZW4gdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdG9rZW5NdWx0aVRyYW5zZmVyUGFyYW0gPSB7XG4gICAgICB0eEhleDogVGVzdERhdGEuVU5TSUdORURfVE9LRU5fTVVMVElfVFJBTlNGRVIsXG4gICAgICBmZWVJbmZvOiB7XG4gICAgICAgIHNpemU6IDEwMDAsXG4gICAgICAgIGZlZTogMTE2MDQwNyxcbiAgICAgICAgZmVlUmF0ZTogMTE2MDQwNyxcbiAgICAgIH0sXG4gICAgfTtcbiAgICBjb25zdCBleHBsYWluID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHRva2VuTXVsdGlUcmFuc2ZlclBhcmFtKTtcblxuICAgIGV4cGxhaW4uaWQuc2hvdWxkLmVxdWFsKCcwLjAuODEzMjBAMTU5NjExMDQ5My4zNzI2NDY1NzAnKTtcbiAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgICBleHBsYWluLnRpbWVzdGFtcC5zaG91bGQuZXF1YWwoJzE1OTYxMTA0OTMuMzcyNjQ2NTcwJyk7XG4gICAgZXhwbGFpbi5leHBpcmF0aW9uLnNob3VsZC5lcXVhbCgnMTgwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoJzEwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNzU4NjEnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0ubWVtby5zaG91bGQuZXF1YWwoJycpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS50b2tlbk5hbWUuc2hvdWxkLmVxdWFsKCd0aGJhcjp1c2RjJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzFdLmFtb3VudC5zaG91bGQuZXF1YWwoJzE1Jyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzFdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcwLjAuNzg5NjMnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMV0udG9rZW5OYW1lLnNob3VsZC5lcXVhbCgndGhiYXI6dXNkYycpO1xuICAgIGV4cGxhaW4uZmVlLnNob3VsZC5lcXVhbCgxMTYwNDA3KTtcbiAgICBleHBsYWluLmNoYW5nZUFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBleHBsYWluIGEgdG9rZW4gYXNzb2NpYXRlIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHRva2VuQXNzb2NpYXRlUGFyYW0gPSB7XG4gICAgICB0eEhleDogVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFLFxuICAgICAgZmVlSW5mbzoge1xuICAgICAgICBzaXplOiAxMDAwLFxuICAgICAgICBmZWU6IDExNjA0MDcsXG4gICAgICAgIGZlZVJhdGU6IDExNjA0MDcsXG4gICAgICB9LFxuICAgIH07XG4gICAgY29uc3QgZXhwbGFpbiA9IGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih0b2tlbkFzc29jaWF0ZVBhcmFtKTtcblxuICAgIGV4cGxhaW4uaWQuc2hvdWxkLmVxdWFsKCcwLjAuODEzMjBAMTU5NjExMDQ5My4zNzI2NDY1NzAnKTtcbiAgICBleHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgICBleHBsYWluLnRpbWVzdGFtcC5zaG91bGQuZXF1YWwoJzE1OTYxMTA0OTMuMzcyNjQ2NTcwJyk7XG4gICAgZXhwbGFpbi5leHBpcmF0aW9uLnNob3VsZC5lcXVhbCgnMTgwJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoJzAnKTtcbiAgICBleHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoJzAuMC44MTMyMCcpO1xuICAgIGV4cGxhaW4ub3V0cHV0c1swXS5tZW1vLnNob3VsZC5lcXVhbCgnJyk7XG4gICAgZXhwbGFpbi5vdXRwdXRzWzBdLnRva2VuTmFtZS5zaG91bGQuZXF1YWwoJ3RoYmFyOnVzZGMnKTtcbiAgICBleHBsYWluLmZlZS5zaG91bGQuZXF1YWwoMTE2MDQwNyk7XG4gICAgZXhwbGFpbi5jaGFuZ2VBbW91bnQuc2hvdWxkLmVxdWFsKCcwJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IGlzV2FsbGV0QWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiYXNlQWRkcmVzcyA9ICcwLjAuNDEwOTgnO1xuICAgIGNvbnN0IHZhbGlkQWRkcmVzczEgPSAnMC4wLjQxMDk4P21lbW9JZD0xJztcbiAgICBjb25zdCB2YWxpZEFkZHJlc3MyID0gJzAuMC40MTA5OD9tZW1vSWQ9Mic7XG4gICAgY29uc3QgdW5yZWxhdGVkVmFsaWRBZGRyZXNzID0gJzAuMS40MTA5OD9tZW1vSWQ9MSc7XG4gICAgY29uc3QgaW52YWxpZEFkZHJlc3MgPSAnMC4wLjAuYSc7XG4gICAgKGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7IGFkZHJlc3M6IHZhbGlkQWRkcmVzczEsIGJhc2VBZGRyZXNzIH0pKS5zaG91bGQudHJ1ZSgpO1xuICAgIChhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3MoeyBhZGRyZXNzOiB2YWxpZEFkZHJlc3MyLCBiYXNlQWRkcmVzcyB9KSkuc2hvdWxkLnRydWUoKTtcbiAgICAoYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHsgYWRkcmVzczogdmFsaWRBZGRyZXNzMiwgYmFzZUFkZHJlc3M6IHZhbGlkQWRkcmVzczEgfSkpLnNob3VsZC50cnVlKCk7XG4gICAgKGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7IGFkZHJlc3M6IHVucmVsYXRlZFZhbGlkQWRkcmVzcywgYmFzZUFkZHJlc3MgfSkpLnNob3VsZC5mYWxzZSgpO1xuXG4gICAgYXNzZXJ0LnJlamVjdHMoXG4gICAgICBhc3luYyAoKSA9PiBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3MoeyBhZGRyZXNzOiBpbnZhbGlkQWRkcmVzcywgYmFzZUFkZHJlc3MgfSksXG4gICAgICBgaW52YWxpZCBhZGRyZXNzICR7aW52YWxpZEFkZHJlc3N9YFxuICAgICk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdLZXlwYWlyczonLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhIGtleXBhaXIgZnJvbSByYW5kb20gc2VlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBiYXNlY29pbi5nZW5lcmF0ZUtleVBhaXIoKTtcbiAgICAgIGtleVBhaXIuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3B1YicpO1xuICAgICAga2V5UGFpci5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHJ2Jyk7XG5cbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQdWIoa2V5UGFpci5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgYSBrZXlwYWlyIGZyb20gYSBzZWVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VlZFRleHQgPSAnODAzNTBiNDIwOGQzODFmYmZlMjI3NmEzMjY2MDMwNDlmZTUwMDczMWM0NmQzYzk5MzZiNWNlMDM2YjUxMzc3Zic7XG4gICAgICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oc2VlZFRleHQsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBiYXNlY29pbi5nZW5lcmF0ZUtleVBhaXIoc2VlZCk7XG5cbiAgICAgIGtleVBhaXIucHJ2LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzMwMmUwMjAxMDAzMDA1MDYwMzJiNjU3MDA0MjIwNDIwODAzNTBiNDIwOGQzODFmYmZlMjI3NmEzMjY2MDMwNDlmZTUwMDczMWM0NmQzYzk5MzZiNWNlMDM2YjUxMzc3ZidcbiAgICAgICk7XG4gICAgICBrZXlQYWlyLnB1Yi5zaG91bGQuZXF1YWwoXG4gICAgICAgICczMDJhMzAwNTA2MDMyYjY1NzAwMzIxMDA5Y2M0MDJiNWM3NTIxNDI2OWMyODI2ZTNjNjExOTM3N2NhYjZjMzY3NjAxMzM4NjYxYzg3YTRlMDdjNmUwMzMzJ1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgYSBzdGVsbGFyIHNlZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBiYXNlY29pbi5pc1N0ZWxsYXJTZWVkKCdTQk1XTE5WNzVCUEkyVkI0RzI3UldPTUFCVlJUU1NGNzM1MkNDWUdWRUxaRFNIQ1hXQ1lGS1hJWCcpLnNob3VsZC5vaygpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjb252ZXJ0IGEgc3RlbGxhciBzZWVkIHRvIGFuIGhiYXIgcHJ2JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2VlZCA9IGJhc2Vjb2luLmNvbnZlcnRGcm9tU3RlbGxhclNlZWQoJ1NCTVdMTlY3NUJQSTJWQjRHMjdSV09NQUJWUlRTU0Y3MzUyQ0NZR1ZFTFpEU0hDWFdDWUZLWElYJyk7XG4gICAgICBzZWVkLnNob3VsZC5lcXVhbChcbiAgICAgICAgJzMwMmUwMjAxMDAzMDA1MDYwMzJiNjU3MDA0MjIwNDIwNTk2NWI2YmZlODVlOGQ1NDNjMzZiZjFiMzk4MDBkNjMzOTQ4YmZkZjc0MjE2MGQ1MjJmMjM5MWM1N2IwYjA1NSdcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWZXJpZnkgVHJhbnNhY3Rpb246JywgKCkgPT4ge1xuICAgIGxldCBuZXdUeFByZWJ1aWxkO1xuICAgIGxldCBuZXdUeFBhcmFtcztcbiAgICBsZXQgbmV3VHhQYXJhbXNXaXRoRXJyb3I7XG4gICAgbGV0IG5ld1R4UGFyYW1zV2l0aEV4dHJhRGF0YTtcbiAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJ2xpb250ZXN0ZTIxMicsXG4gICAgICAgICAgYW1vdW50OiAnMTAwMCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgdHhIZXg6IFRlc3REYXRhLlVOU0lHTkVEX01VTFRJX1RSQU5TRkVSLFxuICAgICAgdHhpZDogJzU4NmM1YjU5YjEwYjEzNGQwNGMxNmFjMWIyNzNmZTNjNTUyOWYzNGFlZjc1ZGI0NDU2Y2Q0NjljNWNkYWM3ZTInLFxuICAgICAgaXNWb3RpbmdUcmFuc2FjdGlvbjogZmFsc2UsXG4gICAgICBjb2luOiAndGhiYXInLFxuICAgICAgZmVlSW5mbzoge1xuICAgICAgICBzaXplOiAxMDAwLFxuICAgICAgICBmZWU6IDExNjA0MDcsXG4gICAgICAgIGZlZVJhdGU6IDExNjA0MDcsXG4gICAgICB9LFxuICAgIH07XG4gICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICB0eFByZWJ1aWxkLFxuICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43NTg2MScsXG4gICAgICAgICAgYW1vdW50OiAnMTAnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43ODk2MycsXG4gICAgICAgICAgYW1vdW50OiAnMTUnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICAgIGNvbnN0IG1lbW8gPSB7IHZhbHVlOiAnJyB9O1xuICAgIGNvbnN0IHR4UGFyYW1zV2l0aEVycm9yID0ge1xuICAgICAgdHhQcmVidWlsZCxcbiAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzU4NjEnLFxuICAgICAgICAgIGFtb3VudDogJzEwMDAnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICAgIGNvbnN0IHR4UGFyYW1zV2l0aEV4dHJhRGF0YSA9IHtcbiAgICAgIHR4UHJlYnVpbGQsXG4gICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc1ODYxJyxcbiAgICAgICAgICBhbW91bnQ6ICcxMCcsXG4gICAgICAgICAgZGF0YTogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43ODk2MycsXG4gICAgICAgICAgYW1vdW50OiAnMTUnLFxuICAgICAgICAgIGRhdGE6IHVuZGVmaW5lZCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgICBjb25zdCB3YWxsZXREYXRhID0ge1xuICAgICAgaWQ6ICc1YjM0MjUyZjFiZjM0OTkzMGUzNDAyMGEwMDAwMDAwMCcsXG4gICAgICBjb2luOiAndGhiYXInLFxuICAgICAga2V5czogW1xuICAgICAgICAnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc1MDAwMDAwMDAnLFxuICAgICAgICAnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc2MDAwMDAwMDAnLFxuICAgICAgICAnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc3MDAwMDAwMDAnLFxuICAgICAgXSxcbiAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICBiYXNlQWRkcmVzczogJzAuMC4yOTM1JyxcbiAgICAgIH0sXG4gICAgICBtdWx0aXNpZ1R5cGU6ICdvbmNoYWluJyxcbiAgICB9O1xuICAgIGNvbnN0IHdhbGxldE9iaiA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB3YWxsZXREYXRhKTtcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBuZXdUeFByZWJ1aWxkID0gKCkgPT4ge1xuICAgICAgICByZXR1cm4gXy5jbG9uZURlZXAodHhQcmVidWlsZCk7XG4gICAgICB9O1xuICAgICAgbmV3VHhQYXJhbXMgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiBfLmNsb25lRGVlcCh0eFBhcmFtcyk7XG4gICAgICB9O1xuICAgICAgbmV3VHhQYXJhbXNXaXRoRXJyb3IgPSAoKSA9PiB7XG4gICAgICAgIHJldHVybiBfLmNsb25lRGVlcCh0eFBhcmFtc1dpdGhFcnJvcik7XG4gICAgICB9O1xuICAgICAgbmV3VHhQYXJhbXNXaXRoRXh0cmFEYXRhID0gKCkgPT4ge1xuICAgICAgICByZXR1cm4gXy5jbG9uZURlZXAodHhQYXJhbXNXaXRoRXh0cmFEYXRhKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBuYXRpdmUgdHJhbnNmZXIgdHJhbnNhY3Rpb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICBtZW1vLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldE9iaixcbiAgICAgIH0gYXMgYW55KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSB3aGVuIGlucHV0IGByZWNpcGllbnRzYCBpcyBhYnNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCBtZW1vOiBtZW1vLCB3YWxsZXQ6IHdhbGxldE9iaiB9IGFzIGFueSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcmVxdWlyZWQgdHggcGFyYW1zIHByb3BlcnR5IHJlY2lwaWVudHMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB2ZXJpZnkgdHJhbnNhY3Rpb25zIHdoZW4gaGF2ZSBkaWZmZXJlbnQgcmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXNXaXRoRXJyb3IoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgbWVtbywgd2FsbGV0OiB3YWxsZXRPYmogfSBhcyBhbnkpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdUeCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdHhQYXJhbXMgcmVjaXBpZW50cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzdWNjZWVkIHRvIHZlcmlmeSB0cmFuc2FjdGlvbnMgd2hlbiByZWNpcGllbnRzIGhhcyBleHRyYSBkYXRhJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtc1dpdGhFeHRyYURhdGEoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB2YWxpZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgdHhQcmVidWlsZCxcbiAgICAgICAgbWVtbyxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXRPYmosXG4gICAgICB9IGFzIGFueSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGNyZWF0ZSBhc3NvY2lhdGVkIHRva2VuIGFjY291bnQgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgdHhQcmVidWlsZC50eEhleCA9IFRlc3REYXRhLlVOU0lHTkVEX1RPS0VOX0FTU09DSUFURTtcbiAgICAgIHR4UGFyYW1zLnR5cGUgPSAnZW5hYmxldG9rZW4nO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuODEzMjAnLFxuICAgICAgICAgIGFtb3VudDogJzAnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHZhbGlkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zLFxuICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICBtZW1vLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldE9iaixcbiAgICAgICAgdmVyaWZpY2F0aW9uOiB7IHZlcmlmeVRva2VuRW5hYmxlbWVudDogdHJ1ZSB9LFxuICAgICAgfSBhcyBhbnkpO1xuICAgICAgdmFsaWRUcmFuc2FjdGlvbi5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdmVyaWZ5IGNyZWF0ZSBhc3NvY2lhdGVkIHRva2VuIGFjY291bnQgdHJhbnNhY3Rpb24gd2l0aCBtaXNtYXRjaCByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIHR4UHJlYnVpbGQudHhIZXggPSBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9BU1NPQ0lBVEU7XG4gICAgICB0eFBhcmFtcy50eXBlID0gJ2VuYWJsZXRva2VuJztcbiAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjgxMzIxJyxcbiAgICAgICAgICBhbW91bnQ6ICcwJyxcbiAgICAgICAgICB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zLFxuICAgICAgICAgIHR4UHJlYnVpbGQsXG4gICAgICAgICAgbWVtbyxcbiAgICAgICAgICB3YWxsZXQ6IHdhbGxldE9iaixcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHsgdmVyaWZ5VG9rZW5FbmFibGVtZW50OiB0cnVlIH0sXG4gICAgICAgIH0gYXMgYW55KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCB0b2tlbiBlbmFibGVtZW50IHRyYW5zYWN0aW9uOiBFeHBlY3RlZCBhY2NvdW50IDAuMC44MTMyMSwgZ290IDAuMC44MTMyMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdG9rZW4gdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgdHhQcmVidWlsZC50eEhleCA9IFRlc3REYXRhLlVOU0lHTkVEX1RPS0VOX01VTFRJX1RSQU5TRkVSO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzU4NjEnLFxuICAgICAgICAgIGFtb3VudDogJzEwJyxcbiAgICAgICAgICB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzg5NjMnLFxuICAgICAgICAgIGFtb3VudDogJzE1JyxcbiAgICAgICAgICB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCB2YWxpZFRyYW5zYWN0aW9uID0gYXdhaXQgdG9rZW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgdHhQcmVidWlsZCxcbiAgICAgICAgbWVtbyxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXRPYmosXG4gICAgICB9IGFzIGFueSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IHRva2VuIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGggYW55IHRva2VuIG5hbWUgb24gdG9rZW4gYmFzZSBjb2luJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcbiAgICAgIHR4UHJlYnVpbGQudHhIZXggPSBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9NVUxUSV9UUkFOU0ZFUjtcbiAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc1ODYxJyxcbiAgICAgICAgICBhbW91bnQ6ICcxMCcsXG4gICAgICAgICAgdG9rZW5OYW1lOiAndGhiYXI6dXNkYycsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMC4wLjc4OTYzJyxcbiAgICAgICAgICBhbW91bnQ6ICcxNScsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgKGF3YWl0IHRva2VuLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIG1lbW8sIHdhbGxldDogd2FsbGV0T2JqIH0gYXMgYW55KSkuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHZlcmlmeSB0b2tlbiB0cmFuc2ZlciB3aXRoIG1pc21hdGNoZWQgcmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICB0eFByZWJ1aWxkLnR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fTVVMVElfVFJBTlNGRVI7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43NTg2MScsXG4gICAgICAgICAgYW1vdW50OiAnMTEnLFxuICAgICAgICAgIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC43ODk2MycsXG4gICAgICAgICAgYW1vdW50OiAnMTUnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGF3YWl0IHRva2VuXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCBtZW1vLCB3YWxsZXQ6IHdhbGxldE9iaiB9IGFzIGFueSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmVyaWZ5IHRva2VuIHRyYW5zZmVyIHdpdGggaW5jb3JyZWN0IHRva2VuIG5hbWUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgdHhQcmVidWlsZC50eEhleCA9IFRlc3REYXRhLlVOU0lHTkVEX1RPS0VOX01VTFRJX1RSQU5TRkVSO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzU4NjEnLFxuICAgICAgICAgIGFtb3VudDogJzExJyxcbiAgICAgICAgICB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6ICcwLjAuNzg5NjMnLFxuICAgICAgICAgIGFtb3VudDogJzE1JyxcbiAgICAgICAgICB0b2tlbk5hbWU6ICdpbnZhbGlkdG9rZW4nLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGF3YWl0IHRva2VuXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCBtZW1vLCB3YWxsZXQ6IHdhbGxldE9iaiB9IGFzIGFueSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0luY29ycmVjdCB0b2tlbiBuYW1lIHNwZWNpZmllZCBpbiByZWNpcGllbnRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2Nlc3MgdG8gdmVyaWZ5IHRyYW5zZmVyIGhhdmluZyBhZGRyZXNzIHdpdGggbWVtbyBpZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICB0eFByZWJ1aWxkLnR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFO1xuICAgICAgdHhQYXJhbXMudHlwZSA9ICdlbmFibGV0b2tlbic7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogJzAuMC44MTMyMD9tZW1vSWQ9MScsXG4gICAgICAgICAgYW1vdW50OiAnMCcsXG4gICAgICAgICAgdG9rZW5OYW1lOiAndGhiYXI6dXNkYycsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgY29uc3QgdmFsaWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXMsXG4gICAgICAgIHR4UHJlYnVpbGQsXG4gICAgICAgIG1lbW8sXG4gICAgICAgIHdhbGxldDogd2FsbGV0T2JqLFxuICAgICAgICB2ZXJpZmljYXRpb246IHsgdmVyaWZ5VG9rZW5FbmFibGVtZW50OiB0cnVlIH0sXG4gICAgICB9IGFzIGFueSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1ZlcmlmeSBUb2tlbiBFbmFibGVtZW50IFRyYW5zYWN0aW9uOicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIHRva2VuIGVuYWJsZW1lbnQgdHJhbnNhY3Rpb24gd2l0aCB0b2tlbk5hbWUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9IFRlc3REYXRhLlVOU0lHTkVEX1RPS0VOX0FTU09DSUFURTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVG9rZW4gPSB7IHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH07XG4gICAgICBjb25zdCBleHBlY3RlZEFjY291bnRJZCA9ICcwLjAuODEzMjAnO1xuXG4gICAgICBhd2FpdCBiYXNlY29pbi52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbih0eEhleCwgZXhwZWN0ZWRUb2tlbiwgZXhwZWN0ZWRBY2NvdW50SWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCB0b2tlbiBlbmFibGVtZW50IHRyYW5zYWN0aW9uIHdpdGggdG9rZW5JZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUb2tlbiA9IHsgdG9rZW5JZDogJzAuMC40MjkyNzQnIH07IC8vIEFjdHVhbCB0b2tlbklkIGZvciB0aGJhcjp1c2RjXG4gICAgICBjb25zdCBleHBlY3RlZEFjY291bnRJZCA9ICcwLjAuODEzMjAnO1xuXG4gICAgICBhd2FpdCBiYXNlY29pbi52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbih0eEhleCwgZXhwZWN0ZWRUb2tlbiwgZXhwZWN0ZWRBY2NvdW50SWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdoZW4gdHhIZXggaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbignJywgeyB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyB9LCAnMC4wLjgxMzIwJylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ01pc3NpbmcgcmVxdWlyZWQgcGFyYW1ldGVyczogdHhIZXgnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB3aGVuIGV4cGVjdGVkQWNjb3VudElkIGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VG9rZW5FbmFibGVtZW50VHJhbnNhY3Rpb24oVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFLCB7IHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH0sICcnKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnTWlzc2luZyByZXF1aXJlZCBwYXJhbWV0ZXJzOiBleHBlY3RlZEFjY291bnRJZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdoZW4gd2FsbGV0IHBsYXRmb3JtIHNlbmRzIHNwb29mZWQgdHJhbnNhY3Rpb24gaGV4IGZvciB0b2tlbiBlbmFibGVtZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQ3JlYXRlIGEgdmFsaWQgdHJhbnNhY3Rpb24gcmVzcG9uc2Ugc3RydWN0dXJlIGZyb20gd2FsbGV0IHBsYXRmb3JtIHdpdGggc3Bvb2ZlZCB0eEhleFxuICAgICAgLy8gVGhlIHR4SGV4IGxvb2tzIGxpa2UgdmFsaWQgaGV4IGJ1dCBjb250YWlucyBtYWxpY2lvdXMvaW52YWxpZCB0cmFuc2FjdGlvbiBkYXRhXG4gICAgICBjb25zdCBzcG9vZmVkVHhIZXggPSAnMGEwYzBhMDgwODAwMTAwMDE4YThmYjA0MTAxMzBhMGMwYTA4MDgwMDEwMDAxOGQ1ZDAwNDEwMTQnOyAvLyBWYWxpZCBoZXggYnV0IGludmFsaWQgdHJhbnNhY3Rpb25cblxuICAgICAgLy8gTW9jayB0aGUgQVBJIGVuZHBvaW50cyB0aGF0IHdpbGwgYmUgY2FsbGVkIGR1cmluZyB0b2tlbiBlbmFibGVtZW50XG4gICAgICBjb25zdCBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbJ21vY2snXS51cmk7XG5cbiAgICAgIC8vIE1vY2sgdGhlIGtleSBlbmRwb2ludCBuZWVkZWQgZm9yIHNpZ25pbmdcbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KCcvYXBpL3YyL3RoYmFyL2tleS81YjM0MjRmOTFiZjM0OTkzMDA2ZWFlOTQnKVxuICAgICAgICAucmVwbHkoMjAwLCBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiAnZmFrZVBydicsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG5cbiAgICAgIC8vIE1vY2sgdGhlIHByZWJ1aWxkIEFQSSByZXNwb25zZSB0byByZXR1cm4gc3Bvb2ZlZCB0eEhleFxuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLnBvc3QoJy9hcGkvdjIvdGhiYXIvd2FsbGV0LzViMzQyNTJmMWJmMzQ5OTMwMDZlYWU5Ni90eC9idWlsZCcpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICB0eEhleDogc3Bvb2ZlZFR4SGV4LFxuICAgICAgICAgIHR4aWQ6ICc1ODZjNWI1OWIxMGIxMzRkMDRjMTZhYzFiMjczZmUzYzU1MjlmMzRhZWY3NWRiNDQ1NmNkNDY5YzVjZGFjN2UyJyxcbiAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6ICcwLjAuODEzMjAnLFxuICAgICAgICAgICAgICBhbW91bnQ6ICcwJywgLy8gVmFsaWQgYW1vdW50IGZvciB0b2tlbiBlbmFibGVtZW50XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgY29pbjogJ3RoYmFyJyxcbiAgICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgICBzaXplOiAxMDAwLFxuICAgICAgICAgICAgZmVlOiAxMTYwNDA3LFxuICAgICAgICAgICAgZmVlUmF0ZTogMTE2MDQwNyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgLy8gVGhpcyBzaG91bGQgZmFpbCBiZWNhdXNlIHRoZSBzcG9vZmVkIHRyYW5zYWN0aW9uIGhleCBjb250YWlucyBpbnZhbGlkIHRyYW5zYWN0aW9uIGRhdGFcbiAgICAgIC8vIFRoZSB2ZXJpZmljYXRpb24gbG9naWMgc2hvdWxkIGNhdGNoIHRoaXMgd2hlbiB0cnlpbmcgdG8gdmFsaWRhdGUgdGhlIHRyYW5zYWN0aW9uXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIC8vIFRlc3QgdGhlIHZlcmlmaWNhdGlvbiBkaXJlY3RseSBpbnN0ZWFkIG9mIGdvaW5nIHRocm91Z2ggdGhlIHdhbGxldCBmbG93XG4gICAgICAgICAgYXdhaXQgYmFzZWNvaW4udmVyaWZ5VG9rZW5FbmFibGVtZW50VHJhbnNhY3Rpb24oc3Bvb2ZlZFR4SGV4LCB7IHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH0sICcwLjAuODEzMjAnKTtcbiAgICAgICAgfSxcbiAgICAgICAgKGVycm9yOiBhbnkpID0+IHtcbiAgICAgICAgICAvLyBUaGUgZXJyb3Igc2hvdWxkIGluZGljYXRlIHRoYXQgdGhlIHRyYW5zYWN0aW9uIGlzIGludmFsaWRcbiAgICAgICAgICByZXR1cm4gZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnSW52YWxpZCB0b2tlbiBlbmFibGVtZW50IHRyYW5zYWN0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2hlbiBib3RoIHRva2VuSWQgYW5kIHRva2VuTmFtZSBhcmUgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbihUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9BU1NPQ0lBVEUsIHt9LCAnMC4wLjgxMzIwJylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ01pc3NpbmcgcmVxdWlyZWQgcGFyYW1ldGVyczogZXhwZWN0ZWRUb2tlbi50b2tlbklkfHRva2VuTmFtZScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdoZW4gdG9rZW4gbmFtZSBkb2VzIG5vdCBtYXRjaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbihcbiAgICAgICAgICBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9BU1NPQ0lBVEUsXG4gICAgICAgICAgeyB0b2tlbk5hbWU6ICd0aGJhcjp3cm9uZ3Rva2VuJyB9LFxuICAgICAgICAgICcwLjAuODEzMjAnXG4gICAgICAgIClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL0V4cGVjdGVkIHRva2VuIG5hbWUgdGhiYXI6d3Jvbmd0b2tlbiwgZ290IHRoYmFyOnVzZGMvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB3aGVuIGFjY291bnQgSUQgZG9lcyBub3QgbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VG9rZW5FbmFibGVtZW50VHJhbnNhY3Rpb24oVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFLCB7IHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH0sICcwLjAuOTk5OTknKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvRXhwZWN0ZWQgYWNjb3VudCAwLjAuOTk5OTksIGdvdCAwLjAuODEzMjAvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB3aGVuIHRyYW5zYWN0aW9uIGlzIG5vdCBhIHRva2VuIGVuYWJsZW1lbnQgKGhhcyBub24temVybyBhbW91bnQpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVXNlIGEgcmVndWxhciB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aGljaCBoYXMgbm9uLXplcm8gYW1vdW50XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VG9rZW5FbmFibGVtZW50VHJhbnNhY3Rpb24oVGVzdERhdGEuVU5TSUdORURfVE9LRU5fVFJBTlNGRVIsIHsgdG9rZW5OYW1lOiAndGhiYXI6dXNkYycgfSwgJzAuMC44MTMyMCcpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9FeHBlY3RlZCBvdXRwdXQgYW1vdW50ICcwJy8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdoZW4gdHJhbnNhY3Rpb24gdHlwZSBpcyBub3QgdG9rZW5Bc3NvY2lhdGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBVc2UgYSByZWd1bGFyIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdoaWNoIGlzIG5vdCB0b2tlbkFzc29jaWF0ZVxuICAgICAgLy8gVGhpcyB3aWxsIGZhaWwgb24gYW1vdW50IHZhbGlkYXRpb24gZmlyc3QsIGJ1dCB0aGF0J3MgZXhwZWN0ZWQgYmVoYXZpb3JcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbihUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9UUkFOU0ZFUiwgeyB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyB9LCAnMC4wLjgxMzIwJylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL0V4cGVjdGVkIG91dHB1dCBhbW91bnQgJzAnLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHRyYW5zYWN0aW9uIHR5cGUgZm9yIHZhbGlkIHRva2VuIGFzc29jaWF0ZSB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFRoaXMgdGVzdCBlbnN1cmVzIHRoZSB0cmFuc2FjdGlvbiB0eXBlIHZhbGlkYXRpb24gd29ya3MgZm9yIHZhbGlkIHRva2VuIGFzc29jaWF0ZSB0cmFuc2FjdGlvbnNcbiAgICAgIGNvbnN0IHR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFO1xuICAgICAgY29uc3QgZXhwZWN0ZWRUb2tlbiA9IHsgdG9rZW5OYW1lOiAndGhiYXI6dXNkYycgfTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkQWNjb3VudElkID0gJzAuMC44MTMyMCc7XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRva2VuRW5hYmxlbWVudFRyYW5zYWN0aW9uKHR4SGV4LCBleHBlY3RlZFRva2VuLCBleHBlY3RlZEFjY291bnRJZCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2l0aCBpbnZhbGlkIHRyYW5zYWN0aW9uIGhleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbignaW52YWxpZF9oZXgnLCB7IHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH0sICcwLjAuODEzMjAnKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvSW52YWxpZCB0b2tlbiBlbmFibGVtZW50IHRyYW5zYWN0aW9uLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2hlbiB0eEhleCBjb250YWlucyB3cm9uZyB0b2tlbklkIGNvbXBhcmVkIHRvIGV4cGVjdGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGhpcyB0ZXN0IGVuc3VyZXMgZGlyZWN0IHR4SGV4IHZhbGlkYXRpb24gY2F0Y2hlcyBzcG9vZmVkIHRva2VuSWRzXG4gICAgICBjb25zdCB0eEhleCA9IFRlc3REYXRhLlVOU0lHTkVEX1RPS0VOX0FTU09DSUFURTtcbiAgICAgIGNvbnN0IHdyb25nVG9rZW5JZCA9ICcwLjAuOTk5OTk5JzsgLy8gV3JvbmcgdG9rZW5JZFxuICAgICAgY29uc3QgZXhwZWN0ZWRBY2NvdW50SWQgPSAnMC4wLjgxMzIwJztcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRva2VuRW5hYmxlbWVudFRyYW5zYWN0aW9uKHR4SGV4LCB7IHRva2VuSWQ6IHdyb25nVG9rZW5JZCB9LCBleHBlY3RlZEFjY291bnRJZClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgbmV3IFJlZ0V4cChgRXhwZWN0ZWQgdG9rZW5JZCAke18uZXNjYXBlUmVnRXhwKHdyb25nVG9rZW5JZCl9LCBidXQgdHJhbnNhY3Rpb24gY29udGFpbnMgdG9rZW5JZGApXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2hlbiB0eEhleCBjb250YWlucyB3cm9uZyBhY2NvdW50SWQgY29tcGFyZWQgdG8gZXhwZWN0ZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUaGlzIHRlc3QgZW5zdXJlcyBkaXJlY3QgdHhIZXggdmFsaWRhdGlvbiBjYXRjaGVzIHNwb29mZWQgYWNjb3VudElkc1xuICAgICAgY29uc3QgdHhIZXggPSBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9BU1NPQ0lBVEU7XG4gICAgICBjb25zdCBleHBlY3RlZFRva2VuID0geyB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyB9O1xuICAgICAgY29uc3Qgd3JvbmdBY2NvdW50SWQgPSAnMC4wLjk5OTk5OSc7IC8vIFdyb25nIGFjY291bnRJZFxuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VG9rZW5FbmFibGVtZW50VHJhbnNhY3Rpb24odHhIZXgsIGV4cGVjdGVkVG9rZW4sIHdyb25nQWNjb3VudElkKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChuZXcgUmVnRXhwKGBFeHBlY3RlZCBhY2NvdW50ICR7Xy5lc2NhcGVSZWdFeHAod3JvbmdBY2NvdW50SWQpfSwgZ290YCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXNzIHZlcmlmaWNhdGlvbiBmb3IgdmFsaWQgdG9rZW4gZW5hYmxlbWVudCB0cmFuc2FjdGlvbiB3aXRob3V0IHRocm93aW5nIGVycm9yJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGhpcyB0ZXN0IGVuc3VyZXMgdGhhdCBhIHZhbGlkIHRva2VuIGVuYWJsZW1lbnQgdHJhbnNhY3Rpb24gcGFzc2VzIGFsbCB2YWxpZGF0aW9uc1xuICAgICAgY29uc3QgdHhIZXggPSBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9BU1NPQ0lBVEU7XG4gICAgICBjb25zdCBleHBlY3RlZFRva2VuID0geyB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyB9O1xuICAgICAgY29uc3QgZXhwZWN0ZWRBY2NvdW50SWQgPSAnMC4wLjgxMzIwJztcblxuICAgICAgLy8gVGhpcyBzaG91bGQgY29tcGxldGUgd2l0aG91dCB0aHJvd2luZyBhbnkgZXJyb3JzXG4gICAgICBhd2FpdCBiYXNlY29pbi52ZXJpZnlUb2tlbkVuYWJsZW1lbnRUcmFuc2FjdGlvbih0eEhleCwgZXhwZWN0ZWRUb2tlbiwgZXhwZWN0ZWRBY2NvdW50SWQpO1xuXG4gICAgICAvLyBJZiB3ZSByZWFjaCB0aGlzIHBvaW50LCB0aGUgdGVzdCBwYXNzZWRcbiAgICAgIGFzc2VydC5vayh0cnVlLCAnVmFsaWQgdG9rZW4gZW5hYmxlbWVudCB0cmFuc2FjdGlvbiBzaG91bGQgbm90IHRocm93IGFueSBlcnJvcnMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3VjY2Vzc2Z1bGx5IGNvbXBsZXRlIHNlbmRUb2tlbkVuYWJsZW1lbnRzIHdpdGggdmFsaWQgdHJhbnNhY3Rpb24gcmVzcG9uc2UgZnJvbSB3YWxsZXQgcGxhdGZvcm0nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2YWxpZFR4SGV4ID0gVGVzdERhdGEuVU5TSUdORURfVE9LRU5fQVNTT0NJQVRFO1xuXG4gICAgICBjb25zdCB3YWxsZXQgPSB7XG4gICAgICAgIGlkOiAoKSA9PiAnNWIzNDI1MmYxYmYzNDk5MzAwNmVhZTk2JyxcbiAgICAgICAgY29pbjogKCkgPT4gJ3RoYmFyJyxcbiAgICAgICAgcHJlYnVpbGRUcmFuc2FjdGlvbjogYXN5bmMgKCkgPT4gKHtcbiAgICAgICAgICB0eEhleDogdmFsaWRUeEhleCwgLy8gVmFsaWQgdG9rZW4gYXNzb2NpYXRlIHRyYW5zYWN0aW9uXG4gICAgICAgICAgdHhpZDogJzU4NmM1YjU5YjEwYjEzNGQwNGMxNmFjMWIyNzNmZTNjNTUyOWYzNGFlZjc1ZGI0NDU2Y2Q0NjljNWNkYWM3ZTInLFxuICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6ICcwLjAuODEzMjAnLCBhbW91bnQ6ICcwJyB9XSxcbiAgICAgICAgICBjb2luOiAndGhiYXInLFxuICAgICAgICAgIGZlZUluZm86IHsgc2l6ZTogMTAwMCwgZmVlOiAxMTYwNDA3LCBmZWVSYXRlOiAxMTYwNDA3IH0sXG4gICAgICAgIH0pLFxuICAgICAgICBzZW5kVG9rZW5FbmFibGVtZW50czogYXN5bmMgKHBhcmFtczogYW55KSA9PiB7XG4gICAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IGF3YWl0IHdhbGxldC5wcmVidWlsZFRyYW5zYWN0aW9uKCk7XG4gICAgICAgICAgYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzAuMC44MTMyMCcsIGFtb3VudDogJzAnLCB0b2tlbk5hbWU6ICd0aGJhcjp1c2RjJyB9XSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICAgICAgdmVyaWZpY2F0aW9uOiB7IHZlcmlmeVRva2VuRW5hYmxlbWVudDogdHJ1ZSB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN1Y2Nlc3M6IFt7IHR4aWQ6IHR4UHJlYnVpbGQudHhpZCwgc3RhdHVzOiAnc3VjY2VzcycgfV0sXG4gICAgICAgICAgICBmYWlsdXJlOiBbXSxcbiAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgd2FsbGV0LnNlbmRUb2tlbkVuYWJsZW1lbnRzKHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzAuMC44MTMyMCcsIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH1dLFxuICAgICAgfSk7XG5cbiAgICAgIGFzc2VydC5vayhcbiAgICAgICAgdHJ1ZSxcbiAgICAgICAgJ1ZhbGlkIHRva2VuIGVuYWJsZW1lbnQgdHJhbnNhY3Rpb24gc2hvdWxkIGNvbXBsZXRlIHN1Y2Nlc3NmdWxseSB0aHJvdWdoIHNlbmRUb2tlbkVuYWJsZW1lbnRzIGZsb3cnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBkZXRlY3Qgc3Bvb2ZlZCB0cmFuc2FjdGlvbiBoZXggdGhyb3VnaCBzZW5kVG9rZW5FbmFibGVtZW50cyBmbG93JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVXNlIGEgdmFsaWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24gaGV4IGluc3RlYWQgb2YgYSB0b2tlbiBhc3NvY2lhdGUgdHJhbnNhY3Rpb25cbiAgICAgIC8vIFRoaXMgd2lsbCBwYXJzZSBjb3JyZWN0bHkgYnV0IGZhaWwgdmFsaWRhdGlvbiBiZWNhdXNlIGl0J3Mgbm90IGEgdG9rZW4gYXNzb2NpYXRlIHRyYW5zYWN0aW9uXG4gICAgICBjb25zdCBzcG9vZmVkVHhIZXggPSBUZXN0RGF0YS5VTlNJR05FRF9UT0tFTl9UUkFOU0ZFUjsgLy8gVmFsaWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24sIG5vdCB0b2tlbiBhc3NvY2lhdGVcblxuICAgICAgLy8gQ3JlYXRlIGEgd2FsbGV0IG1vY2sgZm9yIHRoZSBzZW5kVG9rZW5FbmFibGVtZW50cyBmbG93XG4gICAgICBjb25zdCB3YWxsZXQgPSB7XG4gICAgICAgIGlkOiAoKSA9PiAnNWIzNDI1MmYxYmYzNDk5MzAwNmVhZTk2JyxcbiAgICAgICAgY29pbjogKCkgPT4gJ3RoYmFyJyxcbiAgICAgICAgcHJlYnVpbGRUcmFuc2FjdGlvbjogYXN5bmMgKCkgPT4gKHtcbiAgICAgICAgICB0eEhleDogc3Bvb2ZlZFR4SGV4LFxuICAgICAgICAgIHR4aWQ6ICc1ODZjNWI1OWIxMGIxMzRkMDRjMTZhYzFiMjczZmUzYzU1MjlmMzRhZWY3NWRiNDQ1NmNkNDY5YzVjZGFjN2UyJyxcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMC4wLjgxMzIwJywgYW1vdW50OiAnMCcgfV0sXG4gICAgICAgICAgY29pbjogJ3RoYmFyJyxcbiAgICAgICAgICBmZWVJbmZvOiB7IHNpemU6IDEwMDAsIGZlZTogMTE2MDQwNywgZmVlUmF0ZTogMTE2MDQwNyB9LFxuICAgICAgICB9KSxcbiAgICAgICAgc2VuZFRva2VuRW5hYmxlbWVudHM6IGFzeW5jIChwYXJhbXM6IGFueSkgPT4ge1xuICAgICAgICAgIC8vIFRoaXMgc2hvdWxkIHRyaWdnZXIgdGhlIHZlcmlmaWNhdGlvbiBhbmQgZmFpbFxuICAgICAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBhd2FpdCB3YWxsZXQucHJlYnVpbGRUcmFuc2FjdGlvbigpO1xuICAgICAgICAgIHJldHVybiBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMC4wLjgxMzIwJywgYW1vdW50OiAnMCcsIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH1dLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHR4UHJlYnVpbGQsXG4gICAgICAgICAgICB2ZXJpZmljYXRpb246IHsgdmVyaWZ5VG9rZW5FbmFibGVtZW50OiB0cnVlIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICAvLyBUaGlzIHNob3VsZCBmYWlsIGJlY2F1c2UgdGhlIHNwb29mZWQgdHJhbnNhY3Rpb24gaGV4IGNvbnRhaW5zIGEgdHJhbnNmZXIgdHJhbnNhY3Rpb24sIG5vdCBhIHRva2VuIGFzc29jaWF0ZVxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICBhd2FpdCB3YWxsZXQuc2VuZFRva2VuRW5hYmxlbWVudHMoe1xuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzAuMC44MTMyMCcsIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH1dLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAoZXJyb3I6IGFueSkgPT4ge1xuICAgICAgICAgIC8vIFRoZSBlcnJvciBzaG91bGQgaW5kaWNhdGUgdGhhdCB0aGUgdHJhbnNhY3Rpb24gaXMgaW52YWxpZCBmb3IgdG9rZW4gZW5hYmxlbWVudFxuICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdJbnZhbGlkIHRva2VuIGVuYWJsZW1lbnQgdHJhbnNhY3Rpb24nKSB8fFxuICAgICAgICAgICAgZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnVG9rZW4gZW5hYmxlbWVudCB0cmFuc2FjdGlvbiBtaXNzaW5nIHRva2VuSWQnKSB8fFxuICAgICAgICAgICAgZXJyb3IubWVzc2FnZS5pbmNsdWRlcyhcIkV4cGVjdGVkIG91dHB1dCBhbW91bnQgJzAnXCIpIHx8XG4gICAgICAgICAgICBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdUcmFuc2FjdGlvbiBpcyBub3QgYSBUb2tlbkFzc29jaWF0ZSB0cmFuc2FjdGlvbicpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1NpZ24gTWVzc2FnZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJlIHBlcmZvcm1lZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgS2V5UGFpcigpO1xuICAgICAgY29uc3QgbWVzc2FnZVRvU2lnbiA9IEJ1ZmZlci5mcm9tKHJhbmRvbUJ5dGVzKDMyKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2Uoa2V5UGFpci5nZXRLZXlzKCksIG1lc3NhZ2VUb1NpZ24pO1xuICAgICAga2V5UGFpci52ZXJpZnlTaWduYXR1cmUobWVzc2FnZVRvU2lnbiwgVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKHNpZ25hdHVyZSwgJ2hleCcpKSkuc2hvdWxkLmVxdWFscyh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB3aXRoIG1pc3NpbmcgcHJpdmF0ZSBrZXknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gbmV3IEtleVBhaXIoe1xuICAgICAgICBwdWI6ICczMDJhMzAwNTA2MDMyYjY1NzAwMzIxMDBkOGZkNzQ1MzYxZGYyNzA3NzZhM2FiMWI1NWQ1NTkwZWMwMGEyNmFiNDVlZWEzNzE5N2RjOTg5NGE4MWZjYjgyJyxcbiAgICAgIH0pLmdldEtleXMoKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VUb1NpZ24gPSBCdWZmZXIuZnJvbShyYW5kb21CeXRlcygzMikpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luLnNpZ25NZXNzYWdlKGtleVBhaXIsIG1lc3NhZ2VUb1NpZ24pLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQga2V5IHBhaXIgb3B0aW9ucycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiB0cmFuc2FjdGlvbjonLCAoKSA9PiB7XG4gICAgY29uc3QgZGVzdGluYXRpb24gPSAnMC4wLjEyOTM2OSc7XG4gICAgY29uc3Qgc291cmNlID0gJzAuMC4xMjM0JztcbiAgICBjb25zdCBhbW91bnQgPSAnMTAwMDAwJztcbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiB1bnNpZ25lZCBhY2NvdW50LWxpYiBtdWx0aS1zaWduYXR1cmUgc2VuZCB0cmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBkZXN0aW5hdGlvbiBUaGUgZGVzdGluYXRpb24gYWRkcmVzcyBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgKiBAcGFyYW0gc291cmNlIFRoZSBhY2NvdW50IHNlbmRpbmcgdGhpc3QgcmFuc2FjdGlvblxuICAgICAqIEBwYXJhbSBhbW91bnQgVGhlIGFtb3VudCB0byBzZW5kIHRvIHRoZSByZWNpcGllbnRcbiAgICAgKi9cbiAgICBjb25zdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhc3luYyBmdW5jdGlvbiAoeyBkZXN0aW5hdGlvbiwgc291cmNlLCBhbW91bnQgPSAnMTAwMDAwJyB9KSB7XG4gICAgICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RoYmFyJyk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICAgIGZlZTogJzEwMDAwMCcsXG4gICAgICB9KTtcbiAgICAgIHR4QnVpbGRlci5zb3VyY2UoeyBhZGRyZXNzOiBzb3VyY2UgfSk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh7IGFkZHJlc3M6IGRlc3RpbmF0aW9uLCBhbW91bnQgfSk7XG5cbiAgICAgIHJldHVybiBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9O1xuXG4gICAgaXQoJ3Nob3VsZCBzaWduIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5ID0gbmV3IEtleVBhaXIoKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oe1xuICAgICAgICBkZXN0aW5hdGlvbixcbiAgICAgICAgc291cmNlLFxuICAgICAgICBhbW91bnQsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICBwcnY6IGtleS5nZXRLZXlzKCkucHJ2IS50b1N0cmluZygpLFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RoYmFyJyk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmZyb20odHguaGFsZlNpZ25lZC50eEhleCk7XG4gICAgICBjb25zdCBzaWduZWRUeCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgdHhKc29uID0gc2lnbmVkVHgudG9Kc29uKCkgYXMgVHhEYXRhO1xuICAgICAgdHhKc29uLnNob3VsZC5oYXZlLnByb3BlcnRpZXMoJ3RvJywgJ2Ftb3VudCcpO1xuICAgICAgdHhKc29uLnRvPy5zaG91bGQuZXF1YWwoZGVzdGluYXRpb24pO1xuICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHNvdXJjZSk7XG4gICAgICB0eEpzb24uYW1vdW50Py5zaG91bGQuZXF1YWwoYW1vdW50KTtcbiAgICAgICh0eEpzb24uaW5zdHJ1Y3Rpb25zRGF0YSBhcyBUcmFuc2ZlcikucGFyYW1zLnJlY2lwaWVudHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IGRlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4LnNpZ25hdHVyZS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmdWxseSBzaWduIHRyYW5zYWN0aW9uIHdpdGggcm9vdCBrZXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXkxID0gYmFzZWNvaW4uZ2VuZXJhdGVSb290S2V5UGFpcigpO1xuICAgICAgY29uc3Qga2V5MiA9IGJhc2Vjb2luLmdlbmVyYXRlUm9vdEtleVBhaXIoKTtcblxuICAgICAgY29uc3QgdW5zaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICAgIGRlc3RpbmF0aW9uLFxuICAgICAgICBzb3VyY2UsXG4gICAgICAgIGFtb3VudCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eEhhbGZTaWduZWQgPSBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICBwcnY6IGtleTEucHJ2LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RoYmFyJyk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXJIYWxmU2lnbmVkID0gZmFjdG9yeS5mcm9tKHR4SGFsZlNpZ25lZC5oYWxmU2lnbmVkLnR4SGV4KTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeCA9IGF3YWl0IHR4QnVpbGRlckhhbGZTaWduZWQuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeEpzb24gPSBoYWxmU2lnbmVkVHgudG9Kc29uKCkgYXMgVHhEYXRhO1xuICAgICAgaGFsZlNpZ25lZFR4SnNvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0aWVzKCd0bycsICdhbW91bnQnKTtcbiAgICAgIGhhbGZTaWduZWRUeEpzb24udG8/LnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICBoYWxmU2lnbmVkVHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHNvdXJjZSk7XG4gICAgICBoYWxmU2lnbmVkVHhKc29uLmFtb3VudD8uc2hvdWxkLmVxdWFsKGFtb3VudCk7XG4gICAgICAoaGFsZlNpZ25lZFR4SnNvbi5pbnN0cnVjdGlvbnNEYXRhIGFzIFRyYW5zZmVyKS5wYXJhbXMucmVjaXBpZW50c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgIH0pO1xuICAgICAgaGFsZlNpZ25lZFR4LnNpZ25hdHVyZS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICBjb25zdCB0eFNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHBydjoga2V5Mi5wcnYsXG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogaGFsZlNpZ25lZFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyU2lnbmVkID0gZmFjdG9yeS5mcm9tKHR4U2lnbmVkLnR4SGV4KTtcbiAgICAgIGNvbnN0IHNpZ25lZFR4ID0gYXdhaXQgdHhCdWlsZGVyU2lnbmVkLmJ1aWxkKCk7XG4gICAgICBjb25zdCBzaWduZWRUeEpzb24gPSBzaWduZWRUeC50b0pzb24oKSBhcyBUeERhdGE7XG4gICAgICBzaWduZWRUeEpzb24uc2hvdWxkLmhhdmUucHJvcGVydGllcygndG8nLCAnYW1vdW50Jyk7XG4gICAgICBzaWduZWRUeEpzb24udG8/LnNob3VsZC5lcXVhbChkZXN0aW5hdGlvbik7XG4gICAgICBzaWduZWRUeEpzb24uZnJvbS5zaG91bGQuZXF1YWwoc291cmNlKTtcbiAgICAgIHNpZ25lZFR4SnNvbi5hbW91bnQ/LnNob3VsZC5lcXVhbChhbW91bnQpO1xuICAgICAgKHNpZ25lZFR4SnNvbi5pbnN0cnVjdGlvbnNEYXRhIGFzIFRyYW5zZmVyKS5wYXJhbXMucmVjaXBpZW50c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogZGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkVHguc2lnbmF0dXJlLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWNvdmVyeScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBkZWZhdWx0VmFsaWREdXJhdGlvbiA9ICcxODAnO1xuICAgIGNvbnN0IGRlZmF1bHRGZWUgPSAxMDAwMDAwMDtcbiAgICBjb25zdCBkZWZhdWx0Tm9kZUlkID0gJzAuMC4zJztcbiAgICBjb25zdCB1c2VyS2V5ID1cbiAgICAgICd7XCJpdlwiOlwiV2xQdUpPZWpSV2dqL05UZDNVTWdydz09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MjU2LFwidHNcIjo2NCxcIm1vZGVcIjpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIjZ5QVZGdnJlSFNRPVwiLFwiY3RcIjpcIjhqL2xCVmtGQnlLbFZoYVM5SldtbUxqYTV5VG9ramFJaUxEeE1JRGpNb2pWRWltOVQzNldBbTVxVzZ2MVYwQTdRY0V1R2lWbDNQS01EYStHcjZ0SS9IVDU4RFc1UkUrcEh6eWE5TVVRcEFnTnJKcjhWRVdqclhXcVpFQ1Z0cmExL2JLQ3lCK21vemM9XCJ9JztcbiAgICBjb25zdCB1c2VyUHViID0gJzMwMmEzMDA1MDYwMzJiNjU3MDAzMjEwMGRkZDUzYTE1OTFkNzJiMTgxMTA5YmQzZTU3YjE4NjAzNzQwNDkwYjlhYjRkMzdiYzdmYTI3NDgwZTZiOGM5MTEnO1xuICAgIGNvbnN0IGJhY2t1cEtleSA9XG4gICAgICAne1wiaXZcIjpcIkQ1RFZEb3pReDlCMDJKZUZWMC9PVkE9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjI1NixcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCI3RlVORjhNMzVibz1cIixcImN0XCI6XCJaaVBzdTVRZS9BSVM0SlFYdCtycnVzSG5ZQ3k0Q3F1ck0xNlI1d0pyZDRDRXg3dTg1eTN5eTVFcm5zZHlZWWNjM3R4eU5tVUlRMi9DQnEvTEtvS08vVkllVSsrQ25LeHpHdUhHY05JNDdCUGszUlFLNDJhNjZ1SVFuL3lUUisrWGdkSzFLaHZVTDNVPVwifSc7XG4gICAgY29uc3QgYmFja3VwUHViID0gJzMwMmEzMDA1MDYwMzJiNjU3MDAzMjEwMDYyOTNlNGVjOWJmMWIyZDhmYWU2MzExMTkxMDcyNDhhNjVlMjIwN2EwNWQzMmExMWY0MmNjM2Q5YTMwMDVkNGEnO1xuICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gJzAuMC43NjcxMTg2JztcbiAgICBjb25zdCB3YWxsZXRQYXNzcGhyYXNlID0gJ1Rlc3RQYXNzd29yZFBsZWFzZUlnbm9yZSc7XG4gICAgY29uc3QgcmVjb3ZlcnlEZXN0aW5hdGlvbiA9ICcwLjAuNzY1MTkwOCc7XG4gICAgY29uc3QgYml0Z29LZXkgPSAnNWE5M2IwMWVhODdlOTYzZjYxYzk3NGE4OWQ2MmUzODQxMzkyZjFiYTAyMGZiYmNjNjVhODA4OWNhMDI1YWJiYic7XG4gICAgY29uc3QgbWVtbyA9ICc0JztcbiAgICBjb25zdCBiYWxhbmNlID0gJzEwMDAwMDAwMDAnO1xuICAgIGNvbnN0IGZvcm1hdEJhbGFuY2VSZXNwb25zZSA9IChiYWxhbmNlOiBzdHJpbmcpID0+XG4gICAgICBuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLmRpdmlkZWRCeShiYXNlY29pbi5nZXRCYXNlRmFjdG9yKCkpLnRvRml4ZWQoOSkgKyAnIOKEjyc7XG4gICAgY29uc3QgdG9rZW5JZCA9ICcwLjAuNDI5Mjc0JztcblxuICAgIGRlc2NyaWJlKCdOb24tQml0R28nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kQm94ID0gU2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBzYW5kQm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIGFuZCBzaWduIHRoZSByZWNvdmVyeSB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRBbW91bnQgPSBuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLm1pbnVzKGRlZmF1bHRGZWUpLnRvU3RyaW5nKCk7XG4gICAgICAgIGNvbnN0IGdldEJhbGFuY2VTdHViID0gc2FuZEJveFxuICAgICAgICAgIC5zdHViKEhiYXIucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKVxuICAgICAgICAgIC5yZXNvbHZlcyh7IGhiYXJzOiBmb3JtYXRCYWxhbmNlUmVzcG9uc2UoYmFsYW5jZSksIHRva2VuczogW10gfSk7XG5cbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0aGJhcicpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9kZUlkJywgZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJhc2Vjb2luLmdldEJ1aWxkZXJGYWN0b3J5KCkuZnJvbShyZWNvdmVyeS50eCk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJlY292ZXJ5LnR4KTtcbiAgICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICAgIHR4SnNvbi5hbW91bnQuc2hvdWxkLmVxdWFsKGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgdHhKc29uLnRvLnNob3VsZC5lcXVhbChyZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzKTtcbiAgICAgICAgdHhKc29uLmZlZS5zaG91bGQuZXF1YWwoZGVmYXVsdEZlZSk7XG4gICAgICAgIHR4SnNvbi5ub2RlLnNob3VsZC5lcXVhbChkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgdHhKc29uLm1lbW8uc2hvdWxkLmVxdWFsKG1lbW8pO1xuICAgICAgICB0eEpzb24udmFsaWREdXJhdGlvbi5zaG91bGQuZXF1YWwoZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgICB0eEpzb24uc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXJ0VGltZScpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhcnRUaW1lJywgdHhKc29uLnN0YXJ0VGltZSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcsIHJvb3RBZGRyZXNzICsgJ0AnICsgdHhKc29uLnN0YXJ0VGltZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCByb290QWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZFJvb3RBZGRyZXNzID0gJ3JhbmRvbXN0cmluZyc7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzOiAncmFuZG9tc3RyaW5nJyxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIHJvb3RBZGRyZXNzLCBnb3Q6ICcgKyBpbnZhbGlkUm9vdEFkZHJlc3MgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZFJlY292ZXJ5RGVzdGluYXRpb24gPSAncmFuZG9tc3RyaW5nJztcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgICAgIGJhY2t1cEtleSxcbiAgICAgICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246ICdyYW5kb21zdHJpbmcnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24sIGdvdDogJyArIGludmFsaWRSZWNvdmVyeURlc3RpbmF0aW9uIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIG5vZGVJZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZE5vZGVJZCA9ICdhLjIuMyc7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICAgIG5vZGVJZDogaW52YWxpZE5vZGVJZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnaW52YWxpZCBub2RlSWQsIGdvdDogJyArIGludmFsaWROb2RlSWQgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGludmFsaWQgbWF4RmVlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbnZhbGlkTWF4RmVlID0gJy0zMic7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICAgIG1heEZlZTogaW52YWxpZE1heEZlZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnaW52YWxpZCBtYXhGZWUsIGdvdDogJyArIGludmFsaWRNYXhGZWUgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgdGhlcmUgaXMgbm8gZW5vdWdoIGJhbGFuY2UgdG8gcmVjb3ZlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZ2V0QmFsYW5jZVN0dWIgPSBzYW5kQm94XG4gICAgICAgICAgLnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpXG4gICAgICAgICAgLnJlc29sdmVzKHsgaGJhcnM6IGZvcm1hdEJhbGFuY2VSZXNwb25zZSgnMTAwJyksIHRva2VuczogW10gfSk7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ0luc3VmZmljaWVudCBiYWxhbmNlIHRvIHJlY292ZXIsIGdvdCBiYWxhbmNlOiAxMDAgZmVlOiAxMDAwMDAwMCcgfVxuICAgICAgICApO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGUgd2FsbGV0UGFzc3BocmFzZSBpcyB1bmRlZmluZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ3dhbGxldFBhc3NwaHJhc2UgaXMgcmVxdWlyZWQgZm9yIG5vbi1iaXRnbyByZWNvdmVyeScgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgdGhlIHdhbGxldFBhc3NwaHJhc2UgaXMgd3JvbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAncmFuZG9tcGFzc3dvcmQnLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgICAgIFwidW5hYmxlIHRvIGRlY3J5cHQgdXNlcktleSBvciBiYWNrdXBLZXkgd2l0aCB0aGUgd2FsbGV0UGFzc3BocmFzZSBwcm92aWRlZCwgZ290IGVycm9yOiBwYXNzd29yZCBlcnJvciAtIGNjbTogdGFnIGRvZXNuJ3QgbWF0Y2hcIixcbiAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgc2lnbiB0aGUgcmVjb3ZlcnkgdHggZm9yIHRva2VucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgYmFsYW5jZSA9ICcxMDAnO1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgIGhiYXJzOiAnMScsXG4gICAgICAgICAgdG9rZW5zOiBbeyB0b2tlbklkOiB0b2tlbklkLCBiYWxhbmNlOiBiYWxhbmNlLCBkZWNpbWFsczogNiB9XSxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZ2V0QmFsYW5jZVN0dWIgPSBzYW5kQm94LnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpLnJlc29sdmVzKGRhdGEpO1xuXG4gICAgICAgIGNvbnN0IHJlY292ZXJ5ID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgdG9rZW5JZDogdG9rZW5JZCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0aGJhcicpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9kZUlkJywgZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJhc2Vjb2luLmdldEJ1aWxkZXJGYWN0b3J5KCkuZnJvbShyZWNvdmVyeS50eCk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJlY292ZXJ5LnR4KTtcbiAgICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICAgIHR4SnNvbi5hbW91bnQuc2hvdWxkLmVxdWFsKGJhbGFuY2UpO1xuICAgICAgICB0eEpzb24udG8uc2hvdWxkLmVxdWFsKHJlY292ZXJ5RGVzdGluYXRpb24pO1xuICAgICAgICB0eEpzb24uZnJvbS5zaG91bGQuZXF1YWwocm9vdEFkZHJlc3MpO1xuICAgICAgICB0eEpzb24uZmVlLnNob3VsZC5lcXVhbChkZWZhdWx0RmVlKTtcbiAgICAgICAgdHhKc29uLm5vZGUuc2hvdWxkLmVxdWFsKGRlZmF1bHROb2RlSWQpO1xuICAgICAgICB0eEpzb24ubWVtby5zaG91bGQuZXF1YWwobWVtbyk7XG4gICAgICAgIHR4SnNvbi52YWxpZER1cmF0aW9uLnNob3VsZC5lcXVhbChkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHR4SnNvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhcnRUaW1lJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGFydFRpbWUnLCB0eEpzb24uc3RhcnRUaW1lKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJywgcm9vdEFkZHJlc3MgKyAnQCcgKyB0eEpzb24uc3RhcnRUaW1lKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBub24gc3VwcG9ydGVkIGludmFsaWQgdG9rZW5JZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaW52YWxpZFRva2VuSWQgPSAncmFuZG9tc3RyaW5nJztcbiAgICAgICAgY29uc3QgZGF0YSA9IHtcbiAgICAgICAgICBoYmFyczogJzEnLFxuICAgICAgICAgIHRva2VuczogW3sgdG9rZW5JZDogdG9rZW5JZCwgYmFsYW5jZTogJzEwMCcsIGRlY2ltYWxzOiA2IH1dLFxuICAgICAgICB9O1xuICAgICAgICBzYW5kQm94LnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpLnJlc29sdmVzKGRhdGEpO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleSxcbiAgICAgICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgICAgICByb290QWRkcmVzczogcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgdG9rZW5JZDogaW52YWxpZFRva2VuSWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ1Vuc3VwcG9ydGVkIHRva2VuOiAnICsgaW52YWxpZFRva2VuSWQgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGluc3VmZmljaWVudCBiYWxhbmNlIGZvciB0b2tlbklkIGlmIHRva2VuIGJhbGFuY2Ugbm90IGV4aXN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgIGhiYXJzOiAnMTAwJyxcbiAgICAgICAgICB0b2tlbnM6IFt7IHRva2VuSWQ6ICdyYW5kb21TdHJpbmcnLCBiYWxhbmNlOiAnMTAwJywgZGVjaW1hbHM6IDYgfV0sXG4gICAgICAgIH07XG4gICAgICAgIHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMoZGF0YSk7XG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgICAgICB1c2VyS2V5LFxuICAgICAgICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzOiByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICB0b2tlbklkOiB0b2tlbklkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdJbnN1ZmZpY2llbnQgYmFsYW5jZSB0byByZWNvdmVyIHRva2VuOiAnICsgdG9rZW5JZCArICcgZm9yIGFjY291bnQ6ICcgKyByb290QWRkcmVzcyB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW5zdWZmaWNpZW50IGJhbGFuY2UgZm9yIHRva2VuSWQgaWYgdG9rZW4gYmFsYW5jZSBleGlzdCB3aXRoIDAgYW1vdW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBkYXRhID0ge1xuICAgICAgICAgIGhiYXJzOiAnMTAwJyxcbiAgICAgICAgICB0b2tlbnM6IFt7IHRva2VuSWQ6ICdyYW5kb21TdHJpbmcnLCBiYWxhbmNlOiAnMCcsIGRlY2ltYWxzOiA2IH1dLFxuICAgICAgICB9O1xuICAgICAgICBzYW5kQm94LnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpLnJlc29sdmVzKGRhdGEpO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleSxcbiAgICAgICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgICAgICByb290QWRkcmVzczogcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgdG9rZW5JZDogdG9rZW5JZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnSW5zdWZmaWNpZW50IGJhbGFuY2UgdG8gcmVjb3ZlciB0b2tlbjogJyArIHRva2VuSWQgKyAnIGZvciBhY2NvdW50OiAnICsgcm9vdEFkZHJlc3MgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGluc3VmZmljaWVudCBuYXRpdmUgYmFsYW5jZSBmb3IgdG9rZW4gdHJhbnNmZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgaGJhcnM6ICcwLjAxJyxcbiAgICAgICAgICB0b2tlbnM6IFt7IHRva2VuSWQ6IHRva2VuSWQsIGJhbGFuY2U6ICcxMCcsIGRlY2ltYWxzOiA2IH1dLFxuICAgICAgICB9O1xuICAgICAgICBzYW5kQm94LnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpLnJlc29sdmVzKGRhdGEpO1xuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleSxcbiAgICAgICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgICAgICByb290QWRkcmVzczogcm9vdEFkZHJlc3MsXG4gICAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgdG9rZW5JZDogdG9rZW5JZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnSW5zdWZmaWNpZW50IG5hdGl2ZSBiYWxhbmNlIHRvIHJlY292ZXIgdG9rZW5zLCBnb3QgbmF0aXZlIGJhbGFuY2U6IDEwMDAwMDAgZmVlOiAnICsgZGVmYXVsdEZlZSB9XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdVbnNpZ25lZCBTd2VlcCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNhbmRCb3ggPSBTaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgICBsZXQgZ2V0QmFsYW5jZVN0dWI6IFNpbm9uU3R1YjtcblxuICAgICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2FuZEJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCB1bnNpZ25lZCBzd2VlcCB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZ2V0QmFsYW5jZVN0dWIgPSBzYW5kQm94XG4gICAgICAgICAgLnN0dWIoSGJhci5wcm90b3R5cGUsICdnZXRBY2NvdW50QmFsYW5jZScpXG4gICAgICAgICAgLnJlc29sdmVzKHsgaGJhcnM6IGZvcm1hdEJhbGFuY2VSZXNwb25zZShiYWxhbmNlKSwgdG9rZW5zOiBbXSB9KTtcbiAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gKERhdGUubm93KCkgLyAxMDAwICsgMTApLnRvRml4ZWQoKTsgLy8gdGltZXN0YW1wIGluIHNlY29uZHMsIDEwIHNlY29uZHMgZnJvbSBub3dcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRBbW91bnQgPSBuZXcgQmlnTnVtYmVyKGJhbGFuY2UpLm1pbnVzKGRlZmF1bHRGZWUpLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgY29uc3QgcmVjb3ZlcnkgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB1c2VyUHViLFxuICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwUHViLFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgIGJpdGdvS2V5LFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcsIHJvb3RBZGRyZXNzICsgJ0AnICsgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd1c2VyS2V5JywgdXNlclB1Yik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdiYWNrdXBLZXknLCBiYWNrdXBQdWIpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYml0Z29LZXknLCBiaXRnb0tleSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhZGRyZXNzJywgcm9vdEFkZHJlc3MpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0aGJhcicpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbWF4RmVlJywgZGVmYXVsdEZlZS50b1N0cmluZygpKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnLCBbeyBhZGRyZXNzOiByZWNvdmVyeURlc3RpbmF0aW9uLCBhbW91bnQ6IGV4cGVjdGVkQW1vdW50IH1dKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2Ftb3VudCcsIGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbGlkRHVyYXRpb24nLCBkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdub2RlSWQnLCBkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ21lbW8nLCBtZW1vKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXJ0VGltZScsIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBiYXNlY29pbi5nZXRCdWlsZGVyRmFjdG9yeSgpLmZyb20ocmVjb3ZlcnkudHhIZXgpO1xuICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmlkLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyArICdAJyArIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICB0eEpzb24uYW1vdW50LnNob3VsZC5lcXVhbChleHBlY3RlZEFtb3VudCk7XG4gICAgICAgIHR4SnNvbi50by5zaG91bGQuZXF1YWwocmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAgIHR4SnNvbi5mcm9tLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyk7XG4gICAgICAgIHR4SnNvbi5mZWUuc2hvdWxkLmVxdWFsKGRlZmF1bHRGZWUpO1xuICAgICAgICB0eEpzb24ubm9kZS5zaG91bGQuZXF1YWwoZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIHR4SnNvbi5tZW1vLnNob3VsZC5lcXVhbChtZW1vKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgICAgdHhKc29uLnN0YXJ0VGltZS5zaG91bGQuZXF1YWwoc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHR4SnNvbi52YWxpZER1cmF0aW9uLnNob3VsZC5lcXVhbChkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCB1bnNpZ25lZCBzd2VlcCB0eCBmb3IgdG9rZW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBiYWxhbmNlID0gJzEwMCc7XG4gICAgICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICAgICAgaGJhcnM6ICcxJyxcbiAgICAgICAgICB0b2tlbnM6IFt7IHRva2VuSWQ6IHRva2VuSWQsIGJhbGFuY2U6IGJhbGFuY2UsIGRlY2ltYWxzOiA2IH1dLFxuICAgICAgICB9O1xuICAgICAgICBnZXRCYWxhbmNlU3R1YiA9IHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2dldEFjY291bnRCYWxhbmNlJykucmVzb2x2ZXMoZGF0YSk7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IChEYXRlLm5vdygpIC8gMTAwMCArIDEwKS50b0ZpeGVkKCk7IC8vIHRpbWVzdGFtcCBpbiBzZWNvbmRzLCAxMCBzZWNvbmRzIGZyb20gbm93XG4gICAgICAgIGNvbnN0IHJlY292ZXJ5ID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogdXNlclB1YixcbiAgICAgICAgICBiYWNrdXBLZXk6IGJhY2t1cFB1YixcbiAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgc3RhcnRUaW1lLFxuICAgICAgICAgIHRva2VuSWQ6IHRva2VuSWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4SGV4Jyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcsIHJvb3RBZGRyZXNzICsgJ0AnICsgc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd1c2VyS2V5JywgdXNlclB1Yik7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdiYWNrdXBLZXknLCBiYWNrdXBQdWIpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYml0Z29LZXknLCBiaXRnb0tleSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhZGRyZXNzJywgcm9vdEFkZHJlc3MpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0aGJhcicpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbWF4RmVlJywgZGVmYXVsdEZlZS50b1N0cmluZygpKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnLCBbXG4gICAgICAgICAgeyBhZGRyZXNzOiByZWNvdmVyeURlc3RpbmF0aW9uLCBhbW91bnQ6IGJhbGFuY2UsIHRva2VuTmFtZTogJ3RoYmFyOnVzZGMnIH0sXG4gICAgICAgIF0pO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYW1vdW50JywgYmFsYW5jZSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd2YWxpZER1cmF0aW9uJywgZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9kZUlkJywgZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdtZW1vJywgbWVtbyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGFydFRpbWUnLCBzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gYmFzZWNvaW4uZ2V0QnVpbGRlckZhY3RvcnkoKS5mcm9tKHJlY292ZXJ5LnR4SGV4KTtcbiAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICAgIHR4SnNvbi5pZC5zaG91bGQuZXF1YWwocm9vdEFkZHJlc3MgKyAnQCcgKyBzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgdHhKc29uLmFtb3VudC5zaG91bGQuZXF1YWwoYmFsYW5jZSk7XG4gICAgICAgIHR4SnNvbi50by5zaG91bGQuZXF1YWwocmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAgIHR4SnNvbi5mcm9tLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyk7XG4gICAgICAgIHR4SnNvbi5mZWUuc2hvdWxkLmVxdWFsKGRlZmF1bHRGZWUpO1xuICAgICAgICB0eEpzb24ubm9kZS5zaG91bGQuZXF1YWwoZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIHR4SnNvbi5tZW1vLnNob3VsZC5lcXVhbChtZW1vKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgICAgdHhKc29uLnN0YXJ0VGltZS5zaG91bGQuZXF1YWwoc3RhcnRUaW1lICsgJy4wJyk7XG4gICAgICAgIHR4SnNvbi52YWxpZER1cmF0aW9uLnNob3VsZC5lcXVhbChkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBzdGFydFRpbWUgaXMgdW5kZWZpbmVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXk6IHVzZXJQdWIsXG4gICAgICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwUHViLFxuICAgICAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgYml0Z29LZXksXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgc3RhcnRUaW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdzdGFydCB0aW1lIGlzIHJlcXVpcmVkIGZvciB1bnNpZ25lZCBzd2VlcCcgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGludmFsaWQgdXNlcktleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gKERhdGUubm93KCkgLyAxMDAwICsgMTApLnRvRml4ZWQoKTtcbiAgICAgICAgY29uc3QgaW52YWxpZFVzZXJQdWIgPSAnMzAyYTMwMDUwNjAzMmI2NTcwMDMyMTAwcmFuZG9tc3RyaW5nJztcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXk6IGludmFsaWRVc2VyUHViLFxuICAgICAgICAgICAgICBiYWNrdXBLZXk6IGJhY2t1cFB1YixcbiAgICAgICAgICAgICAgYml0Z29LZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnaW52YWxpZCB1c2VyS2V5LCBnb3Q6ICcgKyBpbnZhbGlkVXNlclB1YiB9XG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgaW52YWxpZCBiYWNrdXBLZXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGludmFsaWRCYWNrdXBQdWIgPSAnMzAyYTMwMDUwNjAzMmI2NTcwMDMyMTAwcmFuZG9tc3RyaW5nJztcbiAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gKERhdGUubm93KCkgLyAxMDAwICsgMTApLnRvRml4ZWQoKTtcbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXk6IHVzZXJQdWIsXG4gICAgICAgICAgICAgIGJhY2t1cEtleTogaW52YWxpZEJhY2t1cFB1YixcbiAgICAgICAgICAgICAgYml0Z29LZXksXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiByZWNvdmVyeURlc3RpbmF0aW9uICsgJz9tZW1vSWQ9JyArIG1lbW8sXG4gICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBtZXNzYWdlOiAnaW52YWxpZCBiYWNrdXBLZXksIGdvdDogJyArIGludmFsaWRCYWNrdXBQdWIgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgc3RhcnRUaW1lIGlzIGEgdmFsaWQgdGltZXN0YW1wJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSAnYXNkJztcblxuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgICAgICAgdXNlcktleTogdXNlclB1YixcbiAgICAgICAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBQdWIsXG4gICAgICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgICAgICBiaXRnb0tleSxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vLFxuICAgICAgICAgICAgICBzdGFydFRpbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgbWVzc2FnZTogJ2ludmFsaWQgc3RhcnRUaW1lLCBnb3Q6ICcgKyBzdGFydFRpbWUgfVxuICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgc3RhcnRUaW1lIGlzIG5vdCBhIGZ1dHVyZSBkYXRlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgLSAxKS50b1N0cmluZygpOyAvLyB0aW1lc3RhbXAgaW4gc2Vjb25kcywgMSBzZWNvbmQgYWdvXG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgICAgIHVzZXJLZXk6IHVzZXJQdWIsXG4gICAgICAgICAgICAgIGJhY2t1cEtleTogYmFja3VwUHViLFxuICAgICAgICAgICAgICByb290QWRkcmVzcyxcbiAgICAgICAgICAgICAgYml0Z29LZXksXG4gICAgICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IHJlY292ZXJ5RGVzdGluYXRpb24gKyAnP21lbW9JZD0nICsgbWVtbyxcbiAgICAgICAgICAgICAgc3RhcnRUaW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IG1lc3NhZ2U6ICdzdGFydFRpbWUgbXVzdCBiZSBhIGZ1dHVyZSB0aW1lc3RhbXAsIGdvdDogJyArIHN0YXJ0VGltZSB9XG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdSZWNvdmVyeSB3aXRoIHJvb3Qga2V5cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNhbmRCb3ggPSBTaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgICBsZXQgZ2V0QmFsYW5jZVN0dWI6IFNpbm9uU3R1YjtcbiAgICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdGJ0Y3Bhc3N3b3JkMTk5OSc7XG4gICAgICBjb25zdCB1c2VyRWRkc2FSb290WFBydiA9XG4gICAgICAgICd7XCJpdlwiOlwibEhPVGtpdXVjUjJKV0ZEMXgxZ3FwUT09XCIsXCJ2XCI6MSxcIml0ZXJcIjoxMDAwMCxcImtzXCI6MTI4LFwidHNcIjo2NCxcIm1vZGVcIjpcImNjbVwiLFwiYWRhdGFcIjpcIlwiLFwiY2lwaGVyXCI6XCJhZXNcIixcInNhbHRcIjpcIkhrRnJEVkgrK2Q4PVwiLFwiY3RcIjpcIk5CdGJZZEZFSzg0b0g5dXh3bC9VcmhSc1c1bkdKUG5NU3BSQW84QmxyYzdXVFNQeEdYbVZTL0VwVVlFVjAzSEcwNi9FbnlCUjAvWTZiakxRejRna0w2Y0dKRDloZ3lLcUR2YzlSdEtIYWdFYm83NW94UHIwelArcjFITVVHQlczOFR0Z29yNjc0Z0JlYjFNeWV3Njl4Y1M5S2dndU54d3o3N1g2ZmRlQmhyZm9nTFkyMnZjdUxBPT1cIn0nO1xuICAgICAgY29uc3QgdXNlckVkZHNhUm9vdFB1YiA9ICdkOWNiOWM5YzYxN2NmYTBiNzE1ODQ5NTE2YmIwNTRhMmI1ZDc4YzBlM2VlZWYwMTExNzZmYjhiYzAxMDhjNTMxJztcbiAgICAgIGNvbnN0IGJhY2t1cEVkZHNhUm9vdFhwcnYgPVxuICAgICAgICAne1wiaXZcIjpcInNCb0VGQkJOb2kyWVZJQ1BmMTYvQlE9PVwiLFwidlwiOjEsXCJpdGVyXCI6MTAwMDAsXCJrc1wiOjEyOCxcInRzXCI6NjQsXCJtb2RlXCI6XCJjY21cIixcImFkYXRhXCI6XCJcIixcImNpcGhlclwiOlwiYWVzXCIsXCJzYWx0XCI6XCJIa0ZyRFZIKytkOD1cIixcImN0XCI6XCJHc2NPcUpDK0lxK0xyMzlwbFFwNVpDYW1WbHBKSE9sdEdUWjcvVW5VdW5JaEZtWldNQkx4akVWbk1PdFByZWIwTlo0L1NGcU8vTjNtWnZxNkpiQjd2V1J4SnVxa0JJaVZjSVJ3a1NXZFc1NWNib0t4MmVjM2FqZzgrdU8ycGJ2TkRzMjZRKzlOdFo0alpuS05xU1VYaUNtdEpYTFJIUTMyb3lEK29sS1JwSVIyTlFvMis3a0lFdz09XCJ9JztcbiAgICAgIGNvbnN0IGJhY2t1cEVkZHNhUm9vdFB1YiA9ICdmMTYzYjFiOGVlNGMzMzQzYTk3YWMxZDI0NzBiOTY3ZTk2N2FjN2I0ZTM3MzFjYWNmMDJmMjhhMTQzNGEyZjk5JztcbiAgICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gJzAuMC4zNjQ0NjY3JztcbiAgICAgIGNvbnN0IG1lbW9JZCA9ICcwJztcblxuICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGdldEJhbGFuY2VTdHViID0gc2FuZEJveFxuICAgICAgICAgIC5zdHViKEhiYXIucHJvdG90eXBlLCAnZ2V0QWNjb3VudEJhbGFuY2UnKVxuICAgICAgICAgIC5yZXNvbHZlcyh7IGhiYXJzOiBmb3JtYXRCYWxhbmNlUmVzcG9uc2UoYmFsYW5jZSksIHRva2VuczogW10gfSk7XG4gICAgICB9KTtcblxuICAgICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2FuZEJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgc2lnbiBub24tYml0Z28gcmVjb3ZlcnkgdHggd2l0aCByb290IGtleXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGV4cGVjdGVkQW1vdW50ID0gbmV3IEJpZ051bWJlcihiYWxhbmNlKS5taW51cyhkZWZhdWx0RmVlKS50b1N0cmluZygpO1xuXG4gICAgICAgIGNvbnN0IHJlY292ZXJ5ID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogdXNlckVkZHNhUm9vdFhQcnYsXG4gICAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBFZGRzYVJvb3RYcHJ2LFxuICAgICAgICAgIHJvb3RBZGRyZXNzLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vSWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLm5vdC5iZS51bmRlZmluZWQoKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnY29pbicsICd0aGJhcicpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9kZUlkJywgZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIGdldEJhbGFuY2VTdHViLmNhbGxDb3VudC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGJhc2Vjb2luLmdldEJ1aWxkZXJGYWN0b3J5KCkuZnJvbShyZWNvdmVyeS50eCk7XG4gICAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICAgIHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJlY292ZXJ5LnR4KTtcbiAgICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICAgIHR4SnNvbi5hbW91bnQuc2hvdWxkLmVxdWFsKGV4cGVjdGVkQW1vdW50KTtcbiAgICAgICAgdHhKc29uLnRvLnNob3VsZC5lcXVhbChyZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgICAgdHhKc29uLmZyb20uc2hvdWxkLmVxdWFsKHJvb3RBZGRyZXNzKTtcbiAgICAgICAgdHhKc29uLmZlZS5zaG91bGQuZXF1YWwoZGVmYXVsdEZlZSk7XG4gICAgICAgIHR4SnNvbi5ub2RlLnNob3VsZC5lcXVhbChkZWZhdWx0Tm9kZUlkKTtcbiAgICAgICAgdHhKc29uLm1lbW8uc2hvdWxkLmVxdWFsKG1lbW9JZCk7XG4gICAgICAgIHR4SnNvbi52YWxpZER1cmF0aW9uLnNob3VsZC5lcXVhbChkZWZhdWx0VmFsaWREdXJhdGlvbik7XG4gICAgICAgIHR4SnNvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhcnRUaW1lJyk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGFydFRpbWUnLCB0eEpzb24uc3RhcnRUaW1lKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lkJywgcm9vdEFkZHJlc3MgKyAnQCcgKyB0eEpzb24uc3RhcnRUaW1lKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGJ1aWxkIHVuc2lnbmVkIHN3ZWVwIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgKyAxMCkudG9GaXhlZCgpOyAvLyB0aW1lc3RhbXAgaW4gc2Vjb25kcywgMTAgc2Vjb25kcyBmcm9tIG5vd1xuICAgICAgICBjb25zdCBleHBlY3RlZEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoYmFsYW5jZSkubWludXMoZGVmYXVsdEZlZSkudG9TdHJpbmcoKTtcblxuICAgICAgICBjb25zdCByZWNvdmVyeSA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IHVzZXJFZGRzYVJvb3RQdWIsXG4gICAgICAgICAgYmFja3VwS2V5OiBiYWNrdXBFZGRzYVJvb3RQdWIsXG4gICAgICAgICAgcm9vdEFkZHJlc3MsXG4gICAgICAgICAgYml0Z29LZXksXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogcmVjb3ZlcnlEZXN0aW5hdGlvbiArICc/bWVtb0lkPScgKyBtZW1vSWQsXG4gICAgICAgICAgc3RhcnRUaW1lLFxuICAgICAgICB9KTtcblxuICAgICAgICBnZXRCYWxhbmNlU3R1Yi5jYWxsQ291bnQuc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5ub3QuYmUudW5kZWZpbmVkKCk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaWQnLCByb290QWRkcmVzcyArICdAJyArIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndXNlcktleScsIHVzZXJFZGRzYVJvb3RQdWIpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYmFja3VwS2V5JywgYmFja3VwRWRkc2FSb290UHViKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2JpdGdvS2V5JywgYml0Z29LZXkpO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWRkcmVzcycsIHJvb3RBZGRyZXNzKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2NvaW4nLCAndGhiYXInKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ21heEZlZScsIGRlZmF1bHRGZWUudG9TdHJpbmcoKSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdyZWNpcGllbnRzJywgW3sgYWRkcmVzczogcmVjb3ZlcnlEZXN0aW5hdGlvbiwgYW1vdW50OiBleHBlY3RlZEFtb3VudCB9XSk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdhbW91bnQnLCBleHBlY3RlZEFtb3VudCk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCd2YWxpZER1cmF0aW9uJywgZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgICByZWNvdmVyeS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9kZUlkJywgZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIHJlY292ZXJ5LnNob3VsZC5oYXZlLnByb3BlcnR5KCdtZW1vJywgbWVtb0lkKTtcbiAgICAgICAgcmVjb3Zlcnkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXJ0VGltZScsIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBiYXNlY29pbi5nZXRCdWlsZGVyRmFjdG9yeSgpLmZyb20ocmVjb3ZlcnkudHhIZXgpO1xuICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgICAgdHhKc29uLmlkLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyArICdAJyArIHN0YXJ0VGltZSArICcuMCcpO1xuICAgICAgICB0eEpzb24uYW1vdW50LnNob3VsZC5lcXVhbChleHBlY3RlZEFtb3VudCk7XG4gICAgICAgIHR4SnNvbi50by5zaG91bGQuZXF1YWwocmVjb3ZlcnlEZXN0aW5hdGlvbik7XG4gICAgICAgIHR4SnNvbi5mcm9tLnNob3VsZC5lcXVhbChyb290QWRkcmVzcyk7XG4gICAgICAgIHR4SnNvbi5mZWUuc2hvdWxkLmVxdWFsKGRlZmF1bHRGZWUpO1xuICAgICAgICB0eEpzb24ubm9kZS5zaG91bGQuZXF1YWwoZGVmYXVsdE5vZGVJZCk7XG4gICAgICAgIHR4SnNvbi5tZW1vLnNob3VsZC5lcXVhbChtZW1vSWQpO1xuICAgICAgICB0eEpzb24udmFsaWREdXJhdGlvbi5zaG91bGQuZXF1YWwoZGVmYXVsdFZhbGlkRHVyYXRpb24pO1xuICAgICAgICB0eEpzb24uc3RhcnRUaW1lLnNob3VsZC5lcXVhbChzdGFydFRpbWUgKyAnLjAnKTtcbiAgICAgICAgdHhKc29uLnZhbGlkRHVyYXRpb24uc2hvdWxkLmVxdWFsKGRlZmF1bHRWYWxpZER1cmF0aW9uKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnYnJvYWRjYXN0VHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgc2FuZEJveCA9IFNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3VjY2VlZCBpZiB0aGUgc3RhcnRUaW1lIGFuZCBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24gYXJlIHZhbGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gKERhdGUubm93KCkgLyAxMDAwIC0gMykudG9GaXhlZCgpOyAvLyB0aW1lc3RhbXAgaW4gc2Vjb25kcywgLTMgc2Vjb25kcyBmcm9tIG5vdyBzbyBpdCdzIHZhbGlkIGFmdGVyIDIgc2Vjb25kc1xuICAgICAgY29uc3QgZXhwZWN0ZWRSZXNwb25zZSA9IHsgdHhJZDogJzAuMC43NjY4NDY1QCcgKyBzdGFydFRpbWUgKyAnLjAnLCBzdGF0dXM6ICdTVUNDRVNTJyB9O1xuICAgICAgY29uc3QgYnJvYWRjYXN0U3R1YiA9IHNhbmRCb3guc3R1YihIYmFyLnByb3RvdHlwZSwgJ2NsaWVudEJyb2FkY2FzdFRyYW5zYWN0aW9uJykucmVzb2x2ZXMoZXhwZWN0ZWRSZXNwb25zZSk7XG4gICAgICBjb25zdCBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24gPVxuICAgICAgICAnMWFjYzAxMGE2NDBhMjA1OTJhNGZiYjcyNjNjNTlkNDUwZTY1MWRmOTY2MjBkYzkyMDhlZTdjN2Q5ZDZmMmZkY2I5MWM1M2Y4ODMxMjYxMWE0MDEwNWI3ZDI1MGM4MWYzNzA1YmMwYjg1MTY4Y2UzZmQwMDMzMDEzMWJiNzcwMTM3ODY4MWM4YzJlNmEwOWE5MTgyODcxNWU3MzM0ZjRlZjI4ZDIwZmYwOTg4N2M2ZTg3YzBhNWM2OTNlMjM4MjRjMjZmM2JhMTYxZmNlMDQ0ODA1MGE2NDBhMjBhNjkwNTA5NTYxNmMzY2ZhYTFiZjYxYjUzZGUzMGU5MzhjZTQxMTJjM2NjNGQyNTM5M2VjNmI5YmY0ZGVhMDYzMWE0MGJmOThjNWI4OWI3YTA4NTQ0ZWRhYTFmNGMwOGEwZGZhNmVjM2Y3OGI3ZTJmZDI3MDQ5MjgzOTg0MDUwZjM4Y2NmMDMwM2VlNTdhMzc3Y2MwYTcyNWZmZDk5ZDY5ZTlmZDkxNDc3MGFiMDk0OWJhNTU2ZDg0YjNiMDBjYjA3ZTBkMjI1MDBhMTMwYTA2MDhjZWE4YzFhZDA2MTIwOTA4MDAxMDAwMThmMTg1ZDQwMzEyMDYwODAwMTAwMDE4MDMxODgwYzJkNzJmMjIwMzA4YjQwMTMyMDEzNDcyMjQwYTIyMGEwZjBhMDkwODAwMTAwMDE4ZjE4NWQ0MDMxMGQzYjA1MTBhMGYwYTA5MDgwMDEwMDAxOGM0ODRkMzAzMTBkNGIwNTEnO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZWNvaW4uYnJvYWRjYXN0VHJhbnNhY3Rpb24oeyBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24sIHN0YXJ0VGltZSB9KTtcbiAgICAgIGJyb2FkY2FzdFN0dWIuY2FsbENvdW50LnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGUgc3RhcnRUaW1lIGlzIGV4cGlyZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzdGFydFRpbWUgPSAoRGF0ZS5ub3coKSAvIDEwMDAgLSAyMDAwKS50b0ZpeGVkKCk7IC8vIHRpbWVzdGFtcCBpbiBzZWNvbmRzLCAyMDAwIHNlY29uZHMgZnJvbSBub3dcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiA9XG4gICAgICAgICcxYWNjMDEwYTY0MGEyMDU5MmE0ZmJiNzI2M2M1OWQ0NTBlNjUxZGY5NjYyMGRjOTIwOGVlN2M3ZDlkNmYyZmRjYjkxYzUzZjg4MzEyNjExYTQwMTA1YjdkMjUwYzgxZjM3MDViYzBiODUxNjhjZTNmZDAwMzMwMTMxYmI3NzAxMzc4NjgxYzhjMmU2YTA5YTkxODI4NzE1ZTczMzRmNGVmMjhkMjBmZjA5ODg3YzZlODdjMGE1YzY5M2UyMzgyNGMyNmYzYmExNjFmY2UwNDQ4MDUwYTY0MGEyMGE2OTA1MDk1NjE2YzNjZmFhMWJmNjFiNTNkZTMwZTkzOGNlNDExMmMzY2M0ZDI1MzkzZWM2YjliZjRkZWEwNjMxYTQwYmY5OGM1Yjg5YjdhMDg1NDRlZGFhMWY0YzA4YTBkZmE2ZWMzZjc4YjdlMmZkMjcwNDkyODM5ODQwNTBmMzhjY2YwMzAzZWU1N2EzNzdjYzBhNzI1ZmZkOTlkNjllOWZkOTE0NzcwYWIwOTQ5YmE1NTZkODRiM2IwMGNiMDdlMGQyMjUwMGExMzBhMDYwOGNlYThjMWFkMDYxMjA5MDgwMDEwMDAxOGYxODVkNDAzMTIwNjA4MDAxMDAwMTgwMzE4ODBjMmQ3MmYyMjAzMDhiNDAxMzIwMTM0NzIyNDBhMjIwYTBmMGEwOTA4MDAxMDAwMThmMTg1ZDQwMzEwZDNiMDUxMGEwZjBhMDkwODAwMTAwMDE4YzQ4NGQzMDMxMGQ0YjA1MSc7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IGJhc2Vjb2luLmJyb2FkY2FzdFRyYW5zYWN0aW9uKHsgc2VyaWFsaXplZFNpZ25lZFRyYW5zYWN0aW9uLCBzdGFydFRpbWUgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIChlcnJvcjogYW55KSA9PiB7XG4gICAgICAgICAgYXNzZXJ0Lm9rKGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoJ0ZhaWxlZCB0byBicm9hZGNhc3QgdHJhbnNhY3Rpb24sIGVycm9yOiBzdGFydFRpbWUgd2luZG93IGV4cGlyZWQnKSk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIHRoZSBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24gaXMgaW52YWxpZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IChEYXRlLm5vdygpIC8gMTAwMCAtIDEwKS50b0ZpeGVkKCk7IC8vIHRpbWVzdGFtcCBpbiBzZWNvbmRzLCAxMCBzZWNvbmRzIGZyb20gbm93XG4gICAgICBjb25zdCBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24gPSAncmFuZG9tc3RyaW5nJztcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgYmFzZWNvaW4uYnJvYWRjYXN0VHJhbnNhY3Rpb24oeyBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24sIHN0YXJ0VGltZSB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGUgc3RhcnRUaW1lIGluIHRoZSB0eCBpcyBpbnZhbGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWRSZXNwb25zZSA9XG4gICAgICAgICd0cmFuc2FjdGlvbiAwLjAuNzY2ODQ2NUAxNzA2MDU2MzAxLjAwMDAwMDAwMCBmYWlsZWQgcHJlY2hlY2sgd2l0aCBzdGF0dXMgSU5WQUxJRF9UUkFOU0FDVElPTl9TVEFSVCc7XG4gICAgICBzYW5kQm94LnN0dWIoSGJhci5wcm90b3R5cGUsICdjbGllbnRCcm9hZGNhc3RUcmFuc2FjdGlvbicpLnJlamVjdHMobmV3IEVycm9yKGV4cGVjdGVkUmVzcG9uc2UpKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbiA9XG4gICAgICAgICcxYWNjMDEwYTY0MGEyMDU5MmE0ZmJiNzI2M2M1OWQ0NTBlNjUxZGY5NjYyMGRjOTIwOGVlN2M3ZDlkNmYyZmRjYjkxYzUzZjg4MzEyNjExYTQwMTA1YjdkMjUwYzgxZjM3MDViYzBiODUxNjhjZTNmZDAwMzMwMTMxYmI3NzAxMzc4NjgxYzhjMmU2YTA5YTkxODI4NzE1ZTczMzRmNGVmMjhkMjBmZjA5ODg3YzZlODdjMGE1YzY5M2UyMzgyNGMyNmYzYmExNjFmY2UwNDQ4MDUwYTY0MGEyMGE2OTA1MDk1NjE2YzNjZmFhMWJmNjFiNTNkZTMwZTkzOGNlNDExMmMzY2M0ZDI1MzkzZWM2YjliZjRkZWEwNjMxYTQwYmY5OGM1Yjg5YjdhMDg1NDRlZGFhMWY0YzA4YTBkZmE2ZWMzZjc4YjdlMmZkMjcwNDkyODM5ODQwNTBmMzhjY2YwMzAzZWU1N2EzNzdjYzBhNzI1ZmZkOTlkNjllOWZkOTE0NzcwYWIwOTQ5YmE1NTZkODRiM2IwMGNiMDdlMGQyMjUwMGExMzBhMDYwOGNlYThjMWFkMDYxMjA5MDgwMDEwMDAxOGYxODVkNDAzMTIwNjA4MDAxMDAwMTgwMzE4ODBjMmQ3MmYyMjAzMDhiNDAxMzIwMTM0NzIyNDBhMjIwYTBmMGEwOTA4MDAxMDAwMThmMTg1ZDQwMzEwZDNiMDUxMGEwZjBhMDkwODAwMTAwMDE4YzQ4NGQzMDMxMGQ0YjA1MSc7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgYmFzZWNvaW4uYnJvYWRjYXN0VHJhbnNhY3Rpb24oeyBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb24gfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHsgbWVzc2FnZTogZXhwZWN0ZWRSZXNwb25zZSB9XG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZGVyaXZlS2V5V2l0aFNlZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBkZXJpdmUga2V5IHdpdGggc2VlZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICgoKSA9PiB7XG4gICAgICAgIGJhc2Vjb2luLmRlcml2ZUtleVdpdGhTZWVkKCd0ZXN0Jyk7XG4gICAgICB9KS5zaG91bGQudGhyb3coJ21ldGhvZCBkZXJpdmVLZXlXaXRoU2VlZCBub3Qgc3VwcG9ydGVkIGZvciBlZGRzYSBjdXJ2ZScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnR2VuZXJhdGUgd2FsbGV0IFJvb3Qga2V5IHBhaXI6ICcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleSBwYWlyJywgKCkgPT4ge1xuICAgICAgY29uc3Qga3AgPSBiYXNlY29pbi5nZW5lcmF0ZVJvb3RLZXlQYWlyKCk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHViKGtwLnB1Yikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgY29uc3Qga2V5cGFpciA9IG5ldyBLZXlQYWlyKHsgcHJ2OiBrcC5wcnYgfSkuZ2V0S2V5cyh0cnVlKTtcbiAgICAgIGtleXBhaXIuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3BydicpO1xuICAgICAga2V5cGFpci5wcnY/LnNob3VsZC5lcXVhbChrcC5wcnYuc2xpY2UoMCwgNjQpKTtcbiAgICAgIGtleXBhaXIucHViLnNob3VsZC5lcXVhbChrcC5wdWIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBrZXkgcGFpciBmcm9tIHNlZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oJzlkNjFiMTlkZWZmZDVhNjBiYTg0NGFmNDkyZWMyY2M0NDQ0OWM1Njk3YjMyNjkxOTcwM2JhYzAzMWNhZTdmNjAnLCAnaGV4Jyk7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlUm9vdEtleVBhaXIoc2VlZCk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHViKGtwLnB1Yikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAga3AucHViLnNob3VsZC5lcXVhbCgnZDc1YTk4MDE4MmIxMGFiN2Q1NGJmZWQzYzk2NDA3M2EwZWUxNzJmM2RhYTYyMzI1YWYwMjFhNjhmNzA3NTExYScpO1xuICAgICAga3AucHJ2LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzlkNjFiMTlkZWZmZDVhNjBiYTg0NGFmNDkyZWMyY2M0NDQ0OWM1Njk3YjMyNjkxOTcwM2JhYzAzMWNhZTdmNjBkNzVhOTgwMTgyYjEwYWI3ZDU0YmZlZDNjOTY0MDczYTBlZTE3MmYzZGFhNjIzMjVhZjAyMWE2OGY3MDc1MTFhJ1xuICAgICAgKTtcblxuICAgICAgY29uc3Qga2V5cGFpciA9IG5ldyBLZXlQYWlyKHsgcHJ2OiBrcC5wcnYgfSkuZ2V0S2V5cyh0cnVlKTtcbiAgICAgIGtleXBhaXIuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3BydicpO1xuICAgICAga2V5cGFpci5wcnY/LnNob3VsZC5lcXVhbChrcC5wcnYuc2xpY2UoMCwgNjQpKTtcbiAgICAgIGtleXBhaXIucHViLnNob3VsZC5lcXVhbChrcC5wdWIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXVkaXRLZXknLCAoKSA9PiB7XG4gICAgY29uc3QgeyBrZXkgfSA9IGhiYXJCYWNrdXBLZXk7XG4gICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICdrQW1bRUZRNm89U3hsY0xGRHclLCc7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmb3IgdmFsaWQgaW5wdXRzJywgKCkgPT4ge1xuICAgICAgYmFzZWNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgIGNvaW5OYW1lOiAnaGJhcicsXG4gICAgICAgIGVuY3J5cHRlZFBydjoga2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGlmIHRoZSB3YWxsZXRQYXNzcGhyYXNlIGlzIGluY29ycmVjdCcsICgpID0+IHtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+XG4gICAgICAgICAgYmFzZWNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICBjb2luTmFtZTogJ2hiYXInLFxuICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBrZXksXG4gICAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZm9vJyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgeyBtZXNzYWdlOiBcImZhaWxlZCB0byBkZWNyeXB0IHBydjogY2NtOiB0YWcgZG9lc24ndCBtYXRjaFwiIH1cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGlmIHRoZSBrZXkgaXMgYWx0ZXJlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGFsdGVyZWRLZXkgPSBrZXkucmVwbGFjZSgvWzAtOV0vZywgJzAnKTtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+XG4gICAgICAgICAgYmFzZWNvaW4uYXNzZXJ0SXNWYWxpZEtleSh7XG4gICAgICAgICAgICBjb2luTmFtZTogJ2hiYXInLFxuICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBhbHRlcmVkS2V5LFxuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6ICdmYWlsZWQgdG8gZGVjcnlwdCBwcnY6IGpzb24gZGVjcnlwdDogaW52YWxpZCBwYXJhbWV0ZXJzJyxcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgdGhlIGtleSBpcyBub3QgYSB2YWxpZCBrZXknLCAoKSA9PiB7XG4gICAgICBjb25zdCBpbnZhbGlkS2V5ID0gJyNAKSQjKCQqQCkjKCQqJztcbiAgICAgIGNvbnN0IGVuY3J5cHRlZFBydiA9IGVuY3J5cHQod2FsbGV0UGFzc3BocmFzZSwgaW52YWxpZEtleSk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIGJhc2Vjb2luLmFzc2VydElzVmFsaWRLZXkoe1xuICAgICAgICAgICAgY29pbk5hbWU6ICdoYmFyJyxcbiAgICAgICAgICAgIGVuY3J5cHRlZFBydixcbiAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOiAnSW52YWxpZCBwcml2YXRlIGtleTogSW52YWxpZCBwcml2YXRlIGtleSBsZW5ndGguIE11c3QgYmUgYSBoZXggYW5kIG11bHRpcGxlIG9mIDInLFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19