@bitgo/sdk-coin-eos 3.3.13 → 3.3.14

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