@bitgo-beta/sdk-coin-eos 1.3.19-beta.122 → 1.3.19-beta.1221

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