@bitgo/sdk-coin-eos 1.0.1-rc.0

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 (48) hide show
  1. package/.eslintignore +5 -0
  2. package/.mocharc.yml +8 -0
  3. package/CHANGELOG.md +8 -0
  4. package/LICENSE +191 -0
  5. package/README.md +30 -0
  6. package/dist/src/eos.d.ts +279 -0
  7. package/dist/src/eos.d.ts.map +1 -0
  8. package/dist/src/eos.js +872 -0
  9. package/dist/src/eosToken.d.ts +34 -0
  10. package/dist/src/eosToken.d.ts.map +1 -0
  11. package/dist/src/eosToken.js +68 -0
  12. package/dist/src/eosutil/eosabiprovider.d.ts +8 -0
  13. package/dist/src/eosutil/eosabiprovider.d.ts.map +1 -0
  14. package/dist/src/eosutil/eosabiprovider.js +30 -0
  15. package/dist/src/index.d.ts +5 -0
  16. package/dist/src/index.d.ts.map +1 -0
  17. package/dist/src/index.js +17 -0
  18. package/dist/src/lib/address.d.ts +5 -0
  19. package/dist/src/lib/address.d.ts.map +1 -0
  20. package/dist/src/lib/address.js +7 -0
  21. package/dist/src/lib/enum.d.ts +5 -0
  22. package/dist/src/lib/enum.d.ts.map +1 -0
  23. package/dist/src/lib/enum.js +10 -0
  24. package/dist/src/lib/iface.d.ts +1 -0
  25. package/dist/src/lib/iface.d.ts.map +1 -0
  26. package/dist/src/lib/iface.js +1 -0
  27. package/dist/src/lib/index.d.ts +6 -0
  28. package/dist/src/lib/index.d.ts.map +1 -0
  29. package/dist/src/lib/index.js +17 -0
  30. package/dist/src/lib/keyPair.d.ts +18 -0
  31. package/dist/src/lib/keyPair.d.ts.map +1 -0
  32. package/dist/src/lib/keyPair.js +41 -0
  33. package/dist/src/lib/transaction.d.ts +7 -0
  34. package/dist/src/lib/transaction.d.ts.map +1 -0
  35. package/dist/src/lib/transaction.js +17 -0
  36. package/dist/src/lib/transactionBuilder.d.ts +15 -0
  37. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  38. package/dist/src/lib/transactionBuilder.js +38 -0
  39. package/dist/src/lib/transactionBuilderFactory.d.ts +7 -0
  40. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -0
  41. package/dist/src/lib/transactionBuilderFactory.js +17 -0
  42. package/dist/src/lib/utils.d.ts +8 -0
  43. package/dist/src/lib/utils.d.ts.map +1 -0
  44. package/dist/src/lib/utils.js +24 -0
  45. package/dist/src/teos.d.ts +10 -0
  46. package/dist/src/teos.d.ts.map +1 -0
  47. package/dist/src/teos.js +24 -0
  48. package/package.json +59 -0
@@ -0,0 +1,872 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.Eos = void 0;
23
+ /**
24
+ * @prettier
25
+ */
26
+ const bignumber_js_1 = require("bignumber.js");
27
+ const bip32 = __importStar(require("bip32"));
28
+ const crypto_1 = require("crypto");
29
+ const eosjs_1 = require("eosjs");
30
+ const ecc = __importStar(require("eosjs-ecc"));
31
+ const _ = __importStar(require("lodash"));
32
+ const querystring = __importStar(require("querystring"));
33
+ const request = __importStar(require("superagent"));
34
+ const url = __importStar(require("url"));
35
+ const eosabiprovider_1 = require("./eosutil/eosabiprovider");
36
+ const utils_1 = require("./lib/utils");
37
+ const sdk_core_1 = require("@bitgo/sdk-core");
38
+ class NoopJsonRpc extends eosjs_1.JsonRpc {
39
+ constructor() {
40
+ super('');
41
+ }
42
+ }
43
+ class NoopSignatureProvider {
44
+ async getAvailableKeys() {
45
+ throw new Error('noop signature provider implementation has no available keys');
46
+ }
47
+ async sign(args) {
48
+ throw new Error('noop implementation is unable to sign');
49
+ }
50
+ }
51
+ class Eos extends sdk_core_1.BaseCoin {
52
+ static createInstance(bitgo) {
53
+ return new Eos(bitgo);
54
+ }
55
+ getChainId() {
56
+ return 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906'; // mainnet chain id
57
+ }
58
+ getChain() {
59
+ return 'eos';
60
+ }
61
+ getFamily() {
62
+ return 'eos';
63
+ }
64
+ getFullName() {
65
+ return 'EOS';
66
+ }
67
+ getBaseFactor() {
68
+ return 1e4;
69
+ }
70
+ /**
71
+ * Flag for sending value of 0
72
+ * @returns {boolean} True if okay to send 0 value, false otherwise
73
+ */
74
+ valuelessTransferAllowed() {
75
+ return true;
76
+ }
77
+ /**
78
+ * Get URLs of some active public nodes
79
+ */
80
+ getPublicNodeUrls() {
81
+ return sdk_core_1.Environments[this.bitgo.getEnv()].eosNodeUrls;
82
+ }
83
+ /**
84
+ * Generate secp256k1 key pair
85
+ *
86
+ * @param seed - Seed from which the new keypair should be generated, otherwise a random seed is used
87
+ */
88
+ generateKeyPair(seed) {
89
+ if (!seed) {
90
+ // An extended private key has both a normal 256 bit private key and a 256
91
+ // bit chain code, both of which must be random. 512 bits is therefore the
92
+ // maximum entropy and gives us maximum security against cracking.
93
+ seed = crypto_1.randomBytes(512 / 8);
94
+ }
95
+ const extendedKey = bip32.fromSeed(seed);
96
+ const xpub = extendedKey.neutered().toBase58();
97
+ return {
98
+ pub: xpub,
99
+ prv: extendedKey.toBase58(),
100
+ };
101
+ }
102
+ /**
103
+ * Return boolean indicating whether input is valid public key for the coin.
104
+ *
105
+ * @param pub - the pub to be checked
106
+ */
107
+ isValidPub(pub) {
108
+ try {
109
+ return bip32.fromBase58(pub).isNeutered();
110
+ }
111
+ catch (e) {
112
+ return false;
113
+ }
114
+ }
115
+ /**
116
+ * Return boolean indicating whether input is valid seed for the coin
117
+ *
118
+ * @param prv - the prv to be checked
119
+ */
120
+ isValidPrv(prv) {
121
+ try {
122
+ return !bip32.fromBase58(prv).isNeutered();
123
+ }
124
+ catch (e) {
125
+ return false;
126
+ }
127
+ }
128
+ /**
129
+ * Evaluates whether a memo is valid
130
+ *
131
+ * @param value - the memo to be checked
132
+ */
133
+ isValidMemo({ value }) {
134
+ return _.isString(value) && value.length <= 256;
135
+ }
136
+ /**
137
+ * Return boolean indicating whether a memo id is valid
138
+ *
139
+ * @param memoId - the memo id to be checked
140
+ */
141
+ isValidMemoId(memoId) {
142
+ return this.isValidMemo({ value: memoId });
143
+ }
144
+ /**
145
+ * Process address into address and memo id
146
+ * @param address - the address
147
+ */
148
+ getAddressDetails(address) {
149
+ const destinationDetails = url.parse(address);
150
+ const destinationAddress = destinationDetails.pathname;
151
+ if (!destinationAddress) {
152
+ throw new sdk_core_1.InvalidAddressError(`failed to parse address: ${address}`);
153
+ }
154
+ // EOS addresses have to be "human readable", which means up to 12 characters and only a-z1-5., i.e.mtoda1.bitgo
155
+ // source: https://developers.eos.io/eosio-cpp/docs/naming-conventions
156
+ if (!/^[a-z1-5.]*$/.test(destinationAddress) || destinationAddress.length > Eos.ADDRESS_LENGTH) {
157
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
158
+ }
159
+ // address doesn't have a memo id
160
+ if (destinationDetails.pathname === address) {
161
+ return {
162
+ address: address,
163
+ memoId: undefined,
164
+ };
165
+ }
166
+ if (!destinationDetails.query) {
167
+ throw new sdk_core_1.InvalidAddressError(`failed to parse query string: ${address}`);
168
+ }
169
+ const queryDetails = querystring.parse(destinationDetails.query);
170
+ if (!queryDetails.memoId) {
171
+ // if there are more properties, the query details need to contain the memoId property
172
+ throw new sdk_core_1.InvalidAddressError(`invalid property in address: ${address}`);
173
+ }
174
+ if (Array.isArray(queryDetails.memoId) && queryDetails.memoId.length !== 1) {
175
+ // valid addresses can only contain one memo id
176
+ throw new sdk_core_1.InvalidAddressError(`invalid address '${address}', must contain exactly one memoId`);
177
+ }
178
+ const [memoId] = _.castArray(queryDetails.memoId);
179
+ if (!this.isValidMemoId(memoId)) {
180
+ throw new sdk_core_1.InvalidAddressError(`invalid address: '${address}', memoId is not valid`);
181
+ }
182
+ return {
183
+ address: destinationAddress,
184
+ memoId,
185
+ };
186
+ }
187
+ /**
188
+ * Convert a currency amount represented in base units (satoshi, wei, atoms, drops, stroops)
189
+ * to big units (btc, eth, xrp, xlm)
190
+ */
191
+ baseUnitsToBigUnits(baseUnits) {
192
+ const dividend = this.getBaseFactor();
193
+ const bigNumber = new bignumber_js_1.BigNumber(baseUnits).dividedBy(dividend);
194
+ // set the format so commas aren't added to large coin amounts
195
+ return bigNumber.toFormat(4, null, { groupSeparator: '', decimalSeparator: '.' });
196
+ }
197
+ /**
198
+ * Validate and return address with appended memo id
199
+ *
200
+ * @param address
201
+ * @param memoId
202
+ */
203
+ normalizeAddress({ address, memoId }) {
204
+ if (memoId && this.isValidMemoId(memoId)) {
205
+ return `${address}?memoId=${memoId}`;
206
+ }
207
+ return address;
208
+ }
209
+ /**
210
+ * Return boolean indicating whether input is valid public key for the coin
211
+ *
212
+ * @param address - the address to be checked
213
+ */
214
+ isValidAddress(address) {
215
+ try {
216
+ const addressDetails = this.getAddressDetails(address);
217
+ return address === this.normalizeAddress(addressDetails);
218
+ }
219
+ catch (e) {
220
+ return false;
221
+ }
222
+ }
223
+ /**
224
+ * @param address - the address to verify
225
+ * @param rootAddress - the wallet's root address
226
+ * @return true iff address is a wallet address (based on rootAddress)
227
+ */
228
+ isWalletAddress({ address, rootAddress }) {
229
+ if (!rootAddress || !_.isString(rootAddress)) {
230
+ throw new Error('missing required string rootAddress');
231
+ }
232
+ if (!this.isValidAddress(address)) {
233
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
234
+ }
235
+ const addressDetails = this.getAddressDetails(address);
236
+ const rootAddressDetails = this.getAddressDetails(rootAddress);
237
+ if (!addressDetails || !rootAddressDetails) {
238
+ return false;
239
+ }
240
+ if (addressDetails.address !== rootAddressDetails.address) {
241
+ throw new sdk_core_1.UnexpectedAddressError(`address validation failure: ${addressDetails.address} vs ${rootAddressDetails.address}`);
242
+ }
243
+ return true;
244
+ }
245
+ /**
246
+ * Assemble keychain and half-sign prebuilt transaction
247
+ *
248
+ * @param params
249
+ * @param params.txPrebuild {Object} prebuild object returned by platform
250
+ * @param params.prv {String} user prv
251
+ * @returns {Promise<EosSignedTransaction>}
252
+ */
253
+ async signTransaction(params) {
254
+ const prv = params.prv;
255
+ const txHex = params.txPrebuild.txHex;
256
+ const transaction = params.txPrebuild.transaction;
257
+ const signBuffer = Buffer.from(txHex, 'hex');
258
+ const privateKeyBuffer = bip32.fromBase58(prv).privateKey;
259
+ if (!privateKeyBuffer) {
260
+ throw new Error('no privateKey');
261
+ }
262
+ const signature = ecc.Signature.sign(signBuffer, privateKeyBuffer).toString();
263
+ transaction.signatures.push(signature);
264
+ const txParams = {
265
+ transaction,
266
+ txHex,
267
+ recipients: params.txPrebuild.recipients,
268
+ headers: params.txPrebuild.headers,
269
+ txid: params.txPrebuild.txid,
270
+ };
271
+ return { halfSigned: txParams };
272
+ }
273
+ validateStakeActionData(stakeActionData) {
274
+ if (stakeActionData.from !== stakeActionData.receiver) {
275
+ throw new Error(`staker (${stakeActionData.from}) and receiver (${stakeActionData.receiver}) must be the same`);
276
+ }
277
+ if (stakeActionData.transfer !== 0) {
278
+ throw new Error('cannot transfer funds as part of delegatebw action');
279
+ }
280
+ // stake_cpu_quantity is used as the amount because the BitGo platform only stakes cpu for voting transactions
281
+ return {
282
+ address: stakeActionData.from,
283
+ amount: this.bigUnitsToBaseUnits(stakeActionData.stake_cpu_quantity.split(' ')[0]),
284
+ };
285
+ }
286
+ validateUnstakeActionData(unstakeActionData) {
287
+ if (unstakeActionData.from !== unstakeActionData.receiver) {
288
+ throw new Error(`unstaker (${unstakeActionData.from}) and receiver (${unstakeActionData.receiver}) must be the same`);
289
+ }
290
+ const cpuAmount = new bignumber_js_1.BigNumber(unstakeActionData.unstake_cpu_quantity.split(' ')[0]);
291
+ const netAmount = new bignumber_js_1.BigNumber(unstakeActionData.unstake_net_quantity.split(' ')[0]);
292
+ const totalAmount = cpuAmount.plus(netAmount).toNumber();
293
+ return {
294
+ address: unstakeActionData.receiver,
295
+ amount: this.bigUnitsToBaseUnits(totalAmount),
296
+ };
297
+ }
298
+ static validateVoteActionData(voteActionData) {
299
+ const proxyIsEmpty = _.isEmpty(voteActionData.proxy);
300
+ const producersIsEmpty = _.isEmpty(voteActionData.producers);
301
+ if ((proxyIsEmpty && producersIsEmpty) || (!proxyIsEmpty && !producersIsEmpty)) {
302
+ throw new Error('voting transactions must specify either producers or proxy to vote for');
303
+ }
304
+ return {
305
+ address: voteActionData.voter,
306
+ proxy: voteActionData.proxy,
307
+ producers: voteActionData.producers,
308
+ };
309
+ }
310
+ static createTransactionIdHex(serializedTransactionBuffer) {
311
+ return crypto_1.createHash('sha256').update(serializedTransactionBuffer).digest().toString('hex');
312
+ }
313
+ /**
314
+ * Deserialize a transaction
315
+ * @param transaction
316
+ * @param headers
317
+ */
318
+ async deserializeTransaction({ transaction, headers, }) {
319
+ // create an eosjs API client
320
+ const api = new eosjs_1.Api({
321
+ abiProvider: new eosabiprovider_1.OfflineAbiProvider(),
322
+ rpc: new NoopJsonRpc(),
323
+ signatureProvider: new NoopSignatureProvider(),
324
+ chainId: this.getChainId(),
325
+ // Use a custom TextDecoder as the global TextDecoder leads to crashes in OVC / Electron.
326
+ textDecoder: new utils_1.StringTextDecoder(),
327
+ textEncoder: new TextEncoder(),
328
+ });
329
+ // type guards
330
+ const isTransferActionData = (txActionData) => {
331
+ return (txActionData.from !== undefined &&
332
+ txActionData.to !== undefined &&
333
+ txActionData.quantity !== undefined);
334
+ };
335
+ const isStakeActionData = (txActionData) => {
336
+ return (txActionData.from !== undefined &&
337
+ txActionData.receiver !== undefined &&
338
+ txActionData.transfer !== undefined &&
339
+ txActionData.stake_cpu_quantity !== undefined);
340
+ };
341
+ const isUnstakeActionData = (txActionData) => {
342
+ return (txActionData.from !== undefined &&
343
+ txActionData.receiver !== undefined &&
344
+ txActionData.unstake_cpu_quantity !== undefined &&
345
+ txActionData.unstake_net_quantity !== undefined);
346
+ };
347
+ const isVoteActionData = (txActionData) => {
348
+ return txActionData.voter !== undefined;
349
+ };
350
+ const isRefundActionData = (txActionData) => {
351
+ return txActionData.owner !== undefined;
352
+ };
353
+ // deserializeTransaction
354
+ const serializedTxBuffer = Buffer.from(transaction.packed_trx, 'hex');
355
+ const deserializedTxJsonFromPackedTrx = await api.deserializeTransactionWithActions(serializedTxBuffer);
356
+ if (!deserializedTxJsonFromPackedTrx) {
357
+ throw new Error('could not process transaction from txHex');
358
+ }
359
+ const tx = deserializedTxJsonFromPackedTrx;
360
+ // validate context free actions
361
+ if (tx.context_free_actions.length !== 0) {
362
+ if (tx.context_free_actions.length !== 1) {
363
+ throw new Error('number of context free actions must be 1');
364
+ }
365
+ if (!_.isEqual(_.pick(tx.context_free_actions[0], ['account', 'authorization', 'name']), {
366
+ account: 'eosio.null',
367
+ authorization: [],
368
+ name: 'nonce',
369
+ }) ||
370
+ _.isEmpty(tx.context_free_actions[0].data)) {
371
+ throw new Error('the context free action is invalid');
372
+ }
373
+ }
374
+ // Only support transactions with one (transfer | voteproducer) or two (delegatebw & voteproducer) actions
375
+ if (tx.actions.length !== 1 && tx.actions.length !== 2) {
376
+ throw new Error(`invalid number of actions: ${tx.actions.length}`);
377
+ }
378
+ const txAction = tx.actions[0];
379
+ if (!txAction) {
380
+ throw new Error('missing transaction action');
381
+ }
382
+ if (txAction.name === 'transfer') {
383
+ // Transfers should only have 1 action
384
+ if (tx.actions.length !== 1) {
385
+ throw new Error(`transfers should only have 1 action: ${tx.actions.length} given`);
386
+ }
387
+ if (!isTransferActionData(txAction.data)) {
388
+ throw new Error('Invalid or incomplete transfer action data');
389
+ }
390
+ const transferActionData = txAction.data;
391
+ tx.address = transferActionData.to;
392
+ tx.amount = this.bigUnitsToBaseUnits(transferActionData.quantity.split(' ')[0]);
393
+ tx.memo = transferActionData.memo;
394
+ }
395
+ else if (txAction.name === 'delegatebw') {
396
+ // The delegatebw action should only be part of voting transactions
397
+ if (tx.actions.length !== 2) {
398
+ throw new Error(`staking transactions that include the delegatebw action should have 2 actions: ${tx.actions.length} given`);
399
+ }
400
+ const txAction2 = tx.actions[1];
401
+ if (txAction2.name !== 'voteproducer') {
402
+ throw new Error(`invalid staking transaction action: ${txAction2.name}, expecting: voteproducer`);
403
+ }
404
+ if (!isStakeActionData(txAction.data) || !isVoteActionData(txAction2.data)) {
405
+ throw new Error('Invalid or incomplete stake or vote action data');
406
+ }
407
+ const stakeActionData = txAction.data;
408
+ const voteActionData = txAction2.data;
409
+ const deserializedStakeAction = this.validateStakeActionData(stakeActionData);
410
+ const deserializedVoteAction = Eos.validateVoteActionData(voteActionData);
411
+ if (deserializedStakeAction.address !== deserializedVoteAction.address) {
412
+ throw new Error(`staker (${deserializedStakeAction.address}) and voter (${deserializedVoteAction.address}) must be the same`);
413
+ }
414
+ tx.amount = deserializedStakeAction.amount;
415
+ tx.proxy = deserializedVoteAction.proxy;
416
+ tx.producers = deserializedVoteAction.producers;
417
+ }
418
+ else if (txAction.name === 'voteproducer') {
419
+ if (tx.actions.length > 2) {
420
+ throw new Error('voting transactions should not have more than 2 actions');
421
+ }
422
+ let deserializedStakeAction;
423
+ if (tx.actions.length === 2) {
424
+ const txAction2 = tx.actions[1];
425
+ if (txAction2.name !== 'delegatebw') {
426
+ throw new Error(`invalid staking transaction action: ${txAction2.name}, expecting: delegatebw`);
427
+ }
428
+ if (!isStakeActionData(txAction.data)) {
429
+ throw new Error('Invalid or incomplete stake action data');
430
+ }
431
+ const stakeActionData = txAction.data;
432
+ deserializedStakeAction = this.validateStakeActionData(stakeActionData);
433
+ }
434
+ if (!isVoteActionData(txAction.data)) {
435
+ throw new Error('Invalid or incomplete vote action data');
436
+ }
437
+ const voteActionData = txAction.data;
438
+ const deserializedVoteAction = Eos.validateVoteActionData(voteActionData);
439
+ if (!!deserializedStakeAction && deserializedStakeAction.address !== deserializedVoteAction.address) {
440
+ throw new Error(`staker (${deserializedStakeAction.address}) and voter (${deserializedVoteAction.address}) must be the same`);
441
+ }
442
+ tx.amount = !!deserializedStakeAction ? deserializedStakeAction.amount : '0';
443
+ tx.proxy = deserializedVoteAction.proxy;
444
+ tx.producers = deserializedVoteAction.producers;
445
+ }
446
+ else if (txAction.name === 'undelegatebw') {
447
+ if (tx.actions.length !== 1) {
448
+ throw new Error(`unstake should only have 1 action: ${tx.actions.length} given`);
449
+ }
450
+ if (!isUnstakeActionData(txAction.data)) {
451
+ throw new Error('Invalid or incomplete unstake action data');
452
+ }
453
+ const unstakeActionData = txAction.data;
454
+ const deserializedUnstakeAction = this.validateUnstakeActionData(unstakeActionData);
455
+ tx.amount = deserializedUnstakeAction.amount;
456
+ tx.address = deserializedUnstakeAction.address;
457
+ }
458
+ else if (txAction.name === 'refund') {
459
+ if (tx.actions.length !== 1) {
460
+ throw new Error(`refund should only have 1 action: ${tx.actions.length} given`);
461
+ }
462
+ if (!isRefundActionData(txAction.data)) {
463
+ throw new Error('Invalid or incomplete refund action data');
464
+ }
465
+ const refundActionData = txAction.data;
466
+ tx.address = refundActionData.owner;
467
+ tx.amount = '0';
468
+ }
469
+ else {
470
+ throw new Error(`invalid action: ${txAction.name}`);
471
+ }
472
+ // Get the tx id if tx headers were provided
473
+ if (headers) {
474
+ let rebuiltTransaction;
475
+ try {
476
+ // remove Z at the end
477
+ if (headers.expiration.endsWith('Z')) {
478
+ headers.expiration = headers.expiration.slice(0, -1);
479
+ }
480
+ rebuiltTransaction = await api.transact({ ...tx, ...headers }, { sign: false, broadcast: false });
481
+ }
482
+ catch (e) {
483
+ throw new Error('Could not build transaction to get transaction_id. Please check transaction or headers format.');
484
+ }
485
+ tx.transaction_id = Eos.createTransactionIdHex(rebuiltTransaction.serializedTransaction);
486
+ }
487
+ return tx;
488
+ }
489
+ /**
490
+ * Explain/parse transaction
491
+ * @param params - ExplainTransactionOptions
492
+ */
493
+ async explainTransaction(params) {
494
+ let transaction;
495
+ try {
496
+ transaction = await this.deserializeTransaction(params);
497
+ }
498
+ catch (e) {
499
+ throw new Error('invalid EOS transaction or headers: ' + e.toString());
500
+ }
501
+ return {
502
+ displayOrder: [
503
+ 'id',
504
+ 'outputAmount',
505
+ 'changeAmount',
506
+ 'outputs',
507
+ 'changeOutputs',
508
+ 'fee',
509
+ 'memo',
510
+ 'proxy',
511
+ 'producers',
512
+ ],
513
+ id: transaction.transaction_id,
514
+ changeOutputs: [],
515
+ outputAmount: transaction.amount,
516
+ changeAmount: 0,
517
+ outputs: !!transaction.address ? [{ address: transaction.address, amount: transaction.amount }] : [],
518
+ fee: {},
519
+ memo: transaction.memo,
520
+ proxy: transaction.proxy,
521
+ producers: transaction.producers,
522
+ };
523
+ }
524
+ /**
525
+ * @deprecated
526
+ */
527
+ initiateRecovery(params) {
528
+ throw new Error('deprecated method');
529
+ }
530
+ /**
531
+ * Make a request to one of the public EOS nodes available
532
+ * @param params.endpoint
533
+ * @param params.payload
534
+ */
535
+ async getDataFromNode(params) {
536
+ const nodeUrls = this.getPublicNodeUrls();
537
+ for (const nodeUrl of nodeUrls) {
538
+ try {
539
+ return await request.post(nodeUrl + params.endpoint).send(params.payload);
540
+ }
541
+ catch (e) {
542
+ // let's hope another call succeeds
543
+ }
544
+ }
545
+ throw new Error(`Unable to call endpoint: ${params.endpoint} from nodes: ${_.join(nodeUrls, ', ')}`);
546
+ }
547
+ /**
548
+ * Get EOS chain info from a public node
549
+ */
550
+ async getChainInfoFromNode() {
551
+ const response = await this.getDataFromNode({ endpoint: '/v1/chain/get_info' });
552
+ if (response.status !== 200) {
553
+ throw new Error('Unable to fetch chain info');
554
+ }
555
+ return response.body;
556
+ }
557
+ /**
558
+ * Get data specific to an account from a public node
559
+ * @param address
560
+ */
561
+ async getAccountFromNode({ address }) {
562
+ const response = await this.getDataFromNode({
563
+ endpoint: '/v1/chain/get_account',
564
+ payload: { account_name: address },
565
+ });
566
+ if (response.status !== 200) {
567
+ throw new Error('Account not found');
568
+ }
569
+ return response.body;
570
+ }
571
+ /**
572
+ * Get block data from a public node using its block number or block id
573
+ * @param blockNumOrId
574
+ */
575
+ async getBlockFromNode({ blockNumOrId }) {
576
+ const response = await this.getDataFromNode({
577
+ endpoint: '/v1/chain/get_block',
578
+ payload: { block_num_or_id: blockNumOrId },
579
+ });
580
+ if (response.status !== 200) {
581
+ throw new Error('Block not found');
582
+ }
583
+ return response.body;
584
+ }
585
+ /**
586
+ * Get headers for an EOS tx from a public node
587
+ */
588
+ async getTransactionHeadersFromNode() {
589
+ const chainInfo = await this.getChainInfoFromNode();
590
+ const headBlockInfoResult = await this.getBlockFromNode({ blockNumOrId: chainInfo.head_block_num });
591
+ const expireSeconds = 28800; // maximum tx expire time of 8h
592
+ const chainDate = new Date(chainInfo.head_block_time + 'Z').getTime();
593
+ const expirationDate = new Date(chainDate + expireSeconds * 1000);
594
+ return {
595
+ expiration: expirationDate.toISOString(),
596
+ ref_block_num: chainInfo.head_block_num & 0xffff,
597
+ ref_block_prefix: headBlockInfoResult.ref_block_prefix,
598
+ };
599
+ }
600
+ getTransferAction({ recipient, sender, amount, memo }) {
601
+ return {
602
+ account: 'eosio.token',
603
+ name: 'transfer',
604
+ authorization: [
605
+ {
606
+ actor: sender,
607
+ permission: 'active',
608
+ },
609
+ ],
610
+ data: {
611
+ from: sender,
612
+ to: recipient,
613
+ quantity: `${this.baseUnitsToBigUnits(amount)} EOS`,
614
+ memo: !_.isNil(memo) ? memo : '', // Memo must be defined, set it to empty string if it is not
615
+ },
616
+ };
617
+ }
618
+ /**
619
+ * Sign a transaction with a key
620
+ * @param signableTx
621
+ * @param signingKey
622
+ */
623
+ signTx(signableTx, signingKey) {
624
+ const signBuffer = Buffer.from(signableTx, 'hex');
625
+ const privateKeyBuffer = signingKey.privateKey;
626
+ return ecc.Signature.sign(signBuffer, privateKeyBuffer).toString();
627
+ }
628
+ /**
629
+ * Builds a funds recovery transaction without BitGo
630
+ * @param params
631
+ */
632
+ async recover(params) {
633
+ if (!params.rootAddress) {
634
+ throw new Error('missing required string rootAddress');
635
+ }
636
+ const isKrsRecovery = sdk_core_1.getIsKrsRecovery(params);
637
+ const isUnsignedSweep = sdk_core_1.getIsUnsignedSweep(params);
638
+ const { krsProvider } = params;
639
+ if (sdk_core_1.getIsKrsRecovery(params)) {
640
+ sdk_core_1.checkKrsProvider(this, krsProvider);
641
+ }
642
+ if (!this.isValidAddress(params.recoveryDestination)) {
643
+ throw new Error('Invalid destination address!');
644
+ }
645
+ const keys = sdk_core_1.getBip32Keys(this.bitgo, params, { requireBitGoXpub: false });
646
+ const rootAddressDetails = this.getAddressDetails(params.rootAddress);
647
+ const account = await this.getAccountFromNode({ address: rootAddressDetails.address });
648
+ if (!account.core_liquid_balance) {
649
+ throw new Error('Could not find any balance to recovery for ' + params.rootAddress);
650
+ }
651
+ if (!account.permissions) {
652
+ throw new Error('Could not find permissions for ' + params.rootAddress);
653
+ }
654
+ const userPub = ecc.PublicKey.fromBuffer(keys[0].publicKey).toString();
655
+ const backupPub = ecc.PublicKey.fromBuffer(keys[1].publicKey).toString();
656
+ const activePermission = _.find(account.permissions, { perm_name: 'active' });
657
+ const requiredAuth = _.get(activePermission, 'required_auth');
658
+ if (!requiredAuth) {
659
+ throw new Error('Required auth for active permission not found in account');
660
+ }
661
+ if (requiredAuth.threshold !== 2) {
662
+ throw new Error('Unexpected active permission threshold');
663
+ }
664
+ const foundPubs = {};
665
+ const requiredAuthKeys = requiredAuth.keys;
666
+ for (const signer of requiredAuthKeys) {
667
+ if (signer.weight !== 1) {
668
+ throw new Error('invalid signer weight');
669
+ }
670
+ // if it's a dupe of a pub we already know, block
671
+ if (foundPubs[signer.key]) {
672
+ throw new Error('duplicate signer key');
673
+ }
674
+ foundPubs[signer.key] = (foundPubs[signer.key] || 0) + 1;
675
+ }
676
+ if (foundPubs[userPub] !== 1 || foundPubs[backupPub] !== 1) {
677
+ throw new Error('unexpected incidence frequency of user signer key');
678
+ }
679
+ const accountBalance = account.core_liquid_balance.split(' ')[0];
680
+ const recoveryAmount = this.bigUnitsToBaseUnits(new bignumber_js_1.BigNumber(accountBalance).toFixed());
681
+ const destinationAddress = params.recoveryDestination;
682
+ const destinationAddressDetails = this.getAddressDetails(destinationAddress);
683
+ const destinationAccount = await this.getAccountFromNode({ address: destinationAddressDetails.address });
684
+ if (!destinationAccount) {
685
+ throw new Error('Destination account not found');
686
+ }
687
+ const transactionHeaders = await this.getTransactionHeadersFromNode();
688
+ if (!transactionHeaders) {
689
+ throw new Error('Could not get transaction headers from node');
690
+ }
691
+ const headers = transactionHeaders;
692
+ const nativeDate = new Date(headers.expiration);
693
+ // drop milliseconds and trailing Z from expiration
694
+ nativeDate.setMilliseconds(0);
695
+ const expiration = nativeDate.toISOString();
696
+ if (expiration.endsWith('Z')) {
697
+ headers.expiration = expiration.slice(0, -1);
698
+ }
699
+ // create an offline eosjs API client
700
+ const api = new eosjs_1.Api({
701
+ rpc: new NoopJsonRpc(),
702
+ signatureProvider: new NoopSignatureProvider(),
703
+ abiProvider: new eosabiprovider_1.OfflineAbiProvider(),
704
+ chainId: this.getChainId(),
705
+ textDecoder: new TextDecoder(),
706
+ textEncoder: new TextEncoder(),
707
+ });
708
+ const transferAction = this.getTransferAction({
709
+ recipient: destinationAddressDetails.address,
710
+ sender: rootAddressDetails.address,
711
+ amount: new bignumber_js_1.BigNumber(recoveryAmount),
712
+ memo: destinationAddressDetails.memoId,
713
+ });
714
+ let serializedTransaction;
715
+ const tx = { actions: [transferAction] };
716
+ try {
717
+ serializedTransaction = await api.transact({ ...tx, ...headers }, { sign: false, broadcast: false });
718
+ }
719
+ catch (e) {
720
+ throw new Error('Eos API error: Could not build transaction');
721
+ }
722
+ // create transaction object
723
+ const serializedTransactionHex = Buffer.from(serializedTransaction.serializedTransaction).toString('hex');
724
+ const transactionId = Eos.createTransactionIdHex(serializedTransaction.serializedTransaction);
725
+ const txObject = {
726
+ transaction: {
727
+ compression: 'none',
728
+ packed_trx: serializedTransactionHex,
729
+ signatures: [],
730
+ },
731
+ txid: transactionId,
732
+ recoveryAmount: accountBalance,
733
+ coin: this.getChain(),
734
+ txHex: '',
735
+ };
736
+ const signableTx = Buffer.concat([
737
+ Buffer.from(this.getChainId(), 'hex'),
738
+ Buffer.from(serializedTransaction.serializedTransaction),
739
+ Buffer.from(new Uint8Array(32)), // Some padding
740
+ ]).toString('hex');
741
+ if (isUnsignedSweep) {
742
+ txObject.txHex = signableTx;
743
+ return txObject;
744
+ }
745
+ const userSignature = this.signTx(signableTx, keys[0]);
746
+ txObject.transaction.signatures.push(userSignature);
747
+ if (!isKrsRecovery) {
748
+ const backupSignature = this.signTx(signableTx, keys[1]);
749
+ txObject.transaction.signatures.push(backupSignature);
750
+ }
751
+ return txObject;
752
+ }
753
+ async parseTransaction(params) {
754
+ return {};
755
+ }
756
+ /**
757
+ * Verify that a transaction prebuild complies with the original intention
758
+ *
759
+ * @param params
760
+ * @param params.txParams params used to build the transaction
761
+ * @param params.txPrebuild the prebuilt transaction
762
+ */
763
+ async verifyTransaction(params) {
764
+ var _a;
765
+ const { txParams: txParams, txPrebuild: txPrebuild } = params;
766
+ // check if the transaction has a txHex
767
+ if (!txPrebuild.txHex) {
768
+ throw new Error('missing required tx prebuild property txHex');
769
+ }
770
+ // construct transaction from txHex
771
+ const txFromHex = Buffer.from(txPrebuild.txHex, 'hex');
772
+ const txDataWithPadding = txFromHex.slice(32);
773
+ const txData = txDataWithPadding.slice(0, txDataWithPadding.length - 32);
774
+ const deserializedTxJson = await this.deserializeTransaction({
775
+ transaction: { packed_trx: txData.toString('hex') },
776
+ headers: txPrebuild.headers,
777
+ });
778
+ if (!deserializedTxJson) {
779
+ throw new Error('could not process transaction from txHex');
780
+ }
781
+ const txJsonFromHex = deserializedTxJson;
782
+ // check that if txParams has a txPrebuild, it should be the same as txPrebuild
783
+ if (txParams.txPrebuild && !_.isEqual(txParams.txPrebuild, txPrebuild)) {
784
+ throw new Error('inputs txParams.txPrebuild and txPrebuild expected to be equal but were not');
785
+ }
786
+ // check if prebuild has a transaction
787
+ if (!txPrebuild.transaction) {
788
+ throw new Error('missing required transaction in txPrebuild');
789
+ }
790
+ // check if transaction has a packed_trx
791
+ if (!((_a = txPrebuild.transaction) === null || _a === void 0 ? void 0 : _a.packed_trx)) {
792
+ throw new Error('missing required transaction.packed_trx in txPrebuild');
793
+ }
794
+ // construct transaction using packed_trx
795
+ const deserializedTxJsonFromPackedTrx = await this.deserializeTransaction({
796
+ transaction: { packed_trx: txPrebuild.transaction.packed_trx },
797
+ headers: txPrebuild.headers,
798
+ });
799
+ if (!deserializedTxJsonFromPackedTrx) {
800
+ throw new Error('could not process transaction from packed_trx');
801
+ }
802
+ const txJsonFromPackedTrx = deserializedTxJsonFromPackedTrx;
803
+ // deep check of object from packed_trx and txHex
804
+ if (!_.isEqual(txJsonFromPackedTrx, txJsonFromHex)) {
805
+ throw new Error('unpacked packed_trx and unpacked txHex are not equal');
806
+ }
807
+ if (txParams.recipients.length > 1) {
808
+ throw new Error('only 0 or 1 recipients are supported');
809
+ }
810
+ // check the amounts, recipient, and coin name for transfers
811
+ if (txParams.recipients.length === 1) {
812
+ const expectedOutput = txParams.recipients[0];
813
+ // check output address and memoId
814
+ const expectedOutputAddressAndMemoId = this.getAddressDetails(expectedOutput.address);
815
+ const txHexAction = txJsonFromHex.actions[0];
816
+ const txHexTransferAction = txHexAction.data;
817
+ if (txHexTransferAction.to !== expectedOutputAddressAndMemoId.address) {
818
+ throw new Error('txHex receive address does not match expected recipient address');
819
+ }
820
+ // check if txaction memoid is equal to address memo id only if address also has memoid present
821
+ if (!_.isUndefined(expectedOutputAddressAndMemoId.memoId)) {
822
+ if (txHexTransferAction.memo !== expectedOutputAddressAndMemoId.memoId) {
823
+ throw new Error('txHex receive memoId does not match expected recipient memoId');
824
+ }
825
+ }
826
+ // check amount and coin
827
+ const expectedOutputAmount = expectedOutput.amount;
828
+ const actualAmountAndCoin = txHexTransferAction.quantity.split(' ');
829
+ const actualOutputAmount = this.bigUnitsToBaseUnits(actualAmountAndCoin[0]);
830
+ if (expectedOutputAmount !== actualOutputAmount) {
831
+ throw new Error('txHex receive amount does not match expected recipient amount');
832
+ }
833
+ if (txPrebuild.coin === 'eos' || txPrebuild.coin === 'teos') {
834
+ const expectedSymbol = _.isNil(txPrebuild.token) ? 'EOS' : txPrebuild.token.split(':')[1];
835
+ if (actualAmountAndCoin[1] !== expectedSymbol) {
836
+ throw new Error('txHex receive symbol does not match expected recipient symbol');
837
+ }
838
+ }
839
+ else {
840
+ // this should never happen
841
+ throw new Error('txHex coin name does not match expected coin name');
842
+ }
843
+ }
844
+ return true;
845
+ }
846
+ /**
847
+ * Generate a random EOS address.
848
+ *
849
+ * This is just a random string which abides by the EOS adddress constraints,
850
+ * and is not actually checked for availability on the EOS blockchain.
851
+ *
852
+ * Current EOS address constraints are:
853
+ * * Address must be exactly 12 characters
854
+ * * Address must only contain lowercase letters and numbers 1-5
855
+ * @returns a validly formatted EOS address, which may or may not actually be available on chain.
856
+ */
857
+ generateRandomAddress(params) {
858
+ const address = [];
859
+ while (address.length < 12) {
860
+ const char = _.sample(Eos.VALID_ADDRESS_CHARS);
861
+ if (!char) {
862
+ throw new Error('failed to sample valid EOS address characters');
863
+ }
864
+ address.push(char);
865
+ }
866
+ return address.join('');
867
+ }
868
+ }
869
+ exports.Eos = Eos;
870
+ Eos.VALID_ADDRESS_CHARS = '12345abcdefghijklmnopqrstuvwxyz'.split('');
871
+ Eos.ADDRESS_LENGTH = 12;
872
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW9zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Vvcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0dBRUc7QUFDSCwrQ0FBeUM7QUFDekMsNkNBQStCO0FBQy9CLG1DQUFpRDtBQUNqRCxpQ0FBbUU7QUFDbkUsK0NBQWlDO0FBQ2pDLDBDQUE0QjtBQUM1Qix5REFBMkM7QUFDM0Msb0RBQXNDO0FBQ3RDLHlDQUEyQjtBQUUzQiw2REFBOEQ7QUFDOUQsdUNBQWdEO0FBQ2hELDhDQXFCeUI7QUFvSnpCLE1BQU0sV0FBWSxTQUFRLGVBQU87SUFDL0I7UUFDRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDWixDQUFDO0NBQ0Y7QUFFRCxNQUFNLHFCQUFxQjtJQUN6QixLQUFLLENBQUMsZ0JBQWdCO1FBQ3BCLE1BQU0sSUFBSSxLQUFLLENBQUMsOERBQThELENBQUMsQ0FBQztJQUNsRixDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUF5QztRQUNsRCxNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxDQUFDLENBQUM7SUFDM0QsQ0FBQztDQUNGO0FBRUQsTUFBYSxHQUFJLFNBQVEsbUJBQVE7SUFJL0IsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFnQjtRQUNwQyxPQUFPLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hCLENBQUM7SUFFRCxVQUFVO1FBQ1IsT0FBTyxrRUFBa0UsQ0FBQyxDQUFDLG1CQUFtQjtJQUNoRyxDQUFDO0lBRUQsUUFBUTtRQUNOLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELFNBQVM7UUFDUCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxXQUFXO1FBQ1QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsYUFBYTtRQUNYLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVEOzs7T0FHRztJQUNILHdCQUF3QjtR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QUU7b0JBQzdDLE1BQU0sSUFBSSxLQUFLLENBQUMsK0RBQStELENBQUMsQ0FBQztpQkFDbEY7YUFDRjtpQkFBTTtnQkFDTCwyQkFBMkI7Z0JBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQzthQUN0RTtTQUNGO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILHFCQUFxQixDQUFDLE1BQTZCO1FBQ2pELE1BQU0sT0FBTyxHQUFhLEVBQUUsQ0FBQztRQUM3QixPQUFPLE9BQU8sQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFO1lBQzFCLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDVCxNQUFNLElBQUksS0FBSyxDQUFDLCtDQUErQyxDQUFDLENBQUM7YUFDbEU7WUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3BCO1FBQ0QsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzFCLENBQUM7O0FBbjdCSCxrQkFvN0JDO0FBbjdCZSx1QkFBbUIsR0FBRyxpQ0FBaUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDbEUsa0JBQWMsR0FBRyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwcmV0dGllclxuICovXG5pbXBvcnQgeyBCaWdOdW1iZXIgfSBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0ICogYXMgYmlwMzIgZnJvbSAnYmlwMzInO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCwgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgQXBpLCBBcGlJbnRlcmZhY2VzLCBKc29uUnBjLCBScGNJbnRlcmZhY2VzIH0gZnJvbSAnZW9zanMnO1xuaW1wb3J0ICogYXMgZWNjIGZyb20gJ2Vvc2pzLWVjYyc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBxdWVyeXN0cmluZyBmcm9tICdxdWVyeXN0cmluZyc7XG5pbXBvcnQgKiBhcyByZXF1ZXN0IGZyb20gJ3N1cGVyYWdlbnQnO1xuaW1wb3J0ICogYXMgdXJsIGZyb20gJ3VybCc7XG5cbmltcG9ydCB7IE9mZmxpbmVBYmlQcm92aWRlciB9IGZyb20gJy4vZW9zdXRpbC9lb3NhYmlwcm92aWRlcic7XG5pbXBvcnQgeyBTdHJpbmdUZXh0RGVjb2RlciB9IGZyb20gJy4vbGliL3V0aWxzJztcbmltcG9ydCB7XG4gIEJhc2VDb2luLFxuICBCaXRHb0Jhc2UsXG4gIGNoZWNrS3JzUHJvdmlkZXIsXG4gIEVudmlyb25tZW50cyxcbiAgZ2V0QmlwMzJLZXlzLFxuICBnZXRJc0tyc1JlY292ZXJ5LFxuICBnZXRJc1Vuc2lnbmVkU3dlZXAsXG4gIEhhbGZTaWduZWRBY2NvdW50VHJhbnNhY3Rpb24gYXMgQmFzZUhhbGZTaWduZWRUcmFuc2FjdGlvbixcbiAgSW52YWxpZEFkZHJlc3NFcnJvcixcbiAgS2V5UGFpcixcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBSZXF1ZXN0VHJhY2VyLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zIGFzIEJhc2VTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLFxuICBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yLFxuICBWZXJpZmljYXRpb25PcHRpb25zLFxuICBWZXJpZnlBZGRyZXNzT3B0aW9ucyBhcyBCYXNlVmVyaWZ5QWRkcmVzc09wdGlvbnMsXG4gIFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyBhcyBCYXNlVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zLFxuICBXYWxsZXQsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5cbmludGVyZmFjZSBBZGRyZXNzRGV0YWlscyB7XG4gIGFkZHJlc3M6IHN0cmluZztcbiAgbWVtb0lkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVvc1R4IHtcbiAgc2lnbmF0dXJlczogc3RyaW5nW107XG4gIHBhY2tlZF90cng6IHN0cmluZztcbiAgY29tcHJlc3Npb246IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWNpcGllbnQge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgRW9zVHJhbnNhY3Rpb25IZWFkZXJzIHtcbiAgcmVmX2Jsb2NrX3ByZWZpeDogbnVtYmVyO1xuICByZWZfYmxvY2tfbnVtOiBudW1iZXI7XG4gIGV4cGlyYXRpb24/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBFb3NUcmFuc2FjdGlvbkFjdGlvbiB7XG4gIGFjY291bnQ6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICBhdXRob3JpemF0aW9uOiBbeyBhY3Rvcjogc3RyaW5nOyBwZXJtaXNzaW9uOiBzdHJpbmcgfV07XG4gIGRhdGE6IFRyYW5zZmVyQWN0aW9uRGF0YSB8IFN0YWtlQWN0aW9uRGF0YSB8IFZvdGVBY3Rpb25EYXRhO1xufVxuXG5pbnRlcmZhY2UgRW9zVHJhbnNhY3Rpb25QcmVidWlsZCB7XG4gIHJlY2lwaWVudHM6IFJlY2lwaWVudFtdO1xuICBoZWFkZXJzOiBFb3NUcmFuc2FjdGlvbkhlYWRlcnM7XG4gIHR4SGV4OiBzdHJpbmc7IC8vIFRoZSBzaWduYWJsZSB0eCBoZXggc3RyaW5nXG4gIHRyYW5zYWN0aW9uOiBFb3NUeDtcbiAgdHhpZDogc3RyaW5nO1xuICBjb2luOiBzdHJpbmc7XG4gIC8vIGZ1bGwgdG9rZW4gbmFtZSB3aXRoIHRoZSBmb3JtYXQsIFt0XWVvczpTWU1CT0wuIFRoaXMgd2lsbCBvbmx5IGJlIHByZXNlbnQgZm9yIHRva2VuIHRyYW5zYWN0aW9ucy4gZS5nLiB0ZW9zOkNIRVguXG4gIHRva2VuPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVvc1NpZ25UcmFuc2FjdGlvblBhcmFtcyBleHRlbmRzIEJhc2VTaWduVHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgcHJ2OiBzdHJpbmc7XG4gIHR4UHJlYnVpbGQ6IEVvc1RyYW5zYWN0aW9uUHJlYnVpbGQ7XG4gIHJlY2lwaWVudHM6IFJlY2lwaWVudFtdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVvc1ZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIEJhc2VWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eFByZWJ1aWxkOiBFb3NUcmFuc2FjdGlvblByZWJ1aWxkO1xuICB0eFBhcmFtczogRW9zU2lnblRyYW5zYWN0aW9uUGFyYW1zO1xuICB3YWxsZXQ6IFdhbGxldDtcbiAgdmVyaWZpY2F0aW9uPzogVmVyaWZpY2F0aW9uT3B0aW9ucztcbiAgcmVxSWQ/OiBSZXF1ZXN0VHJhY2VyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVvc0hhbGZTaWduZWQge1xuICByZWNpcGllbnRzOiBSZWNpcGllbnRbXTtcbiAgaGVhZGVyczogRW9zVHJhbnNhY3Rpb25IZWFkZXJzO1xuICB0eEhleDogc3RyaW5nOyAvLyBUaGUgc2lnbmFibGUgdHggaGV4IHN0cmluZ1xuICB0cmFuc2FjdGlvbjogRW9zVHg7XG4gIHR4aWQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFb3NTaWduZWRUcmFuc2FjdGlvbiBleHRlbmRzIEJhc2VIYWxmU2lnbmVkVHJhbnNhY3Rpb24ge1xuICBoYWxmU2lnbmVkOiBFb3NIYWxmU2lnbmVkO1xufVxuXG5pbnRlcmZhY2UgRGVzZXJpYWxpemVkRW9zVHJhbnNhY3Rpb24ge1xuICBleHBpcmF0aW9uOiBzdHJpbmc7XG4gIHJlZl9ibG9ja19udW06IHN0cmluZztcbiAgcmVmX2Jsb2NrX3ByZWZpeDogc3RyaW5nO1xuICBtYXhfbmV0X3VzYWdlX3dvcmRzOiBudW1iZXI7XG4gIG1heF9jcHVfdXNhZ2VfbXM6IG51bWJlcjtcbiAgZGVsYXlfc2VjOiBudW1iZXI7XG4gIGNvbnRleHRfZnJlZV9hY3Rpb25zOiBFb3NUcmFuc2FjdGlvbkFjdGlvbltdO1xuICBhY3Rpb25zOiBFb3NUcmFuc2FjdGlvbkFjdGlvbltdO1xuICB0cmFuc2FjdGlvbl9leHRlbnNpb25zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPltdO1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogc3RyaW5nO1xuICB0cmFuc2FjdGlvbl9pZDogc3RyaW5nO1xuICBtZW1vPzogc3RyaW5nO1xuICBwcm94eT86IHN0cmluZztcbiAgcHJvZHVjZXJzPzogc3RyaW5nW107XG59XG5cbmludGVyZmFjZSBUcmFuc2ZlckFjdGlvbkRhdGEge1xuICBmcm9tOiBzdHJpbmc7XG4gIHRvOiBzdHJpbmc7XG4gIHF1YW50aXR5OiBzdHJpbmc7XG4gIG1lbW8/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBTdGFrZUFjdGlvbkRhdGEge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogc3RyaW5nO1xuICBmcm9tOiBzdHJpbmc7XG4gIHJlY2VpdmVyOiBzdHJpbmc7XG4gIHRyYW5zZmVyOiBudW1iZXI7XG4gIHN0YWtlX2NwdV9xdWFudGl0eTogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgVW5zdGFrZUFjdGlvbkRhdGEge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGFtb3VudDogc3RyaW5nO1xuICBmcm9tOiBzdHJpbmc7XG4gIHJlY2VpdmVyOiBzdHJpbmc7XG4gIHVuc3Rha2VfY3B1X3F1YW50aXR5OiBzdHJpbmc7XG4gIHVuc3Rha2VfbmV0X3F1YW50aXR5OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBSZWZ1bmRBY3Rpb25EYXRhIHtcbiAgYWRkcmVzczogc3RyaW5nO1xuICBvd25lcjogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgVm90ZUFjdGlvbkRhdGEge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIHByb3h5OiBzdHJpbmc7XG4gIHByb2R1Y2Vyczogc3RyaW5nW107XG4gIHZvdGVyOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgdHJhbnNhY3Rpb246IHsgcGFja2VkX3RyeDogc3RyaW5nIH07XG4gIGhlYWRlcnM6IEVvc1RyYW5zYWN0aW9uSGVhZGVycztcbn1cblxuaW50ZXJmYWNlIFJlY292ZXJ5VHJhbnNhY3Rpb24ge1xuICB0cmFuc2FjdGlvbjogRW9zVHg7XG4gIHR4aWQ6IHN0cmluZztcbiAgcmVjb3ZlcnlBbW91bnQ6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFJlY292ZXJ5T3B0aW9ucyB7XG4gIHVzZXJLZXk6IHN0cmluZzsgLy8gQm94IEFcbiAgYmFja3VwS2V5OiBzdHJpbmc7IC8vIEJveCBCXG4gIGJpdGdvS2V5Pzogc3RyaW5nOyAvLyBCb3ggQ1xuICByZWNvdmVyeURlc3RpbmF0aW9uOiBzdHJpbmc7XG4gIGtyc1Byb3ZpZGVyPzogc3RyaW5nO1xuICB3YWxsZXRQYXNzcGhyYXNlPzogc3RyaW5nO1xuICByb290QWRkcmVzcz86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFZlcmlmeUFkZHJlc3NPcHRpb25zIGV4dGVuZHMgQmFzZVZlcmlmeUFkZHJlc3NPcHRpb25zIHtcbiAgcm9vdEFkZHJlc3M6IHN0cmluZztcbn1cblxuY2xhc3MgTm9vcEpzb25ScGMgZXh0ZW5kcyBKc29uUnBjIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoJycpO1xuICB9XG59XG5cbmNsYXNzIE5vb3BTaWduYXR1cmVQcm92aWRlciBpbXBsZW1lbnRzIEFwaUludGVyZmFjZXMuU2lnbmF0dXJlUHJvdmlkZXIge1xuICBhc3luYyBnZXRBdmFpbGFibGVLZXlzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ25vb3Agc2lnbmF0dXJlIHByb3ZpZGVyIGltcGxlbWVudGF0aW9uIGhhcyBubyBhdmFpbGFibGUga2V5cycpO1xuICB9XG5cbiAgYXN5bmMgc2lnbihhcmdzOiBBcGlJbnRlcmZhY2VzLlNpZ25hdHVyZVByb3ZpZGVyQXJncyk6IFByb21pc2U8UnBjSW50ZXJmYWNlcy5QdXNoVHJhbnNhY3Rpb25BcmdzPiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdub29wIGltcGxlbWVudGF0aW9uIGlzIHVuYWJsZSB0byBzaWduJyk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEVvcyBleHRlbmRzIEJhc2VDb2luIHtcbiAgcHVibGljIHN0YXRpYyBWQUxJRF9BRERSRVNTX0NIQVJTID0gJzEyMzQ1YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonLnNwbGl0KCcnKTtcbiAgcHVibGljIHN0YXRpYyBBRERSRVNTX0xFTkdUSCA9IDEyO1xuXG4gIHN0YXRpYyBjcmVhdGVJbnN0YW5jZShiaXRnbzogQml0R29CYXNlKTogQmFzZUNvaW4ge1xuICAgIHJldHVybiBuZXcgRW9zKGJpdGdvKTtcbiAgfVxuXG4gIGdldENoYWluSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ2FjYTM3NmYyMDZiOGZjMjVhNmVkNDRkYmRjNjY1NDdjMzZjNmMzM2UzYTExOWZmYmVhZWY5NDM2NDJmMGU5MDYnOyAvLyBtYWlubmV0IGNoYWluIGlkXG4gIH1cblxuICBnZXRDaGFpbigpOiBzdHJpbmcge1xuICAgIHJldHVybiAnZW9zJztcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBzdHJpbmcge1xuICAgIHJldHVybiAnZW9zJztcbiAgfVxuXG4gIGdldEZ1bGxOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdFT1MnO1xuICB9XG5cbiAgZ2V0QmFzZUZhY3RvcigpOiBudW1iZXIge1xuICAgIHJldHVybiAxZTQ7XG4gIH1cblxuICAvKipcbiAgICogRmxhZyBmb3Igc2VuZGluZyB2YWx1ZSBvZiAwXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG9rYXkgdG8gc2VuZCAwIHZhbHVlLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHZhbHVlbGVzc1RyYW5zZmVyQWxsb3dlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgVVJMcyBvZiBzb21lIGFjdGl2ZSBwdWJsaWMgbm9kZXNcbiAgICovXG4gIGdldFB1YmxpY05vZGVVcmxzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLmVvc05vZGVVcmxzO1xuICB9XG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBzZWNwMjU2azEga2V5IHBhaXJcbiAgICpcbiAgICogQHBhcmFtIHNlZWQgLSBTZWVkIGZyb20gd2hpY2ggdGhlIG5ldyBrZXlwYWlyIHNob3VsZCBiZSBnZW5lcmF0ZWQsIG90aGVyd2lzZSBhIHJhbmRvbSBzZWVkIGlzIHVzZWRcbiAgICovXG4gIGdlbmVyYXRlS2V5UGFpcihzZWVkPzogQnVmZmVyKTogS2V5UGFpciB7XG4gICAgaWYgKCFzZWVkKSB7XG4gICAgICAvLyBBbiBleHRlbmRlZCBwcml2YXRlIGtleSBoYXMgYm90aCBhIG5vcm1hbCAyNTYgYml0IHByaXZhdGUga2V5IGFuZCBhIDI1NlxuICAgICAgLy8gYml0IGNoYWluIGNvZGUsIGJvdGggb2Ygd2hpY2ggbXVzdCBiZSByYW5kb20uIDUxMiBiaXRzIGlzIHRoZXJlZm9yZSB0aGVcbiAgICAgIC8vIG1heGltdW0gZW50cm9weSBhbmQgZ2l2ZXMgdXMgbWF4aW11bSBzZWN1cml0eSBhZ2FpbnN0IGNyYWNraW5nLlxuICAgICAgc2VlZCA9IHJhbmRvbUJ5dGVzKDUxMiAvIDgpO1xuICAgIH1cbiAgICBjb25zdCBleHRlbmRlZEtleSA9IGJpcDMyLmZyb21TZWVkKHNlZWQpO1xuICAgIGNvbnN0IHhwdWIgPSBleHRlbmRlZEtleS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHB1YjogeHB1YixcbiAgICAgIHBydjogZXh0ZW5kZWRLZXkudG9CYXNlNTgoKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciBpbnB1dCBpcyB2YWxpZCBwdWJsaWMga2V5IGZvciB0aGUgY29pbi5cbiAgICpcbiAgICogQHBhcmFtIHB1YiAtIHRoZSBwdWIgdG8gYmUgY2hlY2tlZFxuICAgKi9cbiAgaXNWYWxpZFB1YihwdWI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYmlwMzIuZnJvbUJhc2U1OChwdWIpLmlzTmV1dGVyZWQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciBpbnB1dCBpcyB2YWxpZCBzZWVkIGZvciB0aGUgY29pblxuICAgKlxuICAgKiBAcGFyYW0gcHJ2IC0gdGhlIHBydiB0byBiZSBjaGVja2VkXG4gICAqL1xuICBpc1ZhbGlkUHJ2KHBydjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAhYmlwMzIuZnJvbUJhc2U1OChwcnYpLmlzTmV1dGVyZWQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlcyB3aGV0aGVyIGEgbWVtbyBpcyB2YWxpZFxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgLSB0aGUgbWVtbyB0byBiZSBjaGVja2VkXG4gICAqL1xuICBpc1ZhbGlkTWVtbyh7IHZhbHVlIH06IHsgdmFsdWU6IHN0cmluZyB9KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIF8uaXNTdHJpbmcodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA8PSAyNTY7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIGEgbWVtbyBpZCBpcyB2YWxpZFxuICAgKlxuICAgKiBAcGFyYW0gbWVtb0lkIC0gdGhlIG1lbW8gaWQgdG8gYmUgY2hlY2tlZFxuICAgKi9cbiAgaXNWYWxpZE1lbW9JZChtZW1vSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRNZW1vKHsgdmFsdWU6IG1lbW9JZCB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9jZXNzIGFkZHJlc3MgaW50byBhZGRyZXNzIGFuZCBtZW1vIGlkXG4gICAqIEBwYXJhbSBhZGRyZXNzIC0gdGhlIGFkZHJlc3NcbiAgICovXG4gIGdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3M6IHN0cmluZyk6IEFkZHJlc3NEZXRhaWxzIHtcbiAgICBjb25zdCBkZXN0aW5hdGlvbkRldGFpbHMgPSB1cmwucGFyc2UoYWRkcmVzcyk7XG4gICAgY29uc3QgZGVzdGluYXRpb25BZGRyZXNzID0gZGVzdGluYXRpb25EZXRhaWxzLnBhdGhuYW1lO1xuXG4gICAgaWYgKCFkZXN0aW5hdGlvbkFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKGBmYWlsZWQgdG8gcGFyc2UgYWRkcmVzczogJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIC8vIEVPUyBhZGRyZXNzZXMgaGF2ZSB0byBiZSBcImh1bWFuIHJlYWRhYmxlXCIsIHdoaWNoIG1lYW5zIHVwIHRvIDEyIGNoYXJhY3RlcnMgYW5kIG9ubHkgYS16MS01LiwgaS5lLm10b2RhMS5iaXRnb1xuICAgIC8vIHNvdXJjZTogaHR0cHM6Ly9kZXZlbG9wZXJzLmVvcy5pby9lb3Npby1jcHAvZG9jcy9uYW1pbmctY29udmVudGlvbnNcbiAgICBpZiAoIS9eW2EtejEtNS5dKiQvLnRlc3QoZGVzdGluYXRpb25BZGRyZXNzKSB8fCBkZXN0aW5hdGlvbkFkZHJlc3MubGVuZ3RoID4gRW9zLkFERFJFU1NfTEVOR1RIKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAke2FkZHJlc3N9YCk7XG4gICAgfVxuXG4gICAgLy8gYWRkcmVzcyBkb2Vzbid0IGhhdmUgYSBtZW1vIGlkXG4gICAgaWYgKGRlc3RpbmF0aW9uRGV0YWlscy5wYXRobmFtZSA9PT0gYWRkcmVzcykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkcmVzczogYWRkcmVzcyxcbiAgICAgICAgbWVtb0lkOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmICghZGVzdGluYXRpb25EZXRhaWxzLnF1ZXJ5KSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgZmFpbGVkIHRvIHBhcnNlIHF1ZXJ5IHN0cmluZzogJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5RGV0YWlscyA9IHF1ZXJ5c3RyaW5nLnBhcnNlKGRlc3RpbmF0aW9uRGV0YWlscy5xdWVyeSk7XG4gICAgaWYgKCFxdWVyeURldGFpbHMubWVtb0lkKSB7XG4gICAgICAvLyBpZiB0aGVyZSBhcmUgbW9yZSBwcm9wZXJ0aWVzLCB0aGUgcXVlcnkgZGV0YWlscyBuZWVkIHRvIGNvbnRhaW4gdGhlIG1lbW9JZCBwcm9wZXJ0eVxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgcHJvcGVydHkgaW4gYWRkcmVzczogJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIGlmIChBcnJheS5pc0FycmF5KHF1ZXJ5RGV0YWlscy5tZW1vSWQpICYmIHF1ZXJ5RGV0YWlscy5tZW1vSWQubGVuZ3RoICE9PSAxKSB7XG4gICAgICAvLyB2YWxpZCBhZGRyZXNzZXMgY2FuIG9ubHkgY29udGFpbiBvbmUgbWVtbyBpZFxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgYWRkcmVzcyAnJHthZGRyZXNzfScsIG11c3QgY29udGFpbiBleGFjdGx5IG9uZSBtZW1vSWRgKTtcbiAgICB9XG5cbiAgICBjb25zdCBbbWVtb0lkXSA9IF8uY2FzdEFycmF5KHF1ZXJ5RGV0YWlscy5tZW1vSWQpO1xuICAgIGlmICghdGhpcy5pc1ZhbGlkTWVtb0lkKG1lbW9JZCkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKGBpbnZhbGlkIGFkZHJlc3M6ICcke2FkZHJlc3N9JywgbWVtb0lkIGlzIG5vdCB2YWxpZGApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBhZGRyZXNzOiBkZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICBtZW1vSWQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgY3VycmVuY3kgYW1vdW50IHJlcHJlc2VudGVkIGluIGJhc2UgdW5pdHMgKHNhdG9zaGksIHdlaSwgYXRvbXMsIGRyb3BzLCBzdHJvb3BzKVxuICAgKiB0byBiaWcgdW5pdHMgKGJ0YywgZXRoLCB4cnAsIHhsbSlcbiAgICovXG4gIGJhc2VVbml0c1RvQmlnVW5pdHMoYmFzZVVuaXRzOiBzdHJpbmcgfCBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IGRpdmlkZW5kID0gdGhpcy5nZXRCYXNlRmFjdG9yKCk7XG4gICAgY29uc3QgYmlnTnVtYmVyID0gbmV3IEJpZ051bWJlcihiYXNlVW5pdHMpLmRpdmlkZWRCeShkaXZpZGVuZCk7XG4gICAgLy8gc2V0IHRoZSBmb3JtYXQgc28gY29tbWFzIGFyZW4ndCBhZGRlZCB0byBsYXJnZSBjb2luIGFtb3VudHNcbiAgICByZXR1cm4gYmlnTnVtYmVyLnRvRm9ybWF0KDQsIG51bGwgYXMgYW55LCB7IGdyb3VwU2VwYXJhdG9yOiAnJywgZGVjaW1hbFNlcGFyYXRvcjogJy4nIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGFuZCByZXR1cm4gYWRkcmVzcyB3aXRoIGFwcGVuZGVkIG1lbW8gaWRcbiAgICpcbiAgICogQHBhcmFtIGFkZHJlc3NcbiAgICogQHBhcmFtIG1lbW9JZFxuICAgKi9cbiAgbm9ybWFsaXplQWRkcmVzcyh7IGFkZHJlc3MsIG1lbW9JZCB9OiBBZGRyZXNzRGV0YWlscyk6IHN0cmluZyB7XG4gICAgaWYgKG1lbW9JZCAmJiB0aGlzLmlzVmFsaWRNZW1vSWQobWVtb0lkKSkge1xuICAgICAgcmV0dXJuIGAke2FkZHJlc3N9P21lbW9JZD0ke21lbW9JZH1gO1xuICAgIH1cbiAgICByZXR1cm4gYWRkcmVzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHVibGljIGtleSBmb3IgdGhlIGNvaW5cbiAgICpcbiAgICogQHBhcmFtIGFkZHJlc3MgLSB0aGUgYWRkcmVzcyB0byBiZSBjaGVja2VkXG4gICAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYWRkcmVzc0RldGFpbHMgPSB0aGlzLmdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3MpO1xuICAgICAgcmV0dXJuIGFkZHJlc3MgPT09IHRoaXMubm9ybWFsaXplQWRkcmVzcyhhZGRyZXNzRGV0YWlscyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gYWRkcmVzcyAtIHRoZSBhZGRyZXNzIHRvIHZlcmlmeVxuICAgKiBAcGFyYW0gcm9vdEFkZHJlc3MgLSB0aGUgd2FsbGV0J3Mgcm9vdCBhZGRyZXNzXG4gICAqIEByZXR1cm4gdHJ1ZSBpZmYgYWRkcmVzcyBpcyBhIHdhbGxldCBhZGRyZXNzIChiYXNlZCBvbiByb290QWRkcmVzcylcbiAgICovXG4gIGlzV2FsbGV0QWRkcmVzcyh7IGFkZHJlc3MsIHJvb3RBZGRyZXNzIH06IFZlcmlmeUFkZHJlc3NPcHRpb25zKTogYm9vbGVhbiB7XG4gICAgaWYgKCFyb290QWRkcmVzcyB8fCAhXy5pc1N0cmluZyhyb290QWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcm9vdEFkZHJlc3MnKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKGBpbnZhbGlkIGFkZHJlc3M6ICR7YWRkcmVzc31gKTtcbiAgICB9XG5cbiAgICBjb25zdCBhZGRyZXNzRGV0YWlscyA9IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMoYWRkcmVzcyk7XG4gICAgY29uc3Qgcm9vdEFkZHJlc3NEZXRhaWxzID0gdGhpcy5nZXRBZGRyZXNzRGV0YWlscyhyb290QWRkcmVzcyk7XG5cbiAgICBpZiAoIWFkZHJlc3NEZXRhaWxzIHx8ICFyb290QWRkcmVzc0RldGFpbHMpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoYWRkcmVzc0RldGFpbHMuYWRkcmVzcyAhPT0gcm9vdEFkZHJlc3NEZXRhaWxzLmFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yKFxuICAgICAgICBgYWRkcmVzcyB2YWxpZGF0aW9uIGZhaWx1cmU6ICR7YWRkcmVzc0RldGFpbHMuYWRkcmVzc30gdnMgJHtyb290QWRkcmVzc0RldGFpbHMuYWRkcmVzc31gXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2VtYmxlIGtleWNoYWluIGFuZCBoYWxmLXNpZ24gcHJlYnVpbHQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcGFyYW0gcGFyYW1zLnR4UHJlYnVpbGQge09iamVjdH0gcHJlYnVpbGQgb2JqZWN0IHJldHVybmVkIGJ5IHBsYXRmb3JtXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2IHtTdHJpbmd9IHVzZXIgcHJ2XG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEVvc1NpZ25lZFRyYW5zYWN0aW9uPn1cbiAgICovXG4gIGFzeW5jIHNpZ25UcmFuc2FjdGlvbihwYXJhbXM6IEVvc1NpZ25UcmFuc2FjdGlvblBhcmFtcyk6IFByb21pc2U8RW9zU2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCBwcnY6IHN0cmluZyA9IHBhcmFtcy5wcnY7XG4gICAgY29uc3QgdHhIZXg6IHN0cmluZyA9IHBhcmFtcy50eFByZWJ1aWxkLnR4SGV4O1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBFb3NUeCA9IHBhcmFtcy50eFByZWJ1aWxkLnRyYW5zYWN0aW9uO1xuXG4gICAgY29uc3Qgc2lnbkJ1ZmZlcjogQnVmZmVyID0gQnVmZmVyLmZyb20odHhIZXgsICdoZXgnKTtcbiAgICBjb25zdCBwcml2YXRlS2V5QnVmZmVyID0gYmlwMzIuZnJvbUJhc2U1OChwcnYpLnByaXZhdGVLZXk7XG4gICAgaWYgKCFwcml2YXRlS2V5QnVmZmVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIHByaXZhdGVLZXknKTtcbiAgICB9XG4gICAgY29uc3Qgc2lnbmF0dXJlOiBzdHJpbmcgPSBlY2MuU2lnbmF0dXJlLnNpZ24oc2lnbkJ1ZmZlciwgcHJpdmF0ZUtleUJ1ZmZlcikudG9TdHJpbmcoKTtcblxuICAgIHRyYW5zYWN0aW9uLnNpZ25hdHVyZXMucHVzaChzaWduYXR1cmUpO1xuXG4gICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICB0cmFuc2FjdGlvbixcbiAgICAgIHR4SGV4LFxuICAgICAgcmVjaXBpZW50czogcGFyYW1zLnR4UHJlYnVpbGQucmVjaXBpZW50cyxcbiAgICAgIGhlYWRlcnM6IHBhcmFtcy50eFByZWJ1aWxkLmhlYWRlcnMsXG4gICAgICB0eGlkOiBwYXJhbXMudHhQcmVidWlsZC50eGlkLFxuICAgIH07XG4gICAgcmV0dXJuIHsgaGFsZlNpZ25lZDogdHhQYXJhbXMgfTtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVTdGFrZUFjdGlvbkRhdGEoc3Rha2VBY3Rpb25EYXRhOiBTdGFrZUFjdGlvbkRhdGEpOiBhbnkge1xuICAgIGlmIChzdGFrZUFjdGlvbkRhdGEuZnJvbSAhPT0gc3Rha2VBY3Rpb25EYXRhLnJlY2VpdmVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHN0YWtlciAoJHtzdGFrZUFjdGlvbkRhdGEuZnJvbX0pIGFuZCByZWNlaXZlciAoJHtzdGFrZUFjdGlvbkRhdGEucmVjZWl2ZXJ9KSBtdXN0IGJlIHRoZSBzYW1lYCk7XG4gICAgfVxuXG4gICAgaWYgKHN0YWtlQWN0aW9uRGF0YS50cmFuc2ZlciAhPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgdHJhbnNmZXIgZnVuZHMgYXMgcGFydCBvZiBkZWxlZ2F0ZWJ3IGFjdGlvbicpO1xuICAgIH1cblxuICAgIC8vIHN0YWtlX2NwdV9xdWFudGl0eSBpcyB1c2VkIGFzIHRoZSBhbW91bnQgYmVjYXVzZSB0aGUgQml0R28gcGxhdGZvcm0gb25seSBzdGFrZXMgY3B1IGZvciB2b3RpbmcgdHJhbnNhY3Rpb25zXG4gICAgcmV0dXJuIHtcbiAgICAgIGFkZHJlc3M6IHN0YWtlQWN0aW9uRGF0YS5mcm9tLFxuICAgICAgYW1vdW50OiB0aGlzLmJpZ1VuaXRzVG9CYXNlVW5pdHMoc3Rha2VBY3Rpb25EYXRhLnN0YWtlX2NwdV9xdWFudGl0eS5zcGxpdCgnICcpWzBdKSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVVuc3Rha2VBY3Rpb25EYXRhKHVuc3Rha2VBY3Rpb25EYXRhOiBVbnN0YWtlQWN0aW9uRGF0YSk6IGFueSB7XG4gICAgaWYgKHVuc3Rha2VBY3Rpb25EYXRhLmZyb20gIT09IHVuc3Rha2VBY3Rpb25EYXRhLnJlY2VpdmVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGB1bnN0YWtlciAoJHt1bnN0YWtlQWN0aW9uRGF0YS5mcm9tfSkgYW5kIHJlY2VpdmVyICgke3Vuc3Rha2VBY3Rpb25EYXRhLnJlY2VpdmVyfSkgbXVzdCBiZSB0aGUgc2FtZWBcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGNwdUFtb3VudCA9IG5ldyBCaWdOdW1iZXIodW5zdGFrZUFjdGlvbkRhdGEudW5zdGFrZV9jcHVfcXVhbnRpdHkuc3BsaXQoJyAnKVswXSk7XG4gICAgY29uc3QgbmV0QW1vdW50ID0gbmV3IEJpZ051bWJlcih1bnN0YWtlQWN0aW9uRGF0YS51bnN0YWtlX25ldF9xdWFudGl0eS5zcGxpdCgnICcpWzBdKTtcbiAgICBjb25zdCB0b3RhbEFtb3VudCA9IGNwdUFtb3VudC5wbHVzKG5ldEFtb3VudCkudG9OdW1iZXIoKTtcblxuICAgIHJldHVybiB7XG4gICAgICBhZGRyZXNzOiB1bnN0YWtlQWN0aW9uRGF0YS5yZWNlaXZlcixcbiAgICAgIGFtb3VudDogdGhpcy5iaWdVbml0c1RvQmFzZVVuaXRzKHRvdGFsQW1vdW50KSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgdmFsaWRhdGVWb3RlQWN0aW9uRGF0YSh2b3RlQWN0aW9uRGF0YTogVm90ZUFjdGlvbkRhdGEpIHtcbiAgICBjb25zdCBwcm94eUlzRW1wdHkgPSBfLmlzRW1wdHkodm90ZUFjdGlvbkRhdGEucHJveHkpO1xuICAgIGNvbnN0IHByb2R1Y2Vyc0lzRW1wdHkgPSBfLmlzRW1wdHkodm90ZUFjdGlvbkRhdGEucHJvZHVjZXJzKTtcbiAgICBpZiAoKHByb3h5SXNFbXB0eSAmJiBwcm9kdWNlcnNJc0VtcHR5KSB8fCAoIXByb3h5SXNFbXB0eSAmJiAhcHJvZHVjZXJzSXNFbXB0eSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndm90aW5nIHRyYW5zYWN0aW9ucyBtdXN0IHNwZWNpZnkgZWl0aGVyIHByb2R1Y2VycyBvciBwcm94eSB0byB2b3RlIGZvcicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBhZGRyZXNzOiB2b3RlQWN0aW9uRGF0YS52b3RlcixcbiAgICAgIHByb3h5OiB2b3RlQWN0aW9uRGF0YS5wcm94eSxcbiAgICAgIHByb2R1Y2Vyczogdm90ZUFjdGlvbkRhdGEucHJvZHVjZXJzLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBjcmVhdGVUcmFuc2FjdGlvbklkSGV4KHNlcmlhbGl6ZWRUcmFuc2FjdGlvbkJ1ZmZlcjogQnVmZmVyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHNlcmlhbGl6ZWRUcmFuc2FjdGlvbkJ1ZmZlcikuZGlnZXN0KCkudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlc2VyaWFsaXplIGEgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBoZWFkZXJzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGRlc2VyaWFsaXplVHJhbnNhY3Rpb24oe1xuICAgIHRyYW5zYWN0aW9uLFxuICAgIGhlYWRlcnMsXG4gIH06IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPERlc2VyaWFsaXplZEVvc1RyYW5zYWN0aW9uPiB7XG4gICAgLy8gY3JlYXRlIGFuIGVvc2pzIEFQSSBjbGllbnRcbiAgICBjb25zdCBhcGkgPSBuZXcgQXBpKHtcbiAgICAgIGFiaVByb3ZpZGVyOiBuZXcgT2ZmbGluZUFiaVByb3ZpZGVyKCksXG4gICAgICBycGM6IG5ldyBOb29wSnNvblJwYygpLFxuICAgICAgc2lnbmF0dXJlUHJvdmlkZXI6IG5ldyBOb29wU2lnbmF0dXJlUHJvdmlkZXIoKSxcbiAgICAgIGNoYWluSWQ6IHRoaXMuZ2V0Q2hhaW5JZCgpLFxuICAgICAgLy8gVXNlIGEgY3VzdG9tIFRleHREZWNvZGVyIGFzIHRoZSBnbG9iYWwgVGV4dERlY29kZXIgbGVhZHMgdG8gY3Jhc2hlcyBpbiBPVkMgLyBFbGVjdHJvbi5cbiAgICAgIHRleHREZWNvZGVyOiBuZXcgU3RyaW5nVGV4dERlY29kZXIoKSxcbiAgICAgIHRleHRFbmNvZGVyOiBuZXcgVGV4dEVuY29kZXIoKSxcbiAgICB9KTtcblxuICAgIC8vIHR5cGUgZ3VhcmRzXG4gICAgY29uc3QgaXNUcmFuc2ZlckFjdGlvbkRhdGEgPSAodHhBY3Rpb25EYXRhOiBhbnkpOiB0eEFjdGlvbkRhdGEgaXMgVHJhbnNmZXJBY3Rpb25EYXRhID0+IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgICh0eEFjdGlvbkRhdGEgYXMgVHJhbnNmZXJBY3Rpb25EYXRhKS5mcm9tICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgKHR4QWN0aW9uRGF0YSBhcyBUcmFuc2ZlckFjdGlvbkRhdGEpLnRvICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgKHR4QWN0aW9uRGF0YSBhcyBUcmFuc2ZlckFjdGlvbkRhdGEpLnF1YW50aXR5ICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCBpc1N0YWtlQWN0aW9uRGF0YSA9ICh0eEFjdGlvbkRhdGE6IGFueSk6IHR4QWN0aW9uRGF0YSBpcyBTdGFrZUFjdGlvbkRhdGEgPT4ge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgKHR4QWN0aW9uRGF0YSBhcyBTdGFrZUFjdGlvbkRhdGEpLmZyb20gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodHhBY3Rpb25EYXRhIGFzIFN0YWtlQWN0aW9uRGF0YSkucmVjZWl2ZXIgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodHhBY3Rpb25EYXRhIGFzIFN0YWtlQWN0aW9uRGF0YSkudHJhbnNmZXIgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodHhBY3Rpb25EYXRhIGFzIFN0YWtlQWN0aW9uRGF0YSkuc3Rha2VfY3B1X3F1YW50aXR5ICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgfTtcbiAgICBjb25zdCBpc1Vuc3Rha2VBY3Rpb25EYXRhID0gKHR4QWN0aW9uRGF0YTogYW55KTogdHhBY3Rpb25EYXRhIGlzIFVuc3Rha2VBY3Rpb25EYXRhID0+IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgICh0eEFjdGlvbkRhdGEgYXMgVW5zdGFrZUFjdGlvbkRhdGEpLmZyb20gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAodHhBY3Rpb25EYXRhIGFzIFVuc3Rha2VBY3Rpb25EYXRhKS5yZWNlaXZlciAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICh0eEFjdGlvbkRhdGEgYXMgVW5zdGFrZUFjdGlvbkRhdGEpLnVuc3Rha2VfY3B1X3F1YW50aXR5ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgKHR4QWN0aW9uRGF0YSBhcyBVbnN0YWtlQWN0aW9uRGF0YSkudW5zdGFrZV9uZXRfcXVhbnRpdHkgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICB9O1xuICAgIGNvbnN0IGlzVm90ZUFjdGlvbkRhdGEgPSAodHhBY3Rpb25EYXRhOiBhbnkpOiB0eEFjdGlvbkRhdGEgaXMgVm90ZUFjdGlvbkRhdGEgPT4ge1xuICAgICAgcmV0dXJuICh0eEFjdGlvbkRhdGEgYXMgVm90ZUFjdGlvbkRhdGEpLnZvdGVyICE9PSB1bmRlZmluZWQ7XG4gICAgfTtcbiAgICBjb25zdCBpc1JlZnVuZEFjdGlvbkRhdGEgPSAodHhBY3Rpb25EYXRhOiBhbnkpOiB0eEFjdGlvbkRhdGEgaXMgUmVmdW5kQWN0aW9uRGF0YSA9PiB7XG4gICAgICByZXR1cm4gKHR4QWN0aW9uRGF0YSBhcyBSZWZ1bmRBY3Rpb25EYXRhKS5vd25lciAhPT0gdW5kZWZpbmVkO1xuICAgIH07XG5cbiAgICAvLyBkZXNlcmlhbGl6ZVRyYW5zYWN0aW9uXG4gICAgY29uc3Qgc2VyaWFsaXplZFR4QnVmZmVyID0gQnVmZmVyLmZyb20odHJhbnNhY3Rpb24ucGFja2VkX3RyeCwgJ2hleCcpO1xuICAgIGNvbnN0IGRlc2VyaWFsaXplZFR4SnNvbkZyb21QYWNrZWRUcnggPSBhd2FpdCBhcGkuZGVzZXJpYWxpemVUcmFuc2FjdGlvbldpdGhBY3Rpb25zKHNlcmlhbGl6ZWRUeEJ1ZmZlcik7XG5cbiAgICBpZiAoIWRlc2VyaWFsaXplZFR4SnNvbkZyb21QYWNrZWRUcngpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHByb2Nlc3MgdHJhbnNhY3Rpb24gZnJvbSB0eEhleCcpO1xuICAgIH1cbiAgICBjb25zdCB0eDogRGVzZXJpYWxpemVkRW9zVHJhbnNhY3Rpb24gPSBkZXNlcmlhbGl6ZWRUeEpzb25Gcm9tUGFja2VkVHJ4O1xuXG4gICAgLy8gdmFsaWRhdGUgY29udGV4dCBmcmVlIGFjdGlvbnNcbiAgICBpZiAodHguY29udGV4dF9mcmVlX2FjdGlvbnMubGVuZ3RoICE9PSAwKSB7XG4gICAgICBpZiAodHguY29udGV4dF9mcmVlX2FjdGlvbnMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbnVtYmVyIG9mIGNvbnRleHQgZnJlZSBhY3Rpb25zIG11c3QgYmUgMScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgICFfLmlzRXF1YWwoXy5waWNrKHR4LmNvbnRleHRfZnJlZV9hY3Rpb25zWzBdLCBbJ2FjY291bnQnLCAnYXV0aG9yaXphdGlvbicsICduYW1lJ10pLCB7XG4gICAgICAgICAgYWNjb3VudDogJ2Vvc2lvLm51bGwnLFxuICAgICAgICAgIGF1dGhvcml6YXRpb246IFtdLFxuICAgICAgICAgIG5hbWU6ICdub25jZScsXG4gICAgICAgIH0pIHx8XG4gICAgICAgIF8uaXNFbXB0eSh0eC5jb250ZXh0X2ZyZWVfYWN0aW9uc1swXS5kYXRhKVxuICAgICAgKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIGNvbnRleHQgZnJlZSBhY3Rpb24gaXMgaW52YWxpZCcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE9ubHkgc3VwcG9ydCB0cmFuc2FjdGlvbnMgd2l0aCBvbmUgKHRyYW5zZmVyIHwgdm90ZXByb2R1Y2VyKSBvciB0d28gKGRlbGVnYXRlYncgJiB2b3RlcHJvZHVjZXIpIGFjdGlvbnNcbiAgICBpZiAodHguYWN0aW9ucy5sZW5ndGggIT09IDEgJiYgdHguYWN0aW9ucy5sZW5ndGggIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBudW1iZXIgb2YgYWN0aW9uczogJHt0eC5hY3Rpb25zLmxlbmd0aH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCB0eEFjdGlvbiA9IHR4LmFjdGlvbnNbMF07XG4gICAgaWYgKCF0eEFjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHRyYW5zYWN0aW9uIGFjdGlvbicpO1xuICAgIH1cbiAgICBpZiAodHhBY3Rpb24ubmFtZSA9PT0gJ3RyYW5zZmVyJykge1xuICAgICAgLy8gVHJhbnNmZXJzIHNob3VsZCBvbmx5IGhhdmUgMSBhY3Rpb25cbiAgICAgIGlmICh0eC5hY3Rpb25zLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHRyYW5zZmVycyBzaG91bGQgb25seSBoYXZlIDEgYWN0aW9uOiAke3R4LmFjdGlvbnMubGVuZ3RofSBnaXZlbmApO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzVHJhbnNmZXJBY3Rpb25EYXRhKHR4QWN0aW9uLmRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBvciBpbmNvbXBsZXRlIHRyYW5zZmVyIGFjdGlvbiBkYXRhJyk7XG4gICAgICB9XG4gICAgICBjb25zdCB0cmFuc2ZlckFjdGlvbkRhdGEgPSB0eEFjdGlvbi5kYXRhO1xuXG4gICAgICB0eC5hZGRyZXNzID0gdHJhbnNmZXJBY3Rpb25EYXRhLnRvO1xuICAgICAgdHguYW1vdW50ID0gdGhpcy5iaWdVbml0c1RvQmFzZVVuaXRzKHRyYW5zZmVyQWN0aW9uRGF0YS5xdWFudGl0eS5zcGxpdCgnICcpWzBdKTtcbiAgICAgIHR4Lm1lbW8gPSB0cmFuc2ZlckFjdGlvbkRhdGEubWVtbztcbiAgICB9IGVsc2UgaWYgKHR4QWN0aW9uLm5hbWUgPT09ICdkZWxlZ2F0ZWJ3Jykge1xuICAgICAgLy8gVGhlIGRlbGVnYXRlYncgYWN0aW9uIHNob3VsZCBvbmx5IGJlIHBhcnQgb2Ygdm90aW5nIHRyYW5zYWN0aW9uc1xuICAgICAgaWYgKHR4LmFjdGlvbnMubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgc3Rha2luZyB0cmFuc2FjdGlvbnMgdGhhdCBpbmNsdWRlIHRoZSBkZWxlZ2F0ZWJ3IGFjdGlvbiBzaG91bGQgaGF2ZSAyIGFjdGlvbnM6ICR7dHguYWN0aW9ucy5sZW5ndGh9IGdpdmVuYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0eEFjdGlvbjIgPSB0eC5hY3Rpb25zWzFdO1xuICAgICAgaWYgKHR4QWN0aW9uMi5uYW1lICE9PSAndm90ZXByb2R1Y2VyJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgc3Rha2luZyB0cmFuc2FjdGlvbiBhY3Rpb246ICR7dHhBY3Rpb24yLm5hbWV9LCBleHBlY3Rpbmc6IHZvdGVwcm9kdWNlcmApO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzU3Rha2VBY3Rpb25EYXRhKHR4QWN0aW9uLmRhdGEpIHx8ICFpc1ZvdGVBY3Rpb25EYXRhKHR4QWN0aW9uMi5kYXRhKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgb3IgaW5jb21wbGV0ZSBzdGFrZSBvciB2b3RlIGFjdGlvbiBkYXRhJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzdGFrZUFjdGlvbkRhdGEgPSB0eEFjdGlvbi5kYXRhO1xuICAgICAgY29uc3Qgdm90ZUFjdGlvbkRhdGEgPSB0eEFjdGlvbjIuZGF0YTtcblxuICAgICAgY29uc3QgZGVzZXJpYWxpemVkU3Rha2VBY3Rpb24gPSB0aGlzLnZhbGlkYXRlU3Rha2VBY3Rpb25EYXRhKHN0YWtlQWN0aW9uRGF0YSk7XG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWRWb3RlQWN0aW9uID0gRW9zLnZhbGlkYXRlVm90ZUFjdGlvbkRhdGEodm90ZUFjdGlvbkRhdGEpO1xuICAgICAgaWYgKGRlc2VyaWFsaXplZFN0YWtlQWN0aW9uLmFkZHJlc3MgIT09IGRlc2VyaWFsaXplZFZvdGVBY3Rpb24uYWRkcmVzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYHN0YWtlciAoJHtkZXNlcmlhbGl6ZWRTdGFrZUFjdGlvbi5hZGRyZXNzfSkgYW5kIHZvdGVyICgke2Rlc2VyaWFsaXplZFZvdGVBY3Rpb24uYWRkcmVzc30pIG11c3QgYmUgdGhlIHNhbWVgXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHR4LmFtb3VudCA9IGRlc2VyaWFsaXplZFN0YWtlQWN0aW9uLmFtb3VudDtcbiAgICAgIHR4LnByb3h5ID0gZGVzZXJpYWxpemVkVm90ZUFjdGlvbi5wcm94eTtcbiAgICAgIHR4LnByb2R1Y2VycyA9IGRlc2VyaWFsaXplZFZvdGVBY3Rpb24ucHJvZHVjZXJzO1xuICAgIH0gZWxzZSBpZiAodHhBY3Rpb24ubmFtZSA9PT0gJ3ZvdGVwcm9kdWNlcicpIHtcbiAgICAgIGlmICh0eC5hY3Rpb25zLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd2b3RpbmcgdHJhbnNhY3Rpb25zIHNob3VsZCBub3QgaGF2ZSBtb3JlIHRoYW4gMiBhY3Rpb25zJyk7XG4gICAgICB9XG5cbiAgICAgIGxldCBkZXNlcmlhbGl6ZWRTdGFrZUFjdGlvbjtcbiAgICAgIGlmICh0eC5hY3Rpb25zLmxlbmd0aCA9PT0gMikge1xuICAgICAgICBjb25zdCB0eEFjdGlvbjIgPSB0eC5hY3Rpb25zWzFdO1xuICAgICAgICBpZiAodHhBY3Rpb24yLm5hbWUgIT09ICdkZWxlZ2F0ZWJ3Jykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBzdGFraW5nIHRyYW5zYWN0aW9uIGFjdGlvbjogJHt0eEFjdGlvbjIubmFtZX0sIGV4cGVjdGluZzogZGVsZWdhdGVid2ApO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNTdGFrZUFjdGlvbkRhdGEodHhBY3Rpb24uZGF0YSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgb3IgaW5jb21wbGV0ZSBzdGFrZSBhY3Rpb24gZGF0YScpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YWtlQWN0aW9uRGF0YSA9IHR4QWN0aW9uLmRhdGE7XG4gICAgICAgIGRlc2VyaWFsaXplZFN0YWtlQWN0aW9uID0gdGhpcy52YWxpZGF0ZVN0YWtlQWN0aW9uRGF0YShzdGFrZUFjdGlvbkRhdGEpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWlzVm90ZUFjdGlvbkRhdGEodHhBY3Rpb24uZGF0YSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG9yIGluY29tcGxldGUgdm90ZSBhY3Rpb24gZGF0YScpO1xuICAgICAgfVxuICAgICAgY29uc3Qgdm90ZUFjdGlvbkRhdGEgPSB0eEFjdGlvbi5kYXRhO1xuICAgICAgY29uc3QgZGVzZXJpYWxpemVkVm90ZUFjdGlvbiA9IEVvcy52YWxpZGF0ZVZvdGVBY3Rpb25EYXRhKHZvdGVBY3Rpb25EYXRhKTtcblxuICAgICAgaWYgKCEhZGVzZXJpYWxpemVkU3Rha2VBY3Rpb24gJiYgZGVzZXJpYWxpemVkU3Rha2VBY3Rpb24uYWRkcmVzcyAhPT0gZGVzZXJpYWxpemVkVm90ZUFjdGlvbi5hZGRyZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgc3Rha2VyICgke2Rlc2VyaWFsaXplZFN0YWtlQWN0aW9uLmFkZHJlc3N9KSBhbmQgdm90ZXIgKCR7ZGVzZXJpYWxpemVkVm90ZUFjdGlvbi5hZGRyZXNzfSkgbXVzdCBiZSB0aGUgc2FtZWBcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgdHguYW1vdW50ID0gISFkZXNlcmlhbGl6ZWRTdGFrZUFjdGlvbiA/IGRlc2VyaWFsaXplZFN0YWtlQWN0aW9uLmFtb3VudCA6ICcwJztcbiAgICAgIHR4LnByb3h5ID0gZGVzZXJpYWxpemVkVm90ZUFjdGlvbi5wcm94eTtcbiAgICAgIHR4LnByb2R1Y2VycyA9IGRlc2VyaWFsaXplZFZvdGVBY3Rpb24ucHJvZHVjZXJzO1xuICAgIH0gZWxzZSBpZiAodHhBY3Rpb24ubmFtZSA9PT0gJ3VuZGVsZWdhdGVidycpIHtcbiAgICAgIGlmICh0eC5hY3Rpb25zLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3Rha2Ugc2hvdWxkIG9ubHkgaGF2ZSAxIGFjdGlvbjogJHt0eC5hY3Rpb25zLmxlbmd0aH0gZ2l2ZW5gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc1Vuc3Rha2VBY3Rpb25EYXRhKHR4QWN0aW9uLmRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBvciBpbmNvbXBsZXRlIHVuc3Rha2UgYWN0aW9uIGRhdGEnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVuc3Rha2VBY3Rpb25EYXRhID0gdHhBY3Rpb24uZGF0YTtcbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZFVuc3Rha2VBY3Rpb24gPSB0aGlzLnZhbGlkYXRlVW5zdGFrZUFjdGlvbkRhdGEodW5zdGFrZUFjdGlvbkRhdGEpO1xuXG4gICAgICB0eC5hbW91bnQgPSBkZXNlcmlhbGl6ZWRVbnN0YWtlQWN0aW9uLmFtb3VudDtcbiAgICAgIHR4LmFkZHJlc3MgPSBkZXNlcmlhbGl6ZWRVbnN0YWtlQWN0aW9uLmFkZHJlc3M7XG4gICAgfSBlbHNlIGlmICh0eEFjdGlvbi5uYW1lID09PSAncmVmdW5kJykge1xuICAgICAgaWYgKHR4LmFjdGlvbnMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgcmVmdW5kIHNob3VsZCBvbmx5IGhhdmUgMSBhY3Rpb246ICR7dHguYWN0aW9ucy5sZW5ndGh9IGdpdmVuYCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghaXNSZWZ1bmRBY3Rpb25EYXRhKHR4QWN0aW9uLmRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBvciBpbmNvbXBsZXRlIHJlZnVuZCBhY3Rpb24gZGF0YScpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZWZ1bmRBY3Rpb25EYXRhID0gdHhBY3Rpb24uZGF0YTtcbiAgICAgIHR4LmFkZHJlc3MgPSByZWZ1bmRBY3Rpb25EYXRhLm93bmVyO1xuICAgICAgdHguYW1vdW50ID0gJzAnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgYWN0aW9uOiAke3R4QWN0aW9uLm5hbWV9YCk7XG4gICAgfVxuXG4gICAgLy8gR2V0IHRoZSB0eCBpZCBpZiB0eCBoZWFkZXJzIHdlcmUgcHJvdmlkZWRcbiAgICBpZiAoaGVhZGVycykge1xuICAgICAgbGV0IHJlYnVpbHRUcmFuc2FjdGlvbjtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIHJlbW92ZSBaIGF0IHRoZSBlbmRcbiAgICAgICAgaWYgKChoZWFkZXJzLmV4cGlyYXRpb24gYXMgc3RyaW5nKS5lbmRzV2l0aCgnWicpKSB7XG4gICAgICAgICAgaGVhZGVycy5leHBpcmF0aW9uID0gKGhlYWRlcnMuZXhwaXJhdGlvbiBhcyBzdHJpbmcpLnNsaWNlKDAsIC0xKTtcbiAgICAgICAgfVxuICAgICAgICByZWJ1aWx0VHJhbnNhY3Rpb24gPSBhd2FpdCBhcGkudHJhbnNhY3QoeyAuLi50eCwgLi4uaGVhZGVycyB9LCB7IHNpZ246IGZhbHNlLCBicm9hZGNhc3Q6IGZhbHNlIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ0NvdWxkIG5vdCBidWlsZCB0cmFuc2FjdGlvbiB0byBnZXQgdHJhbnNhY3Rpb25faWQuIFBsZWFzZSBjaGVjayB0cmFuc2FjdGlvbiBvciBoZWFkZXJzIGZvcm1hdC4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHR4LnRyYW5zYWN0aW9uX2lkID0gRW9zLmNyZWF0ZVRyYW5zYWN0aW9uSWRIZXgoKHJlYnVpbHRUcmFuc2FjdGlvbiBhcyBhbnkpLnNlcmlhbGl6ZWRUcmFuc2FjdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHR4O1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGxhaW4vcGFyc2UgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHBhcmFtcyAtIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnNcbiAgICovXG4gIGFzeW5jIGV4cGxhaW5UcmFuc2FjdGlvbihwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFRyYW5zYWN0aW9uRXhwbGFuYXRpb24+IHtcbiAgICBsZXQgdHJhbnNhY3Rpb247XG4gICAgdHJ5IHtcbiAgICAgIHRyYW5zYWN0aW9uID0gYXdhaXQgdGhpcy5kZXNlcmlhbGl6ZVRyYW5zYWN0aW9uKHBhcmFtcyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIEVPUyB0cmFuc2FjdGlvbiBvciBoZWFkZXJzOiAnICsgZS50b1N0cmluZygpKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGRpc3BsYXlPcmRlcjogW1xuICAgICAgICAnaWQnLFxuICAgICAgICAnb3V0cHV0QW1vdW50JyxcbiAgICAgICAgJ2NoYW5nZUFtb3VudCcsXG4gICAgICAgICdvdXRwdXRzJyxcbiAgICAgICAgJ2NoYW5nZU91dHB1dHMnLFxuICAgICAgICAnZmVlJyxcbiAgICAgICAgJ21lbW8nLFxuICAgICAgICAncHJveHknLFxuICAgICAgICAncHJvZHVjZXJzJyxcbiAgICAgIF0sXG4gICAgICBpZDogdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25faWQsXG4gICAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICAgIG91dHB1dEFtb3VudDogdHJhbnNhY3Rpb24uYW1vdW50LFxuICAgICAgY2hhbmdlQW1vdW50OiAwLFxuICAgICAgb3V0cHV0czogISF0cmFuc2FjdGlvbi5hZGRyZXNzID8gW3sgYWRkcmVzczogdHJhbnNhY3Rpb24uYWRkcmVzcywgYW1vdW50OiB0cmFuc2FjdGlvbi5hbW91bnQgfV0gOiBbXSxcbiAgICAgIGZlZToge30sXG4gICAgICBtZW1vOiB0cmFuc2FjdGlvbi5tZW1vLFxuICAgICAgcHJveHk6IHRyYW5zYWN0aW9uLnByb3h5LFxuICAgICAgcHJvZHVjZXJzOiB0cmFuc2FjdGlvbi5wcm9kdWNlcnMsXG4gICAgfSBhcyBhbnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWRcbiAgICovXG4gIGluaXRpYXRlUmVjb3ZlcnkocGFyYW1zOiBSZWNvdmVyeU9wdGlvbnMpOiBuZXZlciB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdkZXByZWNhdGVkIG1ldGhvZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgYSByZXF1ZXN0IHRvIG9uZSBvZiB0aGUgcHVibGljIEVPUyBub2RlcyBhdmFpbGFibGVcbiAgICogQHBhcmFtIHBhcmFtcy5lbmRwb2ludFxuICAgKiBAcGFyYW0gcGFyYW1zLnBheWxvYWRcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXREYXRhRnJvbU5vZGUocGFyYW1zOiB7XG4gICAgZW5kcG9pbnQ6IHN0cmluZztcbiAgICBwYXlsb2FkPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH0pOiBQcm9taXNlPHJlcXVlc3QuUmVzcG9uc2U+IHtcbiAgICBjb25zdCBub2RlVXJscyA9IHRoaXMuZ2V0UHVibGljTm9kZVVybHMoKTtcbiAgICBmb3IgKGNvbnN0IG5vZGVVcmwgb2Ygbm9kZVVybHMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCByZXF1ZXN0LnBvc3Qobm9kZVVybCArIHBhcmFtcy5lbmRwb2ludCkuc2VuZChwYXJhbXMucGF5bG9hZCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIGxldCdzIGhvcGUgYW5vdGhlciBjYWxsIHN1Y2NlZWRzXG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGNhbGwgZW5kcG9pbnQ6ICR7cGFyYW1zLmVuZHBvaW50fSBmcm9tIG5vZGVzOiAke18uam9pbihub2RlVXJscywgJywgJyl9YCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IEVPUyBjaGFpbiBpbmZvIGZyb20gYSBwdWJsaWMgbm9kZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGdldENoYWluSW5mb0Zyb21Ob2RlKCk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldERhdGFGcm9tTm9kZSh7IGVuZHBvaW50OiAnL3YxL2NoYWluL2dldF9pbmZvJyB9KTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZldGNoIGNoYWluIGluZm8nKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGRhdGEgc3BlY2lmaWMgdG8gYW4gYWNjb3VudCBmcm9tIGEgcHVibGljIG5vZGVcbiAgICogQHBhcmFtIGFkZHJlc3NcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50RnJvbU5vZGUoeyBhZGRyZXNzIH06IHsgYWRkcmVzczogc3RyaW5nIH0pOiBQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXREYXRhRnJvbU5vZGUoe1xuICAgICAgZW5kcG9pbnQ6ICcvdjEvY2hhaW4vZ2V0X2FjY291bnQnLFxuICAgICAgcGF5bG9hZDogeyBhY2NvdW50X25hbWU6IGFkZHJlc3MgfSxcbiAgICB9KTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQWNjb3VudCBub3QgZm91bmQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGJsb2NrIGRhdGEgZnJvbSBhIHB1YmxpYyBub2RlIHVzaW5nIGl0cyBibG9jayBudW1iZXIgb3IgYmxvY2sgaWRcbiAgICogQHBhcmFtIGJsb2NrTnVtT3JJZFxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEJsb2NrRnJvbU5vZGUoeyBibG9ja051bU9ySWQgfTogeyBibG9ja051bU9ySWQ6IHN0cmluZyB9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0RGF0YUZyb21Ob2RlKHtcbiAgICAgIGVuZHBvaW50OiAnL3YxL2NoYWluL2dldF9ibG9jaycsXG4gICAgICBwYXlsb2FkOiB7IGJsb2NrX251bV9vcl9pZDogYmxvY2tOdW1PcklkIH0sXG4gICAgfSk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Jsb2NrIG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzcG9uc2UuYm9keTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgaGVhZGVycyBmb3IgYW4gRU9TIHR4IGZyb20gYSBwdWJsaWMgbm9kZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGdldFRyYW5zYWN0aW9uSGVhZGVyc0Zyb21Ob2RlKCk6IFByb21pc2U8YW55PiB7XG4gICAgY29uc3QgY2hhaW5JbmZvID0gYXdhaXQgdGhpcy5nZXRDaGFpbkluZm9Gcm9tTm9kZSgpO1xuICAgIGNvbnN0IGhlYWRCbG9ja0luZm9SZXN1bHQgPSBhd2FpdCB0aGlzLmdldEJsb2NrRnJvbU5vZGUoeyBibG9ja051bU9ySWQ6IGNoYWluSW5mby5oZWFkX2Jsb2NrX251bSB9KTtcbiAgICBjb25zdCBleHBpcmVTZWNvbmRzID0gMjg4MDA7IC8vIG1heGltdW0gdHggZXhwaXJlIHRpbWUgb2YgOGhcbiAgICBjb25zdCBjaGFpbkRhdGUgPSBuZXcgRGF0ZShjaGFpbkluZm8uaGVhZF9ibG9ja190aW1lICsgJ1onKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgZXhwaXJhdGlvbkRhdGUgPSBuZXcgRGF0ZShjaGFpbkRhdGUgKyBleHBpcmVTZWNvbmRzICogMTAwMCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZXhwaXJhdGlvbjogZXhwaXJhdGlvbkRhdGUudG9JU09TdHJpbmcoKSxcbiAgICAgIHJlZl9ibG9ja19udW06IGNoYWluSW5mby5oZWFkX2Jsb2NrX251bSAmIDB4ZmZmZixcbiAgICAgIHJlZl9ibG9ja19wcmVmaXg6IGhlYWRCbG9ja0luZm9SZXN1bHQucmVmX2Jsb2NrX3ByZWZpeCxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFRyYW5zZmVyQWN0aW9uKHsgcmVjaXBpZW50LCBzZW5kZXIsIGFtb3VudCwgbWVtbyB9OiBhbnkpOiBFb3NUcmFuc2FjdGlvbkFjdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY291bnQ6ICdlb3Npby50b2tlbicsXG4gICAgICBuYW1lOiAndHJhbnNmZXInLFxuICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICB7XG4gICAgICAgICAgYWN0b3I6IHNlbmRlcixcbiAgICAgICAgICBwZXJtaXNzaW9uOiAnYWN0aXZlJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkYXRhOiB7XG4gICAgICAgIGZyb206IHNlbmRlcixcbiAgICAgICAgdG86IHJlY2lwaWVudCxcbiAgICAgICAgcXVhbnRpdHk6IGAke3RoaXMuYmFzZVVuaXRzVG9CaWdVbml0cyhhbW91bnQpfSBFT1NgLFxuICAgICAgICBtZW1vOiAhXy5pc05pbChtZW1vKSA/IG1lbW8gOiAnJywgLy8gTWVtbyBtdXN0IGJlIGRlZmluZWQsIHNldCBpdCB0byBlbXB0eSBzdHJpbmcgaWYgaXQgaXMgbm90XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2lnbiBhIHRyYW5zYWN0aW9uIHdpdGggYSBrZXlcbiAgICogQHBhcmFtIHNpZ25hYmxlVHhcbiAgICogQHBhcmFtIHNpZ25pbmdLZXlcbiAgICovXG4gIHNpZ25UeChzaWduYWJsZVR4OiBzdHJpbmcsIHNpZ25pbmdLZXk6IGJpcDMyLkJJUDMySW50ZXJmYWNlKTogc3RyaW5nIHtcbiAgICBjb25zdCBzaWduQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVUeCwgJ2hleCcpO1xuICAgIGNvbnN0IHByaXZhdGVLZXlCdWZmZXIgPSBzaWduaW5nS2V5LnByaXZhdGVLZXk7XG4gICAgcmV0dXJuIGVjYy5TaWduYXR1cmUuc2lnbihzaWduQnVmZmVyLCBwcml2YXRlS2V5QnVmZmVyKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGZ1bmRzIHJlY292ZXJ5IHRyYW5zYWN0aW9uIHdpdGhvdXQgQml0R29cbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgcmVjb3ZlcihwYXJhbXM6IFJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8UmVjb3ZlcnlUcmFuc2FjdGlvbj4ge1xuICAgIGlmICghcGFyYW1zLnJvb3RBZGRyZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQgc3RyaW5nIHJvb3RBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNLcnNSZWNvdmVyeSA9IGdldElzS3JzUmVjb3ZlcnkocGFyYW1zKTtcbiAgICBjb25zdCBpc1Vuc2lnbmVkU3dlZXAgPSBnZXRJc1Vuc2lnbmVkU3dlZXAocGFyYW1zKTtcblxuICAgIGNvbnN0IHsga3JzUHJvdmlkZXIgfSA9IHBhcmFtcztcbiAgICBpZiAoZ2V0SXNLcnNSZWNvdmVyeShwYXJhbXMpKSB7XG4gICAgICBjaGVja0tyc1Byb3ZpZGVyKHRoaXMsIGtyc1Byb3ZpZGVyKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGVzdGluYXRpb24gYWRkcmVzcyEnKTtcbiAgICB9XG5cbiAgICBjb25zdCBrZXlzID0gZ2V0QmlwMzJLZXlzKHRoaXMuYml0Z28sIHBhcmFtcywgeyByZXF1aXJlQml0R29YcHViOiBmYWxzZSB9KTtcblxuICAgIGNvbnN0IHJvb3RBZGRyZXNzRGV0YWlscyA9IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMocGFyYW1zLnJvb3RBZGRyZXNzKTtcbiAgICBjb25zdCBhY2NvdW50ID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50RnJvbU5vZGUoeyBhZGRyZXNzOiByb290QWRkcmVzc0RldGFpbHMuYWRkcmVzcyB9KTtcblxuICAgIGlmICghYWNjb3VudC5jb3JlX2xpcXVpZF9iYWxhbmNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBmaW5kIGFueSBiYWxhbmNlIHRvIHJlY292ZXJ5IGZvciAnICsgcGFyYW1zLnJvb3RBZGRyZXNzKTtcbiAgICB9XG5cbiAgICBpZiAoIWFjY291bnQucGVybWlzc2lvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGZpbmQgcGVybWlzc2lvbnMgZm9yICcgKyBwYXJhbXMucm9vdEFkZHJlc3MpO1xuICAgIH1cbiAgICBjb25zdCB1c2VyUHViID0gZWNjLlB1YmxpY0tleS5mcm9tQnVmZmVyKGtleXNbMF0ucHVibGljS2V5KS50b1N0cmluZygpO1xuICAgIGNvbnN0IGJhY2t1cFB1YiA9IGVjYy5QdWJsaWNLZXkuZnJvbUJ1ZmZlcihrZXlzWzFdLnB1YmxpY0tleSkudG9TdHJpbmcoKTtcblxuICAgIGNvbnN0IGFjdGl2ZVBlcm1pc3Npb24gPSBfLmZpbmQoYWNjb3VudC5wZXJtaXNzaW9ucywgeyBwZXJtX25hbWU6ICdhY3RpdmUnIH0pO1xuICAgIGNvbnN0IHJlcXVpcmVkQXV0aCA9IF8uZ2V0KGFjdGl2ZVBlcm1pc3Npb24sICdyZXF1aXJlZF9hdXRoJyk7XG4gICAgaWYgKCFyZXF1aXJlZEF1dGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVxdWlyZWQgYXV0aCBmb3IgYWN0aXZlIHBlcm1pc3Npb24gbm90IGZvdW5kIGluIGFjY291bnQnKTtcbiAgICB9XG4gICAgaWYgKHJlcXVpcmVkQXV0aC50aHJlc2hvbGQgIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5leHBlY3RlZCBhY3RpdmUgcGVybWlzc2lvbiB0aHJlc2hvbGQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBmb3VuZFB1YnMgPSB7fTtcbiAgICBjb25zdCByZXF1aXJlZEF1dGhLZXlzID0gcmVxdWlyZWRBdXRoLmtleXM7XG4gICAgZm9yIChjb25zdCBzaWduZXIgb2YgcmVxdWlyZWRBdXRoS2V5cykge1xuICAgICAgaWYgKHNpZ25lci53ZWlnaHQgIT09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNpZ25lciB3ZWlnaHQnKTtcbiAgICAgIH1cbiAgICAgIC8vIGlmIGl0J3MgYSBkdXBlIG9mIGEgcHViIHdlIGFscmVhZHkga25vdywgYmxvY2tcbiAgICAgIGlmIChmb3VuZFB1YnNbc2lnbmVyLmtleV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkdXBsaWNhdGUgc2lnbmVyIGtleScpO1xuICAgICAgfVxuICAgICAgZm91bmRQdWJzW3NpZ25lci5rZXldID0gKGZvdW5kUHVic1tzaWduZXIua2V5XSB8fCAwKSArIDE7XG4gICAgfVxuICAgIGlmIChmb3VuZFB1YnNbdXNlclB1Yl0gIT09IDEgfHwgZm91bmRQdWJzW2JhY2t1cFB1Yl0gIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndW5leHBlY3RlZCBpbmNpZGVuY2UgZnJlcXVlbmN5IG9mIHVzZXIgc2lnbmVyIGtleScpO1xuICAgIH1cblxuICAgIGNvbnN0IGFjY291bnRCYWxhbmNlID0gYWNjb3VudC5jb3JlX2xpcXVpZF9iYWxhbmNlLnNwbGl0KCcgJylbMF07XG4gICAgY29uc3QgcmVjb3ZlcnlBbW91bnQgPSB0aGlzLmJpZ1VuaXRzVG9CYXNlVW5pdHMobmV3IEJpZ051bWJlcihhY2NvdW50QmFsYW5jZSkudG9GaXhlZCgpKTtcblxuICAgIGNvbnN0IGRlc3RpbmF0aW9uQWRkcmVzcyA9IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uO1xuICAgIGNvbnN0IGRlc3RpbmF0aW9uQWRkcmVzc0RldGFpbHMgPSB0aGlzLmdldEFkZHJlc3NEZXRhaWxzKGRlc3RpbmF0aW9uQWRkcmVzcyk7XG4gICAgY29uc3QgZGVzdGluYXRpb25BY2NvdW50ID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50RnJvbU5vZGUoeyBhZGRyZXNzOiBkZXN0aW5hdGlvbkFkZHJlc3NEZXRhaWxzLmFkZHJlc3MgfSk7XG4gICAgaWYgKCFkZXN0aW5hdGlvbkFjY291bnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRGVzdGluYXRpb24gYWNjb3VudCBub3QgZm91bmQnKTtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFuc2FjdGlvbkhlYWRlcnMgPSBhd2FpdCB0aGlzLmdldFRyYW5zYWN0aW9uSGVhZGVyc0Zyb21Ob2RlKCk7XG4gICAgaWYgKCF0cmFuc2FjdGlvbkhlYWRlcnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGdldCB0cmFuc2FjdGlvbiBoZWFkZXJzIGZyb20gbm9kZScpO1xuICAgIH1cbiAgICBjb25zdCBoZWFkZXJzOiBFb3NUcmFuc2FjdGlvbkhlYWRlcnMgPSB0cmFuc2FjdGlvbkhlYWRlcnM7XG4gICAgY29uc3QgbmF0aXZlRGF0ZSA9IG5ldyBEYXRlKGhlYWRlcnMuZXhwaXJhdGlvbiBhcyBzdHJpbmcpO1xuICAgIC8vIGRyb3AgbWlsbGlzZWNvbmRzIGFuZCB0cmFpbGluZyBaIGZyb20gZXhwaXJhdGlvblxuICAgIG5hdGl2ZURhdGUuc2V0TWlsbGlzZWNvbmRzKDApO1xuICAgIGNvbnN0IGV4cGlyYXRpb24gPSBuYXRpdmVEYXRlLnRvSVNPU3RyaW5nKCk7XG4gICAgaWYgKGV4cGlyYXRpb24uZW5kc1dpdGgoJ1onKSkge1xuICAgICAgaGVhZGVycy5leHBpcmF0aW9uID0gZXhwaXJhdGlvbi5zbGljZSgwLCAtMSk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGFuIG9mZmxpbmUgZW9zanMgQVBJIGNsaWVudFxuICAgIGNvbnN0IGFwaSA9IG5ldyBBcGkoe1xuICAgICAgcnBjOiBuZXcgTm9vcEpzb25ScGMoKSxcbiAgICAgIHNpZ25hdHVyZVByb3ZpZGVyOiBuZXcgTm9vcFNpZ25hdHVyZVByb3ZpZGVyKCksXG4gICAgICBhYmlQcm92aWRlcjogbmV3IE9mZmxpbmVBYmlQcm92aWRlcigpLFxuICAgICAgY2hhaW5JZDogdGhpcy5nZXRDaGFpbklkKCksXG4gICAgICB0ZXh0RGVjb2RlcjogbmV3IFRleHREZWNvZGVyKCksXG4gICAgICB0ZXh0RW5jb2RlcjogbmV3IFRleHRFbmNvZGVyKCksXG4gICAgfSk7XG5cbiAgICBjb25zdCB0cmFuc2ZlckFjdGlvbiA9IHRoaXMuZ2V0VHJhbnNmZXJBY3Rpb24oe1xuICAgICAgcmVjaXBpZW50OiBkZXN0aW5hdGlvbkFkZHJlc3NEZXRhaWxzLmFkZHJlc3MsXG4gICAgICBzZW5kZXI6IHJvb3RBZGRyZXNzRGV0YWlscy5hZGRyZXNzLFxuICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKHJlY292ZXJ5QW1vdW50KSxcbiAgICAgIG1lbW86IGRlc3RpbmF0aW9uQWRkcmVzc0RldGFpbHMubWVtb0lkLFxuICAgIH0pO1xuXG4gICAgbGV0IHNlcmlhbGl6ZWRUcmFuc2FjdGlvbjtcbiAgICBjb25zdCB0eCA9IHsgYWN0aW9uczogW3RyYW5zZmVyQWN0aW9uXSB9O1xuICAgIHRyeSB7XG4gICAgICBzZXJpYWxpemVkVHJhbnNhY3Rpb24gPSBhd2FpdCBhcGkudHJhbnNhY3QoeyAuLi50eCwgLi4uaGVhZGVycyB9LCB7IHNpZ246IGZhbHNlLCBicm9hZGNhc3Q6IGZhbHNlIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRW9zIEFQSSBlcnJvcjogQ291bGQgbm90IGJ1aWxkIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIHRyYW5zYWN0aW9uIG9iamVjdFxuICAgIGNvbnN0IHNlcmlhbGl6ZWRUcmFuc2FjdGlvbkhleCA9IEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZWRUcmFuc2FjdGlvbi5zZXJpYWxpemVkVHJhbnNhY3Rpb24pLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCB0cmFuc2FjdGlvbklkID0gRW9zLmNyZWF0ZVRyYW5zYWN0aW9uSWRIZXgoc2VyaWFsaXplZFRyYW5zYWN0aW9uLnNlcmlhbGl6ZWRUcmFuc2FjdGlvbik7XG4gICAgY29uc3QgdHhPYmplY3QgPSB7XG4gICAgICB0cmFuc2FjdGlvbjoge1xuICAgICAgICBjb21wcmVzc2lvbjogJ25vbmUnLFxuICAgICAgICBwYWNrZWRfdHJ4OiBzZXJpYWxpemVkVHJhbnNhY3Rpb25IZXgsXG4gICAgICAgIHNpZ25hdHVyZXM6IFtdIGFzIHN0cmluZ1tdLFxuICAgICAgfSxcbiAgICAgIHR4aWQ6IHRyYW5zYWN0aW9uSWQsXG4gICAgICByZWNvdmVyeUFtb3VudDogYWNjb3VudEJhbGFuY2UsXG4gICAgICBjb2luOiB0aGlzLmdldENoYWluKCksXG4gICAgICB0eEhleDogJycsXG4gICAgfTtcblxuICAgIGNvbnN0IHNpZ25hYmxlVHggPSBCdWZmZXIuY29uY2F0KFtcbiAgICAgIEJ1ZmZlci5mcm9tKHRoaXMuZ2V0Q2hhaW5JZCgpLCAnaGV4JyksIC8vIFRoZSBDaGFpbklEIHJlcHJlc2VudGluZyB0aGUgY2hhaW4gdGhhdCB3ZSBhcmUgb25cbiAgICAgIEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZWRUcmFuc2FjdGlvbi5zZXJpYWxpemVkVHJhbnNhY3Rpb24pLCAvLyBUaGUgc2VyaWFsaXplZCB1bnNpZ25lZCB0eFxuICAgICAgQnVmZmVyLmZyb20obmV3IFVpbnQ4QXJyYXkoMzIpKSwgLy8gU29tZSBwYWRkaW5nXG4gICAgXSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgdHhPYmplY3QudHhIZXggPSBzaWduYWJsZVR4O1xuICAgICAgcmV0dXJuIHR4T2JqZWN0O1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJTaWduYXR1cmUgPSB0aGlzLnNpZ25UeChzaWduYWJsZVR4LCBrZXlzWzBdKTtcbiAgICB0eE9iamVjdC50cmFuc2FjdGlvbi5zaWduYXR1cmVzLnB1c2godXNlclNpZ25hdHVyZSk7XG5cbiAgICBpZiAoIWlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIGNvbnN0IGJhY2t1cFNpZ25hdHVyZSA9IHRoaXMuc2lnblR4KHNpZ25hYmxlVHgsIGtleXNbMV0pO1xuICAgICAgdHhPYmplY3QudHJhbnNhY3Rpb24uc2lnbmF0dXJlcy5wdXNoKGJhY2t1cFNpZ25hdHVyZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHR4T2JqZWN0O1xuICB9XG5cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZnkgdGhhdCBhIHRyYW5zYWN0aW9uIHByZWJ1aWxkIGNvbXBsaWVzIHdpdGggdGhlIG9yaWdpbmFsIGludGVudGlvblxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zXG4gICAqIEBwYXJhbSBwYXJhbXMudHhQYXJhbXMgcGFyYW1zIHVzZWQgdG8gYnVpbGQgdGhlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXMudHhQcmVidWlsZCB0aGUgcHJlYnVpbHQgdHJhbnNhY3Rpb25cbiAgICovXG4gIGFzeW5jIHZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtczogRW9zVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB7IHR4UGFyYW1zOiB0eFBhcmFtcywgdHhQcmVidWlsZDogdHhQcmVidWlsZCB9ID0gcGFyYW1zO1xuXG4gICAgLy8gY2hlY2sgaWYgdGhlIHRyYW5zYWN0aW9uIGhhcyBhIHR4SGV4XG4gICAgaWYgKCF0eFByZWJ1aWxkLnR4SGV4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQgdHggcHJlYnVpbGQgcHJvcGVydHkgdHhIZXgnKTtcbiAgICB9XG5cbiAgICAvLyBjb25zdHJ1Y3QgdHJhbnNhY3Rpb24gZnJvbSB0eEhleFxuICAgIGNvbnN0IHR4RnJvbUhleCA9IEJ1ZmZlci5mcm9tKHR4UHJlYnVpbGQudHhIZXgsICdoZXgnKTtcbiAgICBjb25zdCB0eERhdGFXaXRoUGFkZGluZyA9IHR4RnJvbUhleC5zbGljZSgzMik7XG4gICAgY29uc3QgdHhEYXRhID0gdHhEYXRhV2l0aFBhZGRpbmcuc2xpY2UoMCwgdHhEYXRhV2l0aFBhZGRpbmcubGVuZ3RoIC0gMzIpO1xuICAgIGNvbnN0IGRlc2VyaWFsaXplZFR4SnNvbiA9IGF3YWl0IHRoaXMuZGVzZXJpYWxpemVUcmFuc2FjdGlvbih7XG4gICAgICB0cmFuc2FjdGlvbjogeyBwYWNrZWRfdHJ4OiB0eERhdGEudG9TdHJpbmcoJ2hleCcpIH0sXG4gICAgICBoZWFkZXJzOiB0eFByZWJ1aWxkLmhlYWRlcnMsXG4gICAgfSk7XG4gICAgaWYgKCFkZXNlcmlhbGl6ZWRUeEpzb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHByb2Nlc3MgdHJhbnNhY3Rpb24gZnJvbSB0eEhleCcpO1xuICAgIH1cbiAgICBjb25zdCB0eEpzb25Gcm9tSGV4OiBEZXNlcmlhbGl6ZWRFb3NUcmFuc2FjdGlvbiA9IGRlc2VyaWFsaXplZFR4SnNvbjtcblxuICAgIC8vIGNoZWNrIHRoYXQgaWYgdHhQYXJhbXMgaGFzIGEgdHhQcmVidWlsZCwgaXQgc2hvdWxkIGJlIHRoZSBzYW1lIGFzIHR4UHJlYnVpbGRcbiAgICBpZiAodHhQYXJhbXMudHhQcmVidWlsZCAmJiAhXy5pc0VxdWFsKHR4UGFyYW1zLnR4UHJlYnVpbGQsIHR4UHJlYnVpbGQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0cyB0eFBhcmFtcy50eFByZWJ1aWxkIGFuZCB0eFByZWJ1aWxkIGV4cGVjdGVkIHRvIGJlIGVxdWFsIGJ1dCB3ZXJlIG5vdCcpO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGlmIHByZWJ1aWxkIGhhcyBhIHRyYW5zYWN0aW9uXG4gICAgaWYgKCF0eFByZWJ1aWxkLnRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQgdHJhbnNhY3Rpb24gaW4gdHhQcmVidWlsZCcpO1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGlmIHRyYW5zYWN0aW9uIGhhcyBhIHBhY2tlZF90cnhcbiAgICBpZiAoIXR4UHJlYnVpbGQudHJhbnNhY3Rpb24/LnBhY2tlZF90cngpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0cmFuc2FjdGlvbi5wYWNrZWRfdHJ4IGluIHR4UHJlYnVpbGQnKTtcbiAgICB9XG5cbiAgICAvLyBjb25zdHJ1Y3QgdHJhbnNhY3Rpb24gdXNpbmcgcGFja2VkX3RyeFxuICAgIGNvbnN0IGRlc2VyaWFsaXplZFR4SnNvbkZyb21QYWNrZWRUcnggPSBhd2FpdCB0aGlzLmRlc2VyaWFsaXplVHJhbnNhY3Rpb24oe1xuICAgICAgdHJhbnNhY3Rpb246IHsgcGFja2VkX3RyeDogdHhQcmVidWlsZC50cmFuc2FjdGlvbi5wYWNrZWRfdHJ4IH0sXG4gICAgICBoZWFkZXJzOiB0eFByZWJ1aWxkLmhlYWRlcnMsXG4gICAgfSk7XG4gICAgaWYgKCFkZXNlcmlhbGl6ZWRUeEpzb25Gcm9tUGFja2VkVHJ4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCBwcm9jZXNzIHRyYW5zYWN0aW9uIGZyb20gcGFja2VkX3RyeCcpO1xuICAgIH1cbiAgICBjb25zdCB0eEpzb25Gcm9tUGFja2VkVHJ4OiBEZXNlcmlhbGl6ZWRFb3NUcmFuc2FjdGlvbiA9IGRlc2VyaWFsaXplZFR4SnNvbkZyb21QYWNrZWRUcng7XG5cbiAgICAvLyBkZWVwIGNoZWNrIG9mIG9iamVjdCBmcm9tIHBhY2tlZF90cnggYW5kIHR4SGV4XG4gICAgaWYgKCFfLmlzRXF1YWwodHhKc29uRnJvbVBhY2tlZFRyeCwgdHhKc29uRnJvbUhleCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndW5wYWNrZWQgcGFja2VkX3RyeCBhbmQgdW5wYWNrZWQgdHhIZXggYXJlIG5vdCBlcXVhbCcpO1xuICAgIH1cblxuICAgIGlmICh0eFBhcmFtcy5yZWNpcGllbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignb25seSAwIG9yIDEgcmVjaXBpZW50cyBhcmUgc3VwcG9ydGVkJyk7XG4gICAgfVxuXG4gICAgLy8gY2hlY2sgdGhlIGFtb3VudHMsIHJlY2lwaWVudCwgYW5kIGNvaW4gbmFtZSBmb3IgdHJhbnNmZXJzXG4gICAgaWYgKHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb25zdCBleHBlY3RlZE91dHB1dCA9IHR4UGFyYW1zLnJlY2lwaWVudHNbMF07XG5cbiAgICAgIC8vIGNoZWNrIG91dHB1dCBhZGRyZXNzIGFuZCBtZW1vSWRcbiAgICAgIGNvbnN0IGV4cGVjdGVkT3V0cHV0QWRkcmVzc0FuZE1lbW9JZCA9IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMoZXhwZWN0ZWRPdXRwdXQuYWRkcmVzcyk7XG4gICAgICBjb25zdCB0eEhleEFjdGlvbiA9IHR4SnNvbkZyb21IZXguYWN0aW9uc1swXTtcbiAgICAgIGNvbnN0IHR4SGV4VHJhbnNmZXJBY3Rpb24gPSB0eEhleEFjdGlvbi5kYXRhIGFzIFRyYW5zZmVyQWN0aW9uRGF0YTtcblxuICAgICAgaWYgKHR4SGV4VHJhbnNmZXJBY3Rpb24udG8gIT09IGV4cGVjdGVkT3V0cHV0QWRkcmVzc0FuZE1lbW9JZC5hZGRyZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndHhIZXggcmVjZWl2ZSBhZGRyZXNzIGRvZXMgbm90IG1hdGNoIGV4cGVjdGVkIHJlY2lwaWVudCBhZGRyZXNzJyk7XG4gICAgICB9XG4gICAgICAvLyBjaGVjayBpZiB0eGFjdGlvbiBtZW1vaWQgaXMgZXF1YWwgdG8gYWRkcmVzcyBtZW1vIGlkIG9ubHkgaWYgYWRkcmVzcyBhbHNvIGhhcyBtZW1vaWQgcHJlc2VudFxuICAgICAgaWYgKCFfLmlzVW5kZWZpbmVkKGV4cGVjdGVkT3V0cHV0QWRkcmVzc0FuZE1lbW9JZC5tZW1vSWQpKSB7XG4gICAgICAgIGlmICh0eEhleFRyYW5zZmVyQWN0aW9uLm1lbW8gIT09IGV4cGVjdGVkT3V0cHV0QWRkcmVzc0FuZE1lbW9JZC5tZW1vSWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3R4SGV4IHJlY2VpdmUgbWVtb0lkIGRvZXMgbm90IG1hdGNoIGV4cGVjdGVkIHJlY2lwaWVudCBtZW1vSWQnKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBjaGVjayBhbW91bnQgYW5kIGNvaW5cbiAgICAgIGNvbnN0IGV4cGVjdGVkT3V0cHV0QW1vdW50ID0gZXhwZWN0ZWRPdXRwdXQuYW1vdW50O1xuICAgICAgY29uc3QgYWN0dWFsQW1vdW50QW5kQ29pbiA9IHR4SGV4VHJhbnNmZXJBY3Rpb24ucXVhbnRpdHkuc3BsaXQoJyAnKTtcbiAgICAgIGNvbnN0IGFjdHVhbE91dHB1dEFtb3VudCA9IHRoaXMuYmlnVW5pdHNUb0Jhc2VVbml0cyhhY3R1YWxBbW91bnRBbmRDb2luWzBdKTtcbiAgICAgIGlmIChleHBlY3RlZE91dHB1dEFtb3VudCAhPT0gYWN0dWFsT3V0cHV0QW1vdW50KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndHhIZXggcmVjZWl2ZSBhbW91bnQgZG9lcyBub3QgbWF0Y2ggZXhwZWN0ZWQgcmVjaXBpZW50IGFtb3VudCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHhQcmVidWlsZC5jb2luID09PSAnZW9zJyB8fCB0eFByZWJ1aWxkLmNvaW4gPT09ICd0ZW9zJykge1xuICAgICAgICBjb25zdCBleHBlY3RlZFN5bWJvbCA9IF8uaXNOaWwodHhQcmVidWlsZC50b2tlbikgPyAnRU9TJyA6IHR4UHJlYnVpbGQudG9rZW4uc3BsaXQoJzonKVsxXTtcblxuICAgICAgICBpZiAoYWN0dWFsQW1vdW50QW5kQ29pblsxXSAhPT0gZXhwZWN0ZWRTeW1ib2wpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3R4SGV4IHJlY2VpdmUgc3ltYm9sIGRvZXMgbm90IG1hdGNoIGV4cGVjdGVkIHJlY2lwaWVudCBzeW1ib2wnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gdGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndHhIZXggY29pbiBuYW1lIGRvZXMgbm90IG1hdGNoIGV4cGVjdGVkIGNvaW4gbmFtZScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGEgcmFuZG9tIEVPUyBhZGRyZXNzLlxuICAgKlxuICAgKiBUaGlzIGlzIGp1c3QgYSByYW5kb20gc3RyaW5nIHdoaWNoIGFiaWRlcyBieSB0aGUgRU9TIGFkZGRyZXNzIGNvbnN0cmFpbnRzLFxuICAgKiBhbmQgaXMgbm90IGFjdHVhbGx5IGNoZWNrZWQgZm9yIGF2YWlsYWJpbGl0eSBvbiB0aGUgRU9TIGJsb2NrY2hhaW4uXG4gICAqXG4gICAqIEN1cnJlbnQgRU9TIGFkZHJlc3MgY29uc3RyYWludHMgYXJlOlxuICAgKiAqIEFkZHJlc3MgbXVzdCBiZSBleGFjdGx5IDEyIGNoYXJhY3RlcnNcbiAgICogKiBBZGRyZXNzIG11c3Qgb25seSBjb250YWluIGxvd2VyY2FzZSBsZXR0ZXJzIGFuZCBudW1iZXJzIDEtNVxuICAgKiBAcmV0dXJucyBhIHZhbGlkbHkgZm9ybWF0dGVkIEVPUyBhZGRyZXNzLCB3aGljaCBtYXkgb3IgbWF5IG5vdCBhY3R1YWxseSBiZSBhdmFpbGFibGUgb24gY2hhaW4uXG4gICAqL1xuICBnZW5lcmF0ZVJhbmRvbUFkZHJlc3MocGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBuZXZlcj4pOiBzdHJpbmcge1xuICAgIGNvbnN0IGFkZHJlc3M6IHN0cmluZ1tdID0gW107XG4gICAgd2hpbGUgKGFkZHJlc3MubGVuZ3RoIDwgMTIpIHtcbiAgICAgIGNvbnN0IGNoYXIgPSBfLnNhbXBsZShFb3MuVkFMSURfQUREUkVTU19DSEFSUyk7XG4gICAgICBpZiAoIWNoYXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdmYWlsZWQgdG8gc2FtcGxlIHZhbGlkIEVPUyBhZGRyZXNzIGNoYXJhY3RlcnMnKTtcbiAgICAgIH1cbiAgICAgIGFkZHJlc3MucHVzaChjaGFyKTtcbiAgICB9XG4gICAgcmV0dXJuIGFkZHJlc3Muam9pbignJyk7XG4gIH1cbn1cbiJdfQ==