@bitgo/sdk-api 1.3.0-dev.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/dist/package.json +20 -9
  3. package/dist/src/api.d.ts.map +1 -1
  4. package/dist/src/api.js +5 -5
  5. package/dist/src/bitgoAPI.d.ts +217 -6
  6. package/dist/src/bitgoAPI.d.ts.map +1 -1
  7. package/dist/src/bitgoAPI.js +588 -16
  8. package/dist/src/types.d.ts +109 -9
  9. package/dist/src/types.d.ts.map +1 -1
  10. package/dist/src/types.js +2 -14
  11. package/dist/src/util.d.ts +0 -8
  12. package/dist/src/util.d.ts.map +1 -1
  13. package/dist/src/util.js +2 -21
  14. package/dist/src/v1/blockchain.d.ts +5 -0
  15. package/dist/src/v1/blockchain.d.ts.map +1 -0
  16. package/dist/src/v1/blockchain.js +114 -0
  17. package/dist/src/v1/keychains.d.ts +5 -0
  18. package/dist/src/v1/keychains.d.ts.map +1 -0
  19. package/dist/src/v1/keychains.js +315 -0
  20. package/dist/src/v1/markets.d.ts +5 -0
  21. package/dist/src/v1/markets.d.ts.map +1 -0
  22. package/dist/src/v1/markets.js +63 -0
  23. package/dist/src/v1/pendingapproval.d.ts +6 -0
  24. package/dist/src/v1/pendingapproval.d.ts.map +1 -0
  25. package/dist/src/v1/pendingapproval.js +322 -0
  26. package/dist/src/v1/pendingapprovals.d.ts +6 -0
  27. package/dist/src/v1/pendingapprovals.d.ts.map +1 -0
  28. package/dist/src/v1/pendingapprovals.js +68 -0
  29. package/dist/src/v1/transactionBuilder.d.ts +5 -0
  30. package/dist/src/v1/transactionBuilder.d.ts.map +1 -0
  31. package/dist/src/v1/transactionBuilder.js +889 -0
  32. package/dist/src/v1/travelRule.d.ts +5 -0
  33. package/dist/src/v1/travelRule.d.ts.map +1 -0
  34. package/dist/src/v1/travelRule.js +257 -0
  35. package/dist/src/v1/wallet.d.ts +6 -0
  36. package/dist/src/v1/wallet.d.ts.map +1 -0
  37. package/dist/src/v1/wallet.js +2095 -0
  38. package/dist/src/v1/wallets.d.ts +5 -0
  39. package/dist/src/v1/wallets.d.ts.map +1 -0
  40. package/dist/src/v1/wallets.js +472 -0
  41. package/dist/web/main.js +1 -1
  42. package/dist/web/main.js.LICENSE.txt +41 -0
  43. package/package.json +20 -9
  44. package/dist/tsconfig.tsbuildinfo +0 -7006
@@ -0,0 +1,2095 @@
1
+ "use strict";
2
+ /**
3
+ * @hidden
4
+ */
5
+ /**
6
+ */
7
+ //
8
+ // Wallet Object
9
+ // BitGo accessor for a specific wallet
10
+ //
11
+ // Copyright 2014, BitGo, Inc. All Rights Reserved.
12
+ //
13
+ const unspents_1 = require("@bitgo/unspents");
14
+ const utxo_lib_1 = require("@bitgo/utxo-lib");
15
+ const TransactionBuilder = require('./transactionBuilder');
16
+ const utxolib = require("@bitgo/utxo-lib");
17
+ const PendingApproval = require('./pendingapproval');
18
+ const sdk_core_1 = require("@bitgo/sdk-core");
19
+ const Bluebird = require("bluebird");
20
+ const co = Bluebird.coroutine;
21
+ const _ = require("lodash");
22
+ const { getExternalChainCode, getInternalChainCode, isChainCode, scriptTypeForChain } = utxolib.bitgo;
23
+ const request = require('superagent');
24
+ //
25
+ // Constructor
26
+ //
27
+ const Wallet = function (bitgo, wallet) {
28
+ // @ts-expect-error - no implicit this
29
+ this.bitgo = bitgo;
30
+ // @ts-expect-error - no implicit this
31
+ this.wallet = wallet;
32
+ // @ts-expect-error - no implicit this
33
+ this.keychains = [];
34
+ if (wallet.private) {
35
+ // @ts-expect-error - no implicit this
36
+ this.keychains = wallet.private.keychains;
37
+ }
38
+ };
39
+ Wallet.prototype.toJSON = function () {
40
+ return this.wallet;
41
+ };
42
+ //
43
+ // id
44
+ // Get the id of this wallet.
45
+ //
46
+ Wallet.prototype.id = function () {
47
+ return this.wallet.id;
48
+ };
49
+ //
50
+ // label
51
+ // Get the label of this wallet.
52
+ //
53
+ Wallet.prototype.label = function () {
54
+ return this.wallet.label;
55
+ };
56
+ //
57
+ // balance
58
+ // Get the balance of this wallet.
59
+ //
60
+ Wallet.prototype.balance = function () {
61
+ return this.wallet.balance;
62
+ };
63
+ //
64
+ // balance
65
+ // Get the spendable balance of this wallet.
66
+ // This is the total of all unspents except those that are unconfirmed and external
67
+ //
68
+ Wallet.prototype.spendableBalance = function () {
69
+ return this.wallet.spendableBalance;
70
+ };
71
+ //
72
+ // confirmedBalance
73
+ // Get the confirmedBalance of this wallet.
74
+ //
75
+ Wallet.prototype.confirmedBalance = function () {
76
+ return this.wallet.confirmedBalance;
77
+ };
78
+ //
79
+ // canSendInstant
80
+ // Returns if the wallet can send instant transactions
81
+ // This is impacted by the choice of backup key provider
82
+ //
83
+ Wallet.prototype.canSendInstant = function () {
84
+ return this.wallet && this.wallet.canSendInstant;
85
+ };
86
+ //
87
+ // instant balance
88
+ // Get the instant balance of this wallet.
89
+ // This is the total of all unspents that may be spent instantly.
90
+ //
91
+ Wallet.prototype.instantBalance = function () {
92
+ if (!this.canSendInstant()) {
93
+ throw new Error('not an instant wallet');
94
+ }
95
+ return this.wallet.instantBalance;
96
+ };
97
+ //
98
+ // unconfirmedSends
99
+ // Get the balance of unconfirmedSends of this wallet.
100
+ //
101
+ Wallet.prototype.unconfirmedSends = function () {
102
+ return this.wallet.unconfirmedSends;
103
+ };
104
+ //
105
+ // unconfirmedReceives
106
+ // Get the balance of unconfirmedReceives balance of this wallet.
107
+ //
108
+ Wallet.prototype.unconfirmedReceives = function () {
109
+ return this.wallet.unconfirmedReceives;
110
+ };
111
+ //
112
+ // type
113
+ // Get the type of this wallet, e.g. 'safehd'
114
+ //
115
+ Wallet.prototype.type = function () {
116
+ return this.wallet.type;
117
+ };
118
+ Wallet.prototype.url = function (extra) {
119
+ extra = extra || '';
120
+ return this.bitgo.url('/wallet/' + this.id() + extra);
121
+ };
122
+ //
123
+ // pendingApprovals
124
+ // returns the pending approvals list for this wallet as pending approval objects
125
+ //
126
+ Wallet.prototype.pendingApprovals = function () {
127
+ const self = this;
128
+ return this.wallet.pendingApprovals.map(function (p) {
129
+ return new PendingApproval(self.bitgo, p, self);
130
+ });
131
+ };
132
+ //
133
+ // approvalsRequired
134
+ // returns the number of approvals required to approve pending approvals involving this wallet
135
+ //
136
+ Wallet.prototype.approvalsRequired = function () {
137
+ return this.wallet.approvalsRequired || 1;
138
+ };
139
+ //
140
+ // get
141
+ // Refetches this wallet and returns it
142
+ //
143
+ Wallet.prototype.get = function (params, callback) {
144
+ params = params || {};
145
+ sdk_core_1.common.validateParams(params, [], [], callback);
146
+ const self = this;
147
+ return Bluebird.resolve(this.bitgo
148
+ .get(this.url())
149
+ .result()
150
+ .then(function (res) {
151
+ self.wallet = res;
152
+ return self;
153
+ })).nodeify(callback);
154
+ };
155
+ //
156
+ // updateApprovalsRequired
157
+ // Updates the number of approvals required on a pending approval involving this wallet.
158
+ // The approvals required is by default 1, but this function allows you to update the
159
+ // number such that 1 <= approvalsRequired <= walletAdmins.length - 1
160
+ //
161
+ Wallet.prototype.updateApprovalsRequired = function (params, callback) {
162
+ params = params || {};
163
+ sdk_core_1.common.validateParams(params, [], [], callback);
164
+ if (params.approvalsRequired === undefined ||
165
+ !_.isInteger(params.approvalsRequired) ||
166
+ params.approvalsRequired < 1) {
167
+ throw new Error('invalid approvalsRequired: must be a nonzero positive number');
168
+ }
169
+ const self = this;
170
+ const currentApprovalsRequired = this.approvalsRequired();
171
+ if (currentApprovalsRequired === params.approvalsRequired) {
172
+ // no-op, just return the current wallet
173
+ return Bluebird.try(function () {
174
+ return self.wallet;
175
+ }).nodeify(callback);
176
+ }
177
+ return Bluebird.resolve(this.bitgo.put(this.url()).send(params).result()).nodeify(callback);
178
+ };
179
+ /**
180
+ * Returns the correct chain for change, taking into consideration segwit
181
+ */
182
+ Wallet.prototype.getChangeChain = function (params) {
183
+ let useSegwitChange = !!this.bitgo.getConstants().enableSegwit;
184
+ if (!_.isUndefined(params.segwitChange)) {
185
+ if (!_.isBoolean(params.segwitChange)) {
186
+ throw new Error('segwitChange must be a boolean');
187
+ }
188
+ // if segwit is disabled through the constants, segwit change should still not be created
189
+ useSegwitChange = this.bitgo.getConstants().enableSegwit && params.segwitChange;
190
+ }
191
+ return useSegwitChange ? getInternalChainCode('p2shP2wsh') : getInternalChainCode('p2sh');
192
+ };
193
+ //
194
+ // createAddress
195
+ // Creates a new address for use with this wallet.
196
+ //
197
+ Wallet.prototype.createAddress = function (params, callback) {
198
+ const self = this;
199
+ params = params || {};
200
+ sdk_core_1.common.validateParams(params, [], [], callback);
201
+ if (this.type() === 'safe') {
202
+ throw new Error('You are using a legacy wallet that cannot create a new address');
203
+ }
204
+ // Default to client-side address validation on, for safety. Use validate=false to disable.
205
+ const shouldValidate = params.validate !== undefined ? params.validate : this.bitgo.getValidate();
206
+ const allowExisting = params.allowExisting;
207
+ if (typeof allowExisting !== 'boolean') {
208
+ params.allowExisting = allowExisting === 'true';
209
+ }
210
+ const isSegwit = this.bitgo.getConstants().enableSegwit;
211
+ const defaultChain = isSegwit ? getExternalChainCode('p2shP2wsh') : getExternalChainCode('p2sh');
212
+ let chain = params.chain;
213
+ if (chain === null || chain === undefined) {
214
+ chain = defaultChain;
215
+ }
216
+ return Bluebird.resolve(this.bitgo
217
+ .post(this.url('/address/' + chain))
218
+ .send(params)
219
+ .result()
220
+ .then(function (addr) {
221
+ if (shouldValidate) {
222
+ self.validateAddress(addr);
223
+ }
224
+ return addr;
225
+ })).nodeify(callback);
226
+ };
227
+ /**
228
+ * Generate address locally without calling server
229
+ * @param params
230
+ *
231
+ */
232
+ Wallet.prototype.generateAddress = function ({ segwit, path, keychains, threshold }) {
233
+ const isSegwit = !!segwit;
234
+ let signatureThreshold = 2;
235
+ if (_.isInteger(threshold)) {
236
+ signatureThreshold = threshold;
237
+ if (signatureThreshold <= 0) {
238
+ throw new Error('threshold has to be positive');
239
+ }
240
+ }
241
+ const pathRegex = /^\/1?[01]\/\d+$/;
242
+ if (!path.match(pathRegex)) {
243
+ throw new Error('unsupported path: ' + path);
244
+ }
245
+ let rootKeys = this.keychains;
246
+ if (Array.isArray(keychains)) {
247
+ rootKeys = keychains;
248
+ }
249
+ const network = sdk_core_1.common.Environments[this.bitgo.getEnv()].network;
250
+ const derivedKeys = rootKeys.map(function (k) {
251
+ const hdnode = utxo_lib_1.bip32.fromBase58(k.xpub);
252
+ const derivationPath = k.path + (k.walletSubPath || '') + path;
253
+ return hdnode.derivePath(sdk_core_1.sanitizeLegacyPath(derivationPath)).publicKey;
254
+ });
255
+ const pathComponents = path.split('/');
256
+ const normalizedPathComponents = _.map(pathComponents, (component) => {
257
+ if (component && component.length > 0) {
258
+ return parseInt(component, 10);
259
+ }
260
+ });
261
+ const pathDetails = _.filter(normalizedPathComponents, _.isInteger);
262
+ const addressDetails = {
263
+ chainPath: path,
264
+ path: path,
265
+ chain: pathDetails[0],
266
+ index: pathDetails[1],
267
+ wallet: this.id(),
268
+ };
269
+ const { scriptPubKey: outputScript, redeemScript, witnessScript, } = utxolib.bitgo.outputScripts.createOutputScript2of3(derivedKeys, isSegwit ? 'p2shP2wsh' : 'p2sh');
270
+ addressDetails.witnessScript = witnessScript === null || witnessScript === void 0 ? void 0 : witnessScript.toString('hex');
271
+ addressDetails.redeemScript = redeemScript === null || redeemScript === void 0 ? void 0 : redeemScript.toString('hex');
272
+ addressDetails.outputScript = outputScript.toString('hex');
273
+ addressDetails.address = utxolib.address.fromOutputScript(outputScript, sdk_core_1.getNetwork(network));
274
+ return addressDetails;
275
+ };
276
+ //
277
+ // validateAddress
278
+ // Validates an address and path by calculating it locally from the keychain xpubs
279
+ //
280
+ Wallet.prototype.validateAddress = function (params) {
281
+ sdk_core_1.common.validateParams(params, ['address', 'path'], []);
282
+ const isSegwit = !!params.witnessScript && params.witnessScript.length > 0;
283
+ const generatedAddress = this.generateAddress({ path: params.path, segwit: isSegwit });
284
+ if (generatedAddress.address !== params.address) {
285
+ throw new Error('address validation failure: ' + params.address + ' vs. ' + generatedAddress.address);
286
+ }
287
+ };
288
+ //
289
+ // addresses
290
+ // Gets the addresses of a HD wallet.
291
+ // Options include:
292
+ // limit: the number of addresses to get
293
+ //
294
+ Wallet.prototype.addresses = function (params, callback) {
295
+ params = params || {};
296
+ sdk_core_1.common.validateParams(params, [], [], callback);
297
+ const query = {};
298
+ if (params.details) {
299
+ query.details = 1;
300
+ }
301
+ const chain = params.chain;
302
+ if (chain !== null && chain !== undefined) {
303
+ if (Array.isArray(chain)) {
304
+ query.chain = _.uniq(_.filter(chain, _.isInteger));
305
+ }
306
+ else {
307
+ if (chain !== 0 && chain !== 1) {
308
+ throw new Error('invalid chain argument, expecting 0 or 1');
309
+ }
310
+ query.chain = chain;
311
+ }
312
+ }
313
+ if (params.limit) {
314
+ if (!_.isInteger(params.limit)) {
315
+ throw new Error('invalid limit argument, expecting number');
316
+ }
317
+ query.limit = params.limit;
318
+ }
319
+ if (params.skip) {
320
+ if (!_.isInteger(params.skip)) {
321
+ throw new Error('invalid skip argument, expecting number');
322
+ }
323
+ query.skip = params.skip;
324
+ }
325
+ if (params.sort) {
326
+ if (!_.isNumber(params.sort)) {
327
+ throw new Error('invalid sort argument, expecting number');
328
+ }
329
+ query.sort = params.sort;
330
+ }
331
+ const url = this.url('/addresses');
332
+ return Bluebird.resolve(this.bitgo.get(url).query(query).result()).nodeify(callback);
333
+ };
334
+ Wallet.prototype.stats = function (params, callback) {
335
+ params = params || {};
336
+ sdk_core_1.common.validateParams(params, [], [], callback);
337
+ const args = [];
338
+ if (params.limit) {
339
+ if (!_.isInteger(params.limit)) {
340
+ throw new Error('invalid limit argument, expecting number');
341
+ }
342
+ args.push('limit=' + params.limit);
343
+ }
344
+ let query = '';
345
+ if (args.length) {
346
+ query = '?' + args.join('&');
347
+ }
348
+ const url = this.url('/stats' + query);
349
+ return Bluebird.resolve(this.bitgo.get(url).result()).nodeify(callback);
350
+ };
351
+ /**
352
+ * Refresh the wallet object by syncing with the back-end
353
+ * @param callback
354
+ * @returns {Wallet}
355
+ */
356
+ Wallet.prototype.refresh = function (params, callback) {
357
+ return co(function* () {
358
+ // when set to true, gpk returns the private data of safe wallets
359
+ const query = _.extend({}, _.pick(params, ['gpk']));
360
+ // @ts-expect-error - no implicit this
361
+ const res = yield this.bitgo.get(this.url()).query(query).result();
362
+ // @ts-expect-error - no implicit this
363
+ this.wallet = res;
364
+ // @ts-expect-error - no implicit this
365
+ return this;
366
+ })
367
+ .call(this)
368
+ .asCallback(callback);
369
+ };
370
+ //
371
+ // address
372
+ // Gets information about a single address on a HD wallet.
373
+ // Information includes index, path, redeemScript, sent, received, txCount and balance
374
+ // Options include:
375
+ // address: the address on this wallet to get
376
+ //
377
+ Wallet.prototype.address = function (params, callback) {
378
+ params = params || {};
379
+ sdk_core_1.common.validateParams(params, ['address'], [], callback);
380
+ const url = this.url('/addresses/' + params.address);
381
+ return Bluebird.resolve(this.bitgo.get(url).result()).nodeify(callback);
382
+ };
383
+ /**
384
+ * Freeze the wallet for a duration of choice, stopping BitGo from signing any transactions.
385
+ * @param {number} limit The duration to freeze the wallet for in seconds, defaults to 3600.
386
+ */
387
+ Wallet.prototype.freeze = function (params, callback) {
388
+ params = params || {};
389
+ sdk_core_1.common.validateParams(params, [], [], callback);
390
+ if (params.duration) {
391
+ if (!_.isNumber(params.duration)) {
392
+ throw new Error('invalid duration - should be number of seconds');
393
+ }
394
+ }
395
+ return Bluebird.resolve(this.bitgo.post(this.url('/freeze')).send(params).result()).nodeify(callback);
396
+ };
397
+ //
398
+ // delete
399
+ // Deletes the wallet
400
+ //
401
+ Wallet.prototype.delete = function (params, callback) {
402
+ params = params || {};
403
+ sdk_core_1.common.validateParams(params, [], [], callback);
404
+ return Bluebird.resolve(this.bitgo.del(this.url()).result()).nodeify(callback);
405
+ };
406
+ //
407
+ // labels
408
+ // List the labels for the addresses in a given wallet
409
+ //
410
+ Wallet.prototype.labels = function (params, callback) {
411
+ params = params || {};
412
+ sdk_core_1.common.validateParams(params, [], [], callback);
413
+ const url = this.bitgo.url('/labels/' + this.id());
414
+ return Bluebird.resolve(this.bitgo.get(url).result('labels')).nodeify(callback);
415
+ };
416
+ /**
417
+ * Rename a wallet
418
+ * @param params
419
+ * - label: the wallet's intended new name
420
+ * @param callback
421
+ * @returns {*}
422
+ */
423
+ Wallet.prototype.setWalletName = function (params, callback) {
424
+ params = params || {};
425
+ sdk_core_1.common.validateParams(params, ['label'], [], callback);
426
+ const url = this.bitgo.url('/wallet/' + this.id());
427
+ return Bluebird.resolve(this.bitgo.put(url).send({ label: params.label }).result()).nodeify(callback);
428
+ };
429
+ //
430
+ // setLabel
431
+ // Sets a label on the provided address
432
+ //
433
+ Wallet.prototype.setLabel = function (params, callback) {
434
+ params = params || {};
435
+ sdk_core_1.common.validateParams(params, ['address', 'label'], [], callback);
436
+ const self = this;
437
+ if (!self.bitgo.verifyAddress({ address: params.address })) {
438
+ throw new Error('Invalid bitcoin address: ' + params.address);
439
+ }
440
+ const url = this.bitgo.url('/labels/' + this.id() + '/' + params.address);
441
+ return Bluebird.resolve(this.bitgo.put(url).send({ label: params.label }).result()).nodeify(callback);
442
+ };
443
+ //
444
+ // deleteLabel
445
+ // Deletes the label associated with the provided address
446
+ //
447
+ Wallet.prototype.deleteLabel = function (params, callback) {
448
+ params = params || {};
449
+ sdk_core_1.common.validateParams(params, ['address'], [], callback);
450
+ const self = this;
451
+ if (!self.bitgo.verifyAddress({ address: params.address })) {
452
+ throw new Error('Invalid bitcoin address: ' + params.address);
453
+ }
454
+ const url = this.bitgo.url('/labels/' + this.id() + '/' + params.address);
455
+ return Bluebird.resolve(this.bitgo.del(url).result()).nodeify(callback);
456
+ };
457
+ //
458
+ // unspents
459
+ // List ALL the unspents for a given wallet
460
+ // This method will return a paged list of all unspents
461
+ //
462
+ // Parameters include:
463
+ // limit: the optional limit of unspents to collect in BTC
464
+ // minConf: only include results with this number of confirmations
465
+ // target: the amount of btc to find to spend
466
+ // instant: only find instant transactions (must specify a target)
467
+ //
468
+ Wallet.prototype.unspents = function (params, callback) {
469
+ params = params || {};
470
+ sdk_core_1.common.validateParams(params, [], [], callback);
471
+ const allUnspents = [];
472
+ const self = this;
473
+ const getUnspentsBatch = function (skip, limit) {
474
+ const queryObject = _.cloneDeep(params);
475
+ if (skip > 0) {
476
+ queryObject.skip = skip;
477
+ }
478
+ if (limit && limit > 0) {
479
+ queryObject.limit = limit;
480
+ }
481
+ return self.unspentsPaged(queryObject).then(function (result) {
482
+ // The API has its own limit handling. For example, the API does not support limits bigger than 500. If the limit
483
+ // specified here is bigger than that, we will have to do multiple requests with necessary limit adjustment.
484
+ for (let i = 0; i < result.unspents.length; i++) {
485
+ const unspent = result.unspents[i];
486
+ allUnspents.push(unspent);
487
+ }
488
+ // Our limit adjustment makes sure that we never fetch more unspents than we need, meaning that if we hit the
489
+ // limit, we hit it precisely
490
+ if (allUnspents.length >= params.limit) {
491
+ return allUnspents; // we aren't interested in any further unspents
492
+ }
493
+ const totalUnspentCount = result.total;
494
+ // if no target is specified and the SDK indicates that there has been a limit, we need to fetch another batch
495
+ if (!params.target && totalUnspentCount && totalUnspentCount > allUnspents.length) {
496
+ // we need to fetch the next batch
497
+ // let's just offset the current skip by the count
498
+ const newSkip = skip + result.count;
499
+ let newLimit;
500
+ if (limit > 0) {
501
+ // we set the new limit to be precisely the number of missing unspents to hit our own limit
502
+ newLimit = limit - allUnspents.length;
503
+ }
504
+ return getUnspentsBatch(newSkip, newLimit);
505
+ }
506
+ return allUnspents;
507
+ });
508
+ };
509
+ return getUnspentsBatch(0, params.limit).nodeify(callback);
510
+ };
511
+ /**
512
+ * List the unspents (paged) for a given wallet, returning the result as an object of unspents, count, skip and total
513
+ * This method may not return all the unspents as the list is paged by the API
514
+ * @param params
515
+ * @param params.limit the optional limit of unspents to collect in BTC
516
+ * @param params.skip index in list of unspents to start paging from
517
+ * @param params.minConfirms only include results with this number of confirmations
518
+ * @param params.target the amount of btc to find to spend
519
+ * @param params.instant only find instant transactions (must specify a target)
520
+ * @param params.targetWalletUnspents desired number of unspents to have in the wallet after the tx goes through (requires target)
521
+ * @param params.minSize minimum unspent size in satoshis
522
+ * @param params.segwit request segwit unspents (defaults to true if undefined)
523
+ * @param params.allowLedgerSegwit allow segwit unspents for ledger devices (defaults to false if undefined)
524
+ * @param callback
525
+ * @returns {*}
526
+ */
527
+ Wallet.prototype.unspentsPaged = function (params, callback) {
528
+ params = params || {};
529
+ sdk_core_1.common.validateParams(params, [], [], callback);
530
+ if (!_.isUndefined(params.limit) && !_.isInteger(params.limit)) {
531
+ throw new Error('invalid limit - should be number');
532
+ }
533
+ if (!_.isUndefined(params.skip) && !_.isInteger(params.skip)) {
534
+ throw new Error('invalid skip - should be number');
535
+ }
536
+ if (!_.isUndefined(params.minConfirms) && !_.isInteger(params.minConfirms)) {
537
+ throw new Error('invalid minConfirms - should be number');
538
+ }
539
+ if (!_.isUndefined(params.target) && !_.isNumber(params.target)) {
540
+ throw new Error('invalid target - should be number');
541
+ }
542
+ if (!_.isUndefined(params.instant) && !_.isBoolean(params.instant)) {
543
+ throw new Error('invalid instant flag - should be boolean');
544
+ }
545
+ if (!_.isUndefined(params.segwit) && !_.isBoolean(params.segwit)) {
546
+ throw new Error('invalid segwit flag - should be boolean');
547
+ }
548
+ if (!_.isUndefined(params.targetWalletUnspents) && !_.isInteger(params.targetWalletUnspents)) {
549
+ throw new Error('invalid targetWalletUnspents flag - should be number');
550
+ }
551
+ if (!_.isUndefined(params.minSize) && !_.isNumber(params.minSize)) {
552
+ throw new Error('invalid argument: minSize must be a number');
553
+ }
554
+ if (!_.isUndefined(params.instant) && !_.isUndefined(params.minConfirms)) {
555
+ throw new Error('only one of instant and minConfirms may be defined');
556
+ }
557
+ if (!_.isUndefined(params.targetWalletUnspents) && _.isUndefined(params.target)) {
558
+ throw new Error('targetWalletUnspents can only be specified in conjunction with a target');
559
+ }
560
+ if (!_.isUndefined(params.allowLedgerSegwit) && !_.isBoolean(params.allowLedgerSegwit)) {
561
+ throw new Error('invalid argument: allowLedgerSegwit must be a boolean');
562
+ }
563
+ const queryObject = _.cloneDeep(params);
564
+ if (!_.isUndefined(params.target)) {
565
+ // skip and limit are unavailable when a target is specified
566
+ delete queryObject.skip;
567
+ delete queryObject.limit;
568
+ }
569
+ queryObject.segwit = true;
570
+ if (!_.isUndefined(params.segwit)) {
571
+ queryObject.segwit = params.segwit;
572
+ }
573
+ if (!_.isUndefined(params.allowLedgerSegwit)) {
574
+ queryObject.allowLedgerSegwit = params.allowLedgerSegwit;
575
+ }
576
+ return Bluebird.resolve(this.bitgo.get(this.url('/unspents')).query(queryObject).result()).nodeify(callback);
577
+ };
578
+ //
579
+ // transactions
580
+ // List the transactions for a given wallet
581
+ // Options include:
582
+ // TODO: Add iterators for start/count/etc
583
+ Wallet.prototype.transactions = function (params, callback) {
584
+ params = params || {};
585
+ sdk_core_1.common.validateParams(params, [], [], callback);
586
+ const args = [];
587
+ if (params.limit) {
588
+ if (!_.isInteger(params.limit)) {
589
+ throw new Error('invalid limit argument, expecting number');
590
+ }
591
+ args.push('limit=' + params.limit);
592
+ }
593
+ if (params.skip) {
594
+ if (!_.isInteger(params.skip)) {
595
+ throw new Error('invalid skip argument, expecting number');
596
+ }
597
+ args.push('skip=' + params.skip);
598
+ }
599
+ if (params.minHeight) {
600
+ if (!_.isInteger(params.minHeight)) {
601
+ throw new Error('invalid minHeight argument, expecting number');
602
+ }
603
+ args.push('minHeight=' + params.minHeight);
604
+ }
605
+ if (params.maxHeight) {
606
+ if (!_.isInteger(params.maxHeight) || params.maxHeight < 0) {
607
+ throw new Error('invalid maxHeight argument, expecting positive integer');
608
+ }
609
+ args.push('maxHeight=' + params.maxHeight);
610
+ }
611
+ if (params.minConfirms) {
612
+ if (!_.isInteger(params.minConfirms) || params.minConfirms < 0) {
613
+ throw new Error('invalid minConfirms argument, expecting positive integer');
614
+ }
615
+ args.push('minConfirms=' + params.minConfirms);
616
+ }
617
+ if (!_.isUndefined(params.compact)) {
618
+ if (!_.isBoolean(params.compact)) {
619
+ throw new Error('invalid compact argument, expecting boolean');
620
+ }
621
+ args.push('compact=' + params.compact);
622
+ }
623
+ let query = '';
624
+ if (args.length) {
625
+ query = '?' + args.join('&');
626
+ }
627
+ const url = this.url('/tx' + query);
628
+ return Bluebird.resolve(this.bitgo.get(url).result()).nodeify(callback);
629
+ };
630
+ //
631
+ // transaction
632
+ // Get a transaction by ID for a given wallet
633
+ Wallet.prototype.getTransaction = function (params, callback) {
634
+ params = params || {};
635
+ sdk_core_1.common.validateParams(params, ['id'], [], callback);
636
+ const url = this.url('/tx/' + params.id);
637
+ return Bluebird.resolve(this.bitgo.get(url).result()).nodeify(callback);
638
+ };
639
+ //
640
+ // pollForTransaction
641
+ // Poll a transaction until successful or times out
642
+ // Parameters:
643
+ // id: the txid
644
+ // delay: delay between polls in ms (default: 1000)
645
+ // timeout: timeout in ms (default: 10000)
646
+ Wallet.prototype.pollForTransaction = function (params, callback) {
647
+ const self = this;
648
+ params = params || {};
649
+ sdk_core_1.common.validateParams(params, ['id'], [], callback);
650
+ if (params.delay && !_.isNumber(params.delay)) {
651
+ throw new Error('invalid delay parameter');
652
+ }
653
+ if (params.timeout && !_.isNumber(params.timeout)) {
654
+ throw new Error('invalid timeout parameter');
655
+ }
656
+ params.delay = params.delay || 1000;
657
+ params.timeout = params.timeout || 10000;
658
+ const start = new Date();
659
+ const doNextPoll = function () {
660
+ return self
661
+ .getTransaction(params)
662
+ .then(function (res) {
663
+ return res;
664
+ })
665
+ .catch(function (err) {
666
+ if (err.status !== 404 || new Date().valueOf() - start.valueOf() > params.timeout) {
667
+ throw err;
668
+ }
669
+ return Bluebird.delay(params.delay).then(function () {
670
+ return doNextPoll();
671
+ });
672
+ });
673
+ };
674
+ return doNextPoll();
675
+ };
676
+ //
677
+ // transaction by sequence id
678
+ // Get a transaction by sequence id for a given wallet
679
+ Wallet.prototype.getWalletTransactionBySequenceId = function (params, callback) {
680
+ params = params || {};
681
+ sdk_core_1.common.validateParams(params, ['sequenceId'], [], callback);
682
+ const url = this.url('/tx/sequence/' + params.sequenceId);
683
+ return Bluebird.resolve(this.bitgo.get(url).result()).nodeify(callback);
684
+ };
685
+ //
686
+ // Key chains
687
+ // Gets the user key chain for this wallet
688
+ // The user key chain is typically the first keychain of the wallet and has the encrypted xpriv stored on BitGo.
689
+ // Useful when trying to get the users' keychain from the server before decrypting to sign a transaction.
690
+ Wallet.prototype.getEncryptedUserKeychain = function (params, callback) {
691
+ return co(function* () {
692
+ params = params || {};
693
+ sdk_core_1.common.validateParams(params, [], [], callback);
694
+ // @ts-expect-error - no implicit this
695
+ const self = this;
696
+ const tryKeyChain = co(function* (index) {
697
+ if (!self.keychains || index >= self.keychains.length) {
698
+ const error = new Error('No encrypted keychains on this wallet.');
699
+ error.code = 'no_encrypted_keychain_on_wallet';
700
+ throw error;
701
+ }
702
+ const params = { xpub: self.keychains[index].xpub };
703
+ const keychain = yield self.bitgo.keychains().get(params);
704
+ // If we find the xprv, then this is probably the user keychain we're looking for
705
+ keychain.walletSubPath = self.keychains[index].path;
706
+ if (keychain.encryptedXprv) {
707
+ return keychain;
708
+ }
709
+ return tryKeyChain(index + 1);
710
+ });
711
+ return tryKeyChain(0);
712
+ })
713
+ .call(this)
714
+ .asCallback(callback);
715
+ };
716
+ //
717
+ // createTransaction
718
+ // Create a transaction (unsigned). To sign it, do signTransaction
719
+ // Parameters:
720
+ // recipients - object of recipient addresses and the amount to send to each e.g. {address:1500, address2:1500}
721
+ // fee - the blockchain fee to send (optional)
722
+ // feeRate - the fee per kb to send (optional)
723
+ // minConfirms - minimum number of confirms to use when gathering unspents
724
+ // forceChangeAtEnd - force change address to be last output (optional)
725
+ // noSplitChange - disable automatic change splitting for purposes of unspent management
726
+ // changeAddress - override the change address (optional)
727
+ // validate - extra verification of change addresses (which are always verified server-side) (defaults to global config)
728
+ // Returns:
729
+ // callback(err, { transactionHex: string, unspents: [inputs], fee: satoshis })
730
+ Wallet.prototype.createTransaction = function (params, callback) {
731
+ params = _.extend({}, params);
732
+ sdk_core_1.common.validateParams(params, [], [], callback);
733
+ if ((!_.isNumber(params.fee) && !_.isUndefined(params.fee)) ||
734
+ (!_.isNumber(params.feeRate) && !_.isUndefined(params.feeRate)) ||
735
+ (!_.isNumber(params.minConfirms) && !_.isUndefined(params.minConfirms)) ||
736
+ (!_.isBoolean(params.forceChangeAtEnd) && !_.isUndefined(params.forceChangeAtEnd)) ||
737
+ (!_.isString(params.changeAddress) && !_.isUndefined(params.changeAddress)) ||
738
+ (!_.isBoolean(params.validate) && !_.isUndefined(params.validate)) ||
739
+ (!_.isBoolean(params.instant) && !_.isUndefined(params.instant))) {
740
+ throw new Error('invalid argument');
741
+ }
742
+ if (!_.isObject(params.recipients)) {
743
+ throw new Error('expecting recipients object');
744
+ }
745
+ params.validate = params.validate !== undefined ? params.validate : this.bitgo.getValidate();
746
+ params.wallet = this;
747
+ return TransactionBuilder.createTransaction(params).nodeify(callback);
748
+ };
749
+ //
750
+ // signTransaction
751
+ // Sign a previously created transaction with a keychain
752
+ // Parameters:
753
+ // transactionHex - serialized form of the transaction in hex
754
+ // unspents - array of unspent information, where each unspent is a chainPath
755
+ // and redeemScript with the same index as the inputs in the
756
+ // transactionHex
757
+ // keychain - Keychain containing the xprv to sign with.
758
+ // signingKey - For legacy safe wallets, the private key string.
759
+ // validate - extra verification of signatures (which are always verified server-side) (defaults to global config)
760
+ // Returns:
761
+ // callback(err, transaction)
762
+ Wallet.prototype.signTransaction = function (params, callback) {
763
+ params = _.extend({}, params);
764
+ sdk_core_1.common.validateParams(params, ['transactionHex'], [], callback);
765
+ if (!Array.isArray(params.unspents)) {
766
+ throw new Error('expecting the unspents array');
767
+ }
768
+ if ((!_.isObject(params.keychain) || !params.keychain.xprv) && !_.isString(params.signingKey)) {
769
+ // allow passing in a WIF private key for legacy safe wallet support
770
+ const error = new Error('expecting keychain object with xprv or signingKey WIF');
771
+ error.code = 'missing_keychain_or_signingKey';
772
+ throw error;
773
+ }
774
+ params.validate = params.validate !== undefined ? params.validate : this.bitgo.getValidate();
775
+ params.bitgo = this.bitgo;
776
+ return TransactionBuilder.signTransaction(params)
777
+ .then(function (result) {
778
+ return {
779
+ tx: result.transactionHex,
780
+ };
781
+ })
782
+ .nodeify(callback);
783
+ };
784
+ //
785
+ // send
786
+ // Send a transaction to the Bitcoin network via BitGo.
787
+ // One of the keys is typically signed, and BitGo will sign the other (if approved) and relay it to the P2P network.
788
+ // Parameters:
789
+ // tx - the hex encoded, signed transaction to send
790
+ // Returns:
791
+ //
792
+ Wallet.prototype.sendTransaction = function (params, callback) {
793
+ params = params || {};
794
+ sdk_core_1.common.validateParams(params, ['tx'], ['message', 'otp'], callback);
795
+ return Bluebird.resolve(this.bitgo.post(this.bitgo.url('/tx/send')).send(params).result())
796
+ .then(function (body) {
797
+ if (body.pendingApproval) {
798
+ return _.extend(body, { status: 'pendingApproval' });
799
+ }
800
+ if (body.otp) {
801
+ return _.extend(body, { status: 'otp' });
802
+ }
803
+ return {
804
+ status: 'accepted',
805
+ tx: body.transaction,
806
+ hash: body.transactionHash,
807
+ instant: body.instant,
808
+ instantId: body.instantId,
809
+ };
810
+ })
811
+ .nodeify(callback);
812
+ };
813
+ /**
814
+ * Share the wallet with an existing BitGo user.
815
+ * @param {string} user The recipient's user id, must have a corresponding user record in our database.
816
+ * @param {keychain} keychain The keychain to be shared with the recipient.
817
+ * @param {string} permissions A comma-separated value string that specifies the recipient's permissions if the share is accepted.
818
+ * @param {string} message The message to be used for this share.
819
+ */
820
+ Wallet.prototype.createShare = function (params, callback) {
821
+ params = params || {};
822
+ sdk_core_1.common.validateParams(params, ['user', 'permissions'], [], callback);
823
+ if (params.keychain && !_.isEmpty(params.keychain)) {
824
+ if (!params.keychain.xpub ||
825
+ !params.keychain.encryptedXprv ||
826
+ !params.keychain.fromPubKey ||
827
+ !params.keychain.toPubKey ||
828
+ !params.keychain.path) {
829
+ throw new Error('requires keychain parameters - xpub, encryptedXprv, fromPubKey, toPubKey, path');
830
+ }
831
+ }
832
+ return Bluebird.resolve(this.bitgo.post(this.url('/share')).send(params).result()).nodeify(callback);
833
+ };
834
+ //
835
+ // createInvite
836
+ // invite a non BitGo customer to join a wallet
837
+ // Parameters:
838
+ // email - the recipient's email address
839
+ // permissions - the recipient's permissions if the share is accepted
840
+ // Returns:
841
+ //
842
+ Wallet.prototype.createInvite = function (params, callback) {
843
+ params = params || {};
844
+ sdk_core_1.common.validateParams(params, ['email', 'permissions'], ['message'], callback);
845
+ const options = {
846
+ toEmail: params.email,
847
+ permissions: params.permissions,
848
+ };
849
+ if (params.message) {
850
+ options.message = params.message;
851
+ }
852
+ return Bluebird.resolve(this.bitgo.post(this.url('/invite')).send(options).result()).nodeify(callback);
853
+ };
854
+ //
855
+ // confirmInviteAndShareWallet
856
+ // confirm my invite on this wallet to a recipient who has
857
+ // subsequently signed up by creating the actual wallet share
858
+ // Parameters:
859
+ // walletInviteId - the wallet invite id
860
+ // walletPassphrase - required if the wallet share success is expected
861
+ // Returns:
862
+ //
863
+ Wallet.prototype.confirmInviteAndShareWallet = function (params, callback) {
864
+ params = params || {};
865
+ sdk_core_1.common.validateParams(params, ['walletInviteId'], ['walletPassphrase'], callback);
866
+ const self = this;
867
+ return this.bitgo
868
+ .wallets()
869
+ .listInvites()
870
+ .then(function (invites) {
871
+ const outgoing = invites.outgoing;
872
+ const invite = _.find(outgoing, function (out) {
873
+ return out.id === params.walletInviteId;
874
+ });
875
+ if (!invite) {
876
+ throw new Error('wallet invite not found');
877
+ }
878
+ const options = {
879
+ email: invite.toEmail,
880
+ permissions: invite.permissions,
881
+ message: invite.message,
882
+ walletPassphrase: params.walletPassphrase,
883
+ };
884
+ return self.shareWallet(options);
885
+ })
886
+ .then(function () {
887
+ // @ts-expect-error - no implicit this
888
+ return this.bitgo.put(this.bitgo.url('/walletinvite/' + params.walletInviteId));
889
+ })
890
+ .nodeify(callback);
891
+ };
892
+ //
893
+ // sendCoins
894
+ // Send coins to a destination address from this wallet using the user key.
895
+ // 1. Gets the user keychain by checking the wallet for a key which has an encrypted xpriv
896
+ // 2. Decrypts user key
897
+ // 3. Creates the transaction with default fee
898
+ // 4. Signs transaction with decrypted user key
899
+ // 3. Sends the transaction to BitGo
900
+ //
901
+ // Parameters:
902
+ // address - the destination address
903
+ // amount - the amount in satoshis to be sent
904
+ // message - optional message to attach to transaction
905
+ // walletPassphrase - the passphrase to be used to decrypt the user key on this wallet
906
+ // xprv - the private key in string form, if walletPassphrase is not available
907
+ // (See transactionBuilder.createTransaction for other passthrough params)
908
+ // Returns:
909
+ //
910
+ Wallet.prototype.sendCoins = function (params, callback) {
911
+ params = params || {};
912
+ sdk_core_1.common.validateParams(params, ['address'], ['message'], callback);
913
+ if (!_.isNumber(params.amount)) {
914
+ throw new Error('invalid argument for amount - number expected');
915
+ }
916
+ params.recipients = {};
917
+ params.recipients[params.address] = params.amount;
918
+ return this.sendMany(params).nodeify(callback);
919
+ };
920
+ //
921
+ // sendMany
922
+ // Send coins to multiple destination addresses from this wallet using the user key.
923
+ // 1. Gets the user keychain by checking the wallet for a key which has an encrypted xpriv
924
+ // 2. Decrypts user key
925
+ // 3. Creates the transaction with default fee
926
+ // 4. Signs transaction with decrypted user key
927
+ // 3. Sends the transaction to BitGo
928
+ //
929
+ // Parameters:
930
+ // recipients - array of { address: string, amount: number, travelInfo: object } to send to
931
+ // walletPassphrase - the passphrase to be used to decrypt the user key on this wallet
932
+ // xprv - the private key in string form, if walletPassphrase is not available
933
+ // (See transactionBuilder.createTransaction for other passthrough params)
934
+ // Returns:
935
+ //
936
+ Wallet.prototype.sendMany = function (params, callback) {
937
+ params = params || {};
938
+ sdk_core_1.common.validateParams(params, [], ['message', 'otp'], callback);
939
+ const self = this;
940
+ if (!_.isObject(params.recipients)) {
941
+ throw new Error('expecting recipients object');
942
+ }
943
+ if (params.fee && !_.isNumber(params.fee)) {
944
+ throw new Error('invalid argument for fee - number expected');
945
+ }
946
+ if (params.feeRate && !_.isNumber(params.feeRate)) {
947
+ throw new Error('invalid argument for feeRate - number expected');
948
+ }
949
+ if (params.instant && !_.isBoolean(params.instant)) {
950
+ throw new Error('invalid argument for instant - boolean expected');
951
+ }
952
+ let bitgoFee;
953
+ let travelInfos;
954
+ let finalResult;
955
+ let unspentsUsed;
956
+ const acceptedBuildParams = [
957
+ 'numBlocks',
958
+ 'feeRate',
959
+ 'minConfirms',
960
+ 'enforceMinConfirmsForChange',
961
+ 'targetWalletUnspents',
962
+ 'message',
963
+ 'minValue',
964
+ 'maxValue',
965
+ 'noSplitChange',
966
+ 'comment',
967
+ ];
968
+ const preservedBuildParams = _.pick(params, acceptedBuildParams);
969
+ // Get the user keychain
970
+ const retPromise = this.createAndSignTransaction(params)
971
+ .then(function (transaction) {
972
+ // Send the transaction
973
+ bitgoFee = transaction.bitgoFee;
974
+ travelInfos = transaction.travelInfos;
975
+ unspentsUsed = transaction.unspents;
976
+ return self.sendTransaction({
977
+ tx: transaction.tx,
978
+ message: params.message,
979
+ sequenceId: params.sequenceId,
980
+ instant: params.instant,
981
+ otp: params.otp,
982
+ // The below params are for logging only, and do not impact the API call
983
+ estimatedSize: transaction.estimatedSize,
984
+ buildParams: preservedBuildParams,
985
+ });
986
+ })
987
+ .then(function (result) {
988
+ const tx = utxolib.bitgo.createTransactionFromHex(result.tx, utxolib.networks.bitcoin);
989
+ const inputsSum = _.sumBy(unspentsUsed, 'value');
990
+ const outputsSum = _.sumBy(tx.outs, 'value');
991
+ const feeUsed = inputsSum - outputsSum;
992
+ if (isNaN(feeUsed)) {
993
+ throw new Error('invalid feeUsed');
994
+ }
995
+ (result.fee = feeUsed), (result.feeRate = (feeUsed * 1000) / tx.virtualSize());
996
+ result.travelInfos = travelInfos;
997
+ if (bitgoFee) {
998
+ result.bitgoFee = bitgoFee;
999
+ }
1000
+ finalResult = result;
1001
+ // Handle sending travel infos if they exist, but make sure we never fail here.
1002
+ // Error or result (with possible sub-errors) will be provided in travelResult
1003
+ if (travelInfos && travelInfos.length) {
1004
+ try {
1005
+ return self
1006
+ .pollForTransaction({ id: result.hash })
1007
+ .then(function () {
1008
+ return self.bitgo.travelRule().sendMany(result);
1009
+ })
1010
+ .then(function (res) {
1011
+ finalResult.travelResult = res;
1012
+ })
1013
+ .catch(function (err) {
1014
+ // catch async errors
1015
+ finalResult.travelResult = { error: err.message };
1016
+ });
1017
+ }
1018
+ catch (err) {
1019
+ // catch synchronous errors
1020
+ finalResult.travelResult = { error: err.message };
1021
+ }
1022
+ }
1023
+ })
1024
+ .then(function () {
1025
+ return finalResult;
1026
+ });
1027
+ return Bluebird.resolve(retPromise).nodeify(callback);
1028
+ };
1029
+ /**
1030
+ * Accelerate a stuck transaction using Child-Pays-For-Parent (CPFP).
1031
+ *
1032
+ * This should only be used for stuck transactions which have no unconfirmed inputs.
1033
+ *
1034
+ * @param {Object} params - Input parameters
1035
+ * @param {String} params.transactionID - ID of transaction to accelerate
1036
+ * @param {Number} params.feeRate - New effective fee rate for stuck transaction (sat per 1000 bytes)
1037
+ * @param {Number} params.maxAdditionalUnspents - Maximum additional unspents to use from the wallet to cover any child fees that the parent unspent output cannot cover. Defaults to 100.
1038
+ * @param {String} params.walletPassphrase - The passphrase which should be used to decrypt the wallet private key. One of either walletPassphrase or xprv is required.
1039
+ * @param {String} params.xprv - The private key for the wallet. One of either walletPassphrase or xprv is required.
1040
+ * @param {Function} callback
1041
+ * @returns Result of sendTransaction() on the child transaction
1042
+ */
1043
+ Wallet.prototype.accelerateTransaction = function accelerateTransaction(params, callback) {
1044
+ const self = this;
1045
+ /**
1046
+ * Helper function to estimate a transactions size in virtual bytes.
1047
+ * Actual transactions may be slightly fewer virtual bytes, due to
1048
+ * the fact that valid ECSDA signatures have a variable length
1049
+ * between 8 and 73 virtual bytes.
1050
+ *
1051
+ * @param inputs.segwit The number of segwit inputs to the transaction
1052
+ * @param inputs.P2SH The number of P2SH inputs to the transaction
1053
+ * @param inputs.P2PKH The number of P2PKH inputs to the transaction
1054
+ */
1055
+ const estimateTxVSize = (inputs) => {
1056
+ const segwit = inputs.segwit || 0;
1057
+ const P2SH = inputs.P2SH || 0;
1058
+ const P2PKH = inputs.P2PKH || 0;
1059
+ const childFeeInfo = TransactionBuilder.calculateMinerFeeInfo({
1060
+ nP2shInputs: P2SH,
1061
+ nP2pkhInputs: P2PKH,
1062
+ nP2shP2wshInputs: segwit,
1063
+ nOutputs: 1,
1064
+ feeRate: 1,
1065
+ });
1066
+ return childFeeInfo.size;
1067
+ };
1068
+ /**
1069
+ * Calculate the number of satoshis that should be paid in fees by the child transaction
1070
+ *
1071
+ * @param inputs Inputs to the child transaction which are passed to estimateTxVSize
1072
+ * @param parentFee The number of satoshis the parent tx originally paid in fees
1073
+ * @param parentVSize The number of virtual bytes in the parent tx
1074
+ * @param feeRate The new fee rate which should be paid by the combined CPFP transaction
1075
+ * @returns {number} The number of satoshis the child tx should pay in fees
1076
+ */
1077
+ const estimateChildFee = ({ inputs, parentFee, parentVSize, feeRate }) => {
1078
+ // calculate how much more we *should* have paid in parent fees,
1079
+ // had the parent been originally sent with the new fee rate
1080
+ const additionalParentFee = _.ceil((parentVSize * feeRate) / 1000) - parentFee;
1081
+ // calculate how much we would pay in fees for the child,
1082
+ // if it were only paying for itself at the new fee rate
1083
+ const childFee = (estimateTxVSize(inputs) * feeRate) / 1000;
1084
+ return _.ceil(childFee + additionalParentFee);
1085
+ };
1086
+ /**
1087
+ * Helper function to find additional unspents to use to pay the child tx fees.
1088
+ * This function is called when the the parent tx output is not sufficient to
1089
+ * cover the total fees which should be paid by the child tx.
1090
+ *
1091
+ * @param inputs Inputs to the child transaction which are passed to estimateTxVSize
1092
+ * @param parentOutputValue The value of the output from the parent tx which we are using as an input to the child tx
1093
+ * @param parentFee The number of satoshis the parent tx originally paid in fees
1094
+ * @param parentVSize The number of virtual bytes in the parent tx
1095
+ * @param maxUnspents The maximum number of additional unspents which should be used to cover the remaining child fees
1096
+ * @returns An object with the additional unspents to use, the updated number of satoshis which should be paid by
1097
+ * the child tx, and the updated inputs for the child tx.
1098
+ */
1099
+ const findAdditionalUnspents = ({ inputs, parentOutputValue, parentFee, parentVSize, maxUnspents }) => {
1100
+ return co(function* coFindAdditionalUnspents() {
1101
+ const additionalUnspents = [];
1102
+ // ask the server for enough unspents to cover the child fee, assuming
1103
+ // that it can be done without additional unspents (which is not possible,
1104
+ // since if that were the case, findAdditionalUnspents would not have been
1105
+ // called in the first place. This will be corrected before returning)
1106
+ let currentChildFeeEstimate = estimateChildFee({ inputs, parentFee, parentVSize, feeRate: params.feeRate });
1107
+ let uncoveredChildFee = currentChildFeeEstimate - parentOutputValue;
1108
+ while (uncoveredChildFee > 0 && additionalUnspents.length < maxUnspents) {
1109
+ // try to get enough unspents to cover the rest of the child fee
1110
+ // @ts-expect-error - no implicit this
1111
+ const unspents = (yield this.unspents({
1112
+ minConfirms: 1,
1113
+ target: uncoveredChildFee,
1114
+ limit: maxUnspents - additionalUnspents.length,
1115
+ }));
1116
+ if (unspents.length === 0) {
1117
+ // no more unspents are available
1118
+ break;
1119
+ }
1120
+ let additionalUnspentValue = 0;
1121
+ // consume all unspents returned by the server, even if we don't need
1122
+ // all of them to cover the child fee. This is because the server will
1123
+ // return enough unspent value to ensure that the minimum change amount
1124
+ // is achieved for the child tx, and we can't leave out those unspents
1125
+ // or else the minimum change amount constraint could be violated
1126
+ _.forEach(unspents, (unspent) => {
1127
+ // update the child tx inputs
1128
+ const unspentChain = getChain(unspent);
1129
+ if (isChainCode(unspentChain) && scriptTypeForChain(unspentChain) === 'p2shP2wsh') {
1130
+ inputs.segwit++;
1131
+ }
1132
+ else {
1133
+ inputs.P2SH++;
1134
+ }
1135
+ additionalUnspents.push(unspent);
1136
+ additionalUnspentValue += unspent.value;
1137
+ });
1138
+ currentChildFeeEstimate = estimateChildFee({ inputs, parentFee, parentVSize, feeRate: params.feeRate });
1139
+ uncoveredChildFee = currentChildFeeEstimate - parentOutputValue - additionalUnspentValue;
1140
+ }
1141
+ if (uncoveredChildFee > 0) {
1142
+ // Unable to find enough unspents to cover the child fee
1143
+ throw new Error(`Insufficient confirmed unspents available to cover the child fee`);
1144
+ }
1145
+ // found enough unspents
1146
+ return {
1147
+ additional: additionalUnspents,
1148
+ newChildFee: currentChildFeeEstimate,
1149
+ newInputs: inputs,
1150
+ };
1151
+ }).call(this);
1152
+ };
1153
+ /**
1154
+ * Helper function to get a full copy (including witness data) of an arbitrary tx using only the tx id.
1155
+ *
1156
+ * We have to use an external service for this (currently blockstream.info), since
1157
+ * the v1 indexer service (based on bitcoinj) does not have segwit support and
1158
+ * does not return any segwit related fields in the tx hex.
1159
+ *
1160
+ * @param parentTxId The ID of the transaction to get the full hex of
1161
+ * @returns {Bluebird<any>} The full hex for the specified transaction
1162
+ */
1163
+ async function getParentTxHex({ parentTxId }) {
1164
+ const explorerBaseUrl = sdk_core_1.common.Environments[self.bitgo.getEnv()].btcExplorerBaseUrl;
1165
+ const result = await request.get(`${explorerBaseUrl}/tx/${parentTxId}/hex`);
1166
+ if (!result.text || !/([a-f0-9]{2})+/.test(result.text)) {
1167
+ throw new Error(`Did not successfully receive parent tx hex. Received '${_.truncate(result.text, { length: 100 })}' instead.`);
1168
+ }
1169
+ return result.text;
1170
+ }
1171
+ /**
1172
+ * Helper function to get the chain from an unspent or tx output.
1173
+ *
1174
+ * @param outputOrUnspent The output or unspent whose chain should be determined
1175
+ * @returns {number} The chain for the given output or unspent
1176
+ */
1177
+ const getChain = (outputOrUnspent) => {
1178
+ if (outputOrUnspent.chain !== undefined) {
1179
+ return outputOrUnspent.chain;
1180
+ }
1181
+ if (outputOrUnspent.chainPath !== undefined) {
1182
+ return _.toNumber(outputOrUnspent.chainPath.split('/')[1]);
1183
+ }
1184
+ // no way to tell the chain, let's just blow up now instead
1185
+ // of blowing up later when the undefined return value is used.
1186
+ // Note: for unspents the field to use is 'address', but for outputs
1187
+ // the field to use is 'account'
1188
+ throw Error(`Could not get chain for output on account ${outputOrUnspent.account || outputOrUnspent.address}`);
1189
+ };
1190
+ /**
1191
+ * Helper function to calculate the actual value contribution an output or unspent will
1192
+ * contribute to a transaction, were it to be used. Each type of output or unspent
1193
+ * will have a different value contribution since each type has a different number
1194
+ * of virtual bytes, and thus will cause a different fee to be paid.
1195
+ *
1196
+ * @param outputOrUnspent Output or unspent whose effective value should be determined
1197
+ * @returns {number} The actual number of satoshis that this unspent or output
1198
+ * would contribute to a transaction, were it to be used.
1199
+ */
1200
+ const effectiveValue = (outputOrUnspent) => {
1201
+ const chain = getChain(outputOrUnspent);
1202
+ if (isChainCode(chain) && scriptTypeForChain(chain) === 'p2shP2wsh') {
1203
+ // VirtualSizes.txP2shP2wshInputSize is in bytes, so we need to convert to kB
1204
+ return outputOrUnspent.value - (unspents_1.VirtualSizes.txP2shP2wshInputSize * params.feeRate) / 1000;
1205
+ }
1206
+ // VirtualSizes.txP2shInputSize is in bytes, so we need to convert to kB
1207
+ return outputOrUnspent.value - (unspents_1.VirtualSizes.txP2shInputSize * params.feeRate) / 1000;
1208
+ };
1209
+ /**
1210
+ * Coroutine which actually implements the accelerateTransaction algorithm
1211
+ *
1212
+ * Described at a high level, the algorithm is as follows:
1213
+ * 1) Find appropriate output from parent transaction to use as child transaction input
1214
+ * 2) Find unspent corresponding to parent transaction output. If not found, return to step 1.
1215
+ * 3) Determine if parent transaction unspent can cover entire child fee, plus minimum change
1216
+ * 4) If yes, go to step 6
1217
+ * 5) Otherwise, find additional unspents from the wallet to use to cover the remaining child fee
1218
+ * 6) Create and sign the child transaction, using the parent transaction output
1219
+ * (and, if necessary, additional wallet unspents) as inputs
1220
+ * 7) Broadcast the new child transaction
1221
+ */
1222
+ return co(function* coAccelerateTransaction() {
1223
+ params = params || {};
1224
+ sdk_core_1.common.validateParams(params, ['transactionID'], [], callback);
1225
+ // validate fee rate
1226
+ if (params.feeRate === undefined) {
1227
+ throw new Error('Missing parameter: feeRate');
1228
+ }
1229
+ if (!_.isFinite(params.feeRate) || params.feeRate <= 0) {
1230
+ throw new Error('Expecting positive finite number for parameter: feeRate');
1231
+ }
1232
+ // validate maxUnspents
1233
+ if (params.maxAdditionalUnspents === undefined) {
1234
+ // by default, use at most 100 additional unspents (not including the unspent output from the parent tx)
1235
+ params.maxAdditionalUnspents = 100;
1236
+ }
1237
+ if (!_.isInteger(params.maxAdditionalUnspents) || params.maxAdditionalUnspents <= 0) {
1238
+ throw Error('Expecting positive integer for parameter: maxAdditionalUnspents');
1239
+ }
1240
+ // @ts-expect-error - no implicit this
1241
+ const parentTx = yield this.getTransaction({ id: params.transactionID });
1242
+ if (parentTx.confirmations > 0) {
1243
+ throw new Error(`Transaction ${params.transactionID} is already confirmed and cannot be accelerated`);
1244
+ }
1245
+ // get the outputs from the parent tx which are to our wallet
1246
+ const walletOutputs = _.filter(parentTx.outputs, (output) => output.isMine);
1247
+ if (walletOutputs.length === 0) {
1248
+ throw new Error(`Transaction ${params.transactionID} contains no outputs to this wallet, and thus cannot be accelerated`);
1249
+ }
1250
+ // use an output from the parent with largest effective value,
1251
+ // but check to make sure the output is actually unspent.
1252
+ // An output could be spent already if the output was used in a
1253
+ // child tx which itself has become stuck due to low fees and is
1254
+ // also unconfirmed.
1255
+ const sortedOutputs = _.sortBy(walletOutputs, effectiveValue);
1256
+ let parentUnspentToUse;
1257
+ let outputToUse;
1258
+ while (sortedOutputs.length > 0 && parentUnspentToUse === undefined) {
1259
+ outputToUse = sortedOutputs.pop();
1260
+ // find the unspent corresponding to this particular output
1261
+ // TODO: is there a better way to get this unspent?
1262
+ // TODO: The best we can do here is set minSize = maxSize = outputToUse.value
1263
+ // @ts-expect-error - no implicit this
1264
+ const unspentsResult = yield this.unspents({
1265
+ minSize: outputToUse.value,
1266
+ maxSize: outputToUse.value,
1267
+ });
1268
+ parentUnspentToUse = _.find(unspentsResult, (unspent) => {
1269
+ // make sure unspent belongs to the given txid
1270
+ if (unspent.tx_hash !== params.transactionID) {
1271
+ return false;
1272
+ }
1273
+ // make sure unspent has correct v_out index
1274
+ return unspent.tx_output_n === outputToUse.vout;
1275
+ });
1276
+ }
1277
+ if (parentUnspentToUse === undefined) {
1278
+ throw new Error(`Could not find unspent output from parent tx to use as child input`);
1279
+ }
1280
+ // get the full hex for the parent tx and decode it to get its vsize
1281
+ const parentTxHex = yield getParentTxHex({ parentTxId: params.transactionID });
1282
+ const decodedParent = utxolib.bitgo.createTransactionFromHex(parentTxHex, utxolib.networks.bitcoin);
1283
+ const parentVSize = decodedParent.virtualSize();
1284
+ // make sure id from decoded tx and given tx id match
1285
+ // this should catch problems emanating from the use of an external service
1286
+ // for getting the complete parent tx hex
1287
+ if (decodedParent.getId() !== params.transactionID) {
1288
+ throw new Error(`Decoded transaction id is ${decodedParent.getId()}, which does not match given txid ${params.transactionID}`);
1289
+ }
1290
+ // make sure new fee rate is greater than the parent's current fee rate
1291
+ // virtualSize is returned in vbytes, so we need to convert to kvB
1292
+ const parentRate = (1000 * parentTx.fee) / parentVSize;
1293
+ if (params.feeRate <= parentRate) {
1294
+ throw new Error(`Cannot lower fee rate! (Parent tx fee rate is ${parentRate} sat/kB, and requested fee rate was ${params.feeRate} sat/kB)`);
1295
+ }
1296
+ // determine if parent output can cover child fee
1297
+ const isParentOutputSegwit = isChainCode(outputToUse.chain) && scriptTypeForChain(outputToUse.chain) === 'p2shP2wsh';
1298
+ let childInputs = {
1299
+ segwit: isParentOutputSegwit ? 1 : 0,
1300
+ P2SH: isParentOutputSegwit ? 0 : 1,
1301
+ };
1302
+ let childFee = estimateChildFee({
1303
+ inputs: childInputs,
1304
+ parentFee: parentTx.fee,
1305
+ feeRate: params.feeRate,
1306
+ parentVSize,
1307
+ });
1308
+ const unspentsToUse = [parentUnspentToUse];
1309
+ // try to get the min change size from the server, otherwise default to 0.1 BTC
1310
+ // TODO: minChangeSize is not currently a constant defined on the client and should be added
1311
+ // @ts-expect-error - no implicit this
1312
+ const minChangeSize = this.bitgo.getConstants().minChangeSize || 1e7;
1313
+ if (outputToUse.value < childFee + minChangeSize) {
1314
+ // parent output cannot cover child fee plus the minimum change,
1315
+ // must find additional unspents to cover the difference
1316
+ const { additional, newChildFee, newInputs } = yield findAdditionalUnspents({
1317
+ inputs: childInputs,
1318
+ parentOutputValue: outputToUse.value,
1319
+ parentFee: parentTx.fee,
1320
+ maxUnspents: params.maxAdditionalUnspents,
1321
+ parentVSize,
1322
+ });
1323
+ childFee = newChildFee;
1324
+ childInputs = newInputs;
1325
+ unspentsToUse.push(...additional);
1326
+ }
1327
+ // sanity check the fee rate we're paying for the combined tx
1328
+ // to make sure it's under the max fee rate. Only the child tx
1329
+ // can break this limit, but the combined tx shall not
1330
+ // @ts-expect-error - no implicit this
1331
+ const maxFeeRate = this.bitgo.getConstants().maxFeeRate;
1332
+ const childVSize = estimateTxVSize(childInputs);
1333
+ const combinedVSize = childVSize + parentVSize;
1334
+ const combinedFee = parentTx.fee + childFee;
1335
+ // combined fee rate must be in sat/kB, so we need to convert
1336
+ const combinedFeeRate = (1000 * combinedFee) / combinedVSize;
1337
+ if (combinedFeeRate > maxFeeRate) {
1338
+ throw new Error(`Transaction cannot be accelerated. Combined fee rate of ${combinedFeeRate} sat/kB exceeds maximum fee rate of ${maxFeeRate} sat/kB`);
1339
+ }
1340
+ // create a new change address and determine change amount.
1341
+ // the tx builder will reject transactions which have no recipients,
1342
+ // and such zero-output transactions are forbidden by the Bitcoin protocol,
1343
+ // so we need at least a single recipient for the change which won't be pruned.
1344
+ const changeAmount = _.sumBy(unspentsToUse, (unspent) => unspent.value) - childFee;
1345
+ // @ts-expect-error - no implicit this
1346
+ const changeChain = this.getChangeChain({});
1347
+ // @ts-expect-error - no implicit this
1348
+ const changeAddress = yield this.createAddress({ chain: changeChain });
1349
+ // create the child tx and broadcast
1350
+ // @ts-expect-error - no implicit this
1351
+ const tx = yield this.createAndSignTransaction({
1352
+ unspents: unspentsToUse,
1353
+ recipients: [
1354
+ {
1355
+ address: changeAddress.address,
1356
+ amount: changeAmount,
1357
+ },
1358
+ ],
1359
+ fee: childFee,
1360
+ bitgoFee: {
1361
+ amount: 0,
1362
+ address: '',
1363
+ },
1364
+ xprv: params.xprv,
1365
+ walletPassphrase: params.walletPassphrase,
1366
+ });
1367
+ // child fee rate must be in sat/kB, so we need to convert
1368
+ const childFeeRate = (1000 * childFee) / childVSize;
1369
+ if (childFeeRate > maxFeeRate) {
1370
+ // combined tx is within max fee rate limits, but the child tx is not.
1371
+ // in this case, we need to use the ignoreMaxFeeRate flag to get the child tx to be accepted
1372
+ tx.ignoreMaxFeeRate = true;
1373
+ }
1374
+ // @ts-expect-error - no implicit this
1375
+ return this.sendTransaction(tx);
1376
+ })
1377
+ .call(this)
1378
+ .asCallback(callback);
1379
+ };
1380
+ //
1381
+ // createAndSignTransaction
1382
+ // INTERNAL function to create and sign a transaction
1383
+ //
1384
+ // Parameters:
1385
+ // recipients - array of { address, amount } to send to
1386
+ // walletPassphrase - the passphrase to be used to decrypt the user key on this wallet
1387
+ // (See transactionBuilder.createTransaction for other passthrough params)
1388
+ // Returns:
1389
+ //
1390
+ Wallet.prototype.createAndSignTransaction = function (params, callback) {
1391
+ return co(function* () {
1392
+ params = params || {};
1393
+ sdk_core_1.common.validateParams(params, [], [], callback);
1394
+ if (!_.isObject(params.recipients)) {
1395
+ throw new Error('expecting recipients object');
1396
+ }
1397
+ if (params.fee && !_.isNumber(params.fee)) {
1398
+ throw new Error('invalid argument for fee - number expected');
1399
+ }
1400
+ if (params.feeRate && !_.isNumber(params.feeRate)) {
1401
+ throw new Error('invalid argument for feeRate - number expected');
1402
+ }
1403
+ if (params.dynamicFeeConfirmTarget && !_.isNumber(params.dynamicFeeConfirmTarget)) {
1404
+ throw new Error('invalid argument for confirmTarget - number expected');
1405
+ }
1406
+ if (params.instant && !_.isBoolean(params.instant)) {
1407
+ throw new Error('invalid argument for instant - boolean expected');
1408
+ }
1409
+ // @ts-expect-error - no implicit this
1410
+ const transaction = (yield this.createTransaction(params));
1411
+ const fee = transaction.fee;
1412
+ const feeRate = transaction.feeRate;
1413
+ const estimatedSize = transaction.estimatedSize;
1414
+ const bitgoFee = transaction.bitgoFee;
1415
+ const travelInfos = transaction.travelInfos;
1416
+ const unspents = transaction.unspents;
1417
+ // Sign the transaction
1418
+ try {
1419
+ // @ts-expect-error - no implicit this
1420
+ const keychain = yield this.getAndPrepareSigningKeychain(params);
1421
+ transaction.keychain = keychain;
1422
+ }
1423
+ catch (e) {
1424
+ if (e.code !== 'no_encrypted_keychain_on_wallet') {
1425
+ throw e;
1426
+ }
1427
+ // this might be a safe wallet, so let's retrieve the private key info
1428
+ // @ts-expect-error - no implicit this
1429
+ yield this.refresh({ gpk: true });
1430
+ // @ts-expect-error - no implicit this
1431
+ const safeUserKey = _.get(this.wallet, 'private.userPrivKey');
1432
+ if (_.isString(safeUserKey) && _.isString(params.walletPassphrase)) {
1433
+ // @ts-expect-error - no implicit this
1434
+ transaction.signingKey = this.bitgo.decrypt({ password: params.walletPassphrase, input: safeUserKey });
1435
+ }
1436
+ else {
1437
+ throw e;
1438
+ }
1439
+ }
1440
+ transaction.feeSingleKeyWIF = params.feeSingleKeyWIF;
1441
+ // @ts-expect-error - no implicit this
1442
+ const result = yield this.signTransaction(transaction);
1443
+ return _.extend(result, {
1444
+ fee,
1445
+ feeRate,
1446
+ instant: params.instant,
1447
+ bitgoFee,
1448
+ travelInfos,
1449
+ estimatedSize,
1450
+ unspents,
1451
+ });
1452
+ })
1453
+ .call(this)
1454
+ .asCallback(callback);
1455
+ };
1456
+ //
1457
+ // getAndPrepareSigningKeychain
1458
+ // INTERNAL function to get the user keychain for signing.
1459
+ // Caller must provider either a keychain, or walletPassphrase or xprv as a string
1460
+ // If the caller provides the keychain with xprv, it is simply returned.
1461
+ // If the caller provides the encrypted xprv (walletPassphrase), then fetch the keychain object and decrypt
1462
+ // Otherwise if the xprv is provided, fetch the keychain object and augment it with the xprv.
1463
+ //
1464
+ // Parameters:
1465
+ // keychain - keychain with xprv
1466
+ // xprv - the private key in string form
1467
+ // walletPassphrase - the passphrase to be used to decrypt the user key on this wallet
1468
+ // Returns:
1469
+ // Keychain object containing xprv, xpub and paths
1470
+ //
1471
+ Wallet.prototype.getAndPrepareSigningKeychain = function (params, callback) {
1472
+ params = params || {};
1473
+ // If keychain with xprv is already provided, use it
1474
+ if (_.isObject(params.keychain) && params.keychain.xprv) {
1475
+ return Bluebird.resolve(params.keychain);
1476
+ }
1477
+ sdk_core_1.common.validateParams(params, [], ['walletPassphrase', 'xprv'], callback);
1478
+ if ((params.walletPassphrase && params.xprv) || (!params.walletPassphrase && !params.xprv)) {
1479
+ throw new Error('must provide exactly one of xprv or walletPassphrase');
1480
+ }
1481
+ const self = this;
1482
+ // Caller provided a wallet passphrase
1483
+ if (params.walletPassphrase) {
1484
+ return self.getEncryptedUserKeychain().then(function (keychain) {
1485
+ // Decrypt the user key with a passphrase
1486
+ try {
1487
+ keychain.xprv = self.bitgo.decrypt({ password: params.walletPassphrase, input: keychain.encryptedXprv });
1488
+ }
1489
+ catch (e) {
1490
+ throw new Error('Unable to decrypt user keychain');
1491
+ }
1492
+ return keychain;
1493
+ });
1494
+ }
1495
+ // Caller provided an xprv - validate and construct keychain object
1496
+ let xpub;
1497
+ try {
1498
+ xpub = utxo_lib_1.bip32.fromBase58(params.xprv).neutered().toBase58();
1499
+ }
1500
+ catch (e) {
1501
+ throw new Error('Unable to parse the xprv');
1502
+ }
1503
+ if (xpub === params.xprv) {
1504
+ throw new Error('xprv provided was not a private key (found xpub instead)');
1505
+ }
1506
+ const walletXpubs = _.map(self.keychains, 'xpub');
1507
+ if (!_.includes(walletXpubs, xpub)) {
1508
+ throw new Error('xprv provided was not a keychain on this wallet!');
1509
+ }
1510
+ // get the keychain object from bitgo to find the path and (potential) wallet structure
1511
+ return self.bitgo
1512
+ .keychains()
1513
+ .get({ xpub: xpub })
1514
+ .then(function (keychain) {
1515
+ keychain.xprv = params.xprv;
1516
+ return keychain;
1517
+ });
1518
+ };
1519
+ /**
1520
+ * Takes a wallet's unspents and fans them out into a larger number of equally sized unspents
1521
+ * @param params
1522
+ * target: set how many unspents you want to have in the end
1523
+ * minConfirms: minimum number of confirms the unspents must have
1524
+ * xprv: private key to sign transaction
1525
+ * walletPassphrase: wallet passphrase to decrypt the wallet's private key
1526
+ * @param callback
1527
+ * @returns {*}
1528
+ */
1529
+ Wallet.prototype.fanOutUnspents = function (params, callback) {
1530
+ const self = this;
1531
+ return Bluebird.coroutine(function* () {
1532
+ // maximum number of inputs for fanout transaction
1533
+ // (when fanning out, we take all the unspents and make a bigger number of outputs)
1534
+ const MAX_FANOUT_INPUT_COUNT = 80;
1535
+ // maximum number of outputs for fanout transaction
1536
+ const MAX_FANOUT_OUTPUT_COUNT = 300;
1537
+ params = params || {};
1538
+ sdk_core_1.common.validateParams(params, [], ['walletPassphrase', 'xprv'], callback);
1539
+ const validate = params.validate === undefined ? true : params.validate;
1540
+ const target = params.target;
1541
+ // the target must be defined, be a number, be at least two, and be a natural number
1542
+ if (!_.isNumber(target) || target < 2 || target % 1 !== 0) {
1543
+ throw new Error('Target needs to be a positive integer');
1544
+ }
1545
+ if (target > MAX_FANOUT_OUTPUT_COUNT) {
1546
+ throw new Error('Fan out target too high');
1547
+ }
1548
+ let minConfirms = params.minConfirms;
1549
+ if (minConfirms === undefined) {
1550
+ minConfirms = 1;
1551
+ }
1552
+ if (!_.isNumber(minConfirms) || minConfirms < 0) {
1553
+ throw new Error('minConfirms needs to be an integer >= 0');
1554
+ }
1555
+ /**
1556
+ * Split a natural number N into n almost equally sized (±1) natural numbers.
1557
+ * In order to calculate the sizes of the parts, we calculate floor(N/n), and thus have the base size of all parts.
1558
+ * If N % n !== 0, this leaves us with a remainder r where r < n. We distribute r equally among the n parts by
1559
+ * adding 1 to the first r parts.
1560
+ * @param total
1561
+ * @param partCount
1562
+ * @returns {Array}
1563
+ */
1564
+ const splitNumberIntoCloseNaturalNumbers = function (total, partCount) {
1565
+ const partSize = Math.floor(total / partCount);
1566
+ const remainder = total - partSize * partCount;
1567
+ // initialize placeholder array
1568
+ const almostEqualParts = new Array(partCount);
1569
+ // fill the first remainder parts with the value partSize+1
1570
+ _.fill(almostEqualParts, partSize + 1, 0, remainder);
1571
+ // fill the remaining parts with the value partSize
1572
+ _.fill(almostEqualParts, partSize, remainder);
1573
+ // assert the correctness of the almost equal parts
1574
+ // TODO: add check for the biggest deviation between any two parts and make sure it's <= 1
1575
+ if (_(almostEqualParts).sum() !== total || _(almostEqualParts).size() !== partCount) {
1576
+ throw new Error('part sum or part count mismatch');
1577
+ }
1578
+ return almostEqualParts;
1579
+ };
1580
+ // first, let's take all the wallet's unspents (with min confirms if necessary)
1581
+ const allUnspents = (yield self.unspents({ minConfirms: minConfirms }));
1582
+ if (allUnspents.length < 1) {
1583
+ throw new Error('No unspents to branch out');
1584
+ }
1585
+ // this consolidation is essentially just a waste of money
1586
+ if (allUnspents.length >= target) {
1587
+ throw new Error('Fan out target has to be bigger than current number of unspents');
1588
+ }
1589
+ // we have at the very minimum 81 inputs, and 81 outputs. That transaction will be big
1590
+ // in the medium run, this algorithm could be reworked to only work with a subset of the transactions
1591
+ if (allUnspents.length > MAX_FANOUT_INPUT_COUNT) {
1592
+ throw new Error('Too many unspents');
1593
+ }
1594
+ // this is all the money that is currently in the wallet
1595
+ const grossAmount = _(allUnspents).map('value').sum();
1596
+ // in order to not modify the params object, we create a copy
1597
+ const txParams = _.extend({}, params);
1598
+ txParams.unspents = allUnspents;
1599
+ txParams.recipients = {};
1600
+ // create target amount of new addresses for this wallet
1601
+ const newAddressPromises = _.range(target).map(() => self.createAddress({ chain: self.getChangeChain(params), validate: validate }));
1602
+ const newAddresses = yield Bluebird.all(newAddressPromises);
1603
+ // let's find a nice, equal distribution of our Satoshis among the new addresses
1604
+ const splitAmounts = splitNumberIntoCloseNaturalNumbers(grossAmount, target);
1605
+ // map the newly created addresses to the almost components amounts we just calculated
1606
+ txParams.recipients = _.zipObject(_.map(newAddresses, 'address'), splitAmounts);
1607
+ txParams.noSplitChange = true;
1608
+ // attempt to create a transaction. As it is a wallet-sweeping transaction with no fee, we expect it to fail
1609
+ try {
1610
+ yield self.sendMany(txParams);
1611
+ }
1612
+ catch (error) {
1613
+ // as expected, the transaction creation did indeed fail due to insufficient fees
1614
+ // the error suggests a fee value which we then use for the transaction
1615
+ // however, let's make sure it wasn't something else
1616
+ if (!error.fee && (!error.result || !error.result.fee)) {
1617
+ // if the error does not contain a fee property, it is something else that has gone awry, and we throw it
1618
+ const debugParams = _.omit(txParams, ['walletPassphrase', 'xprv']);
1619
+ error.message += `\n\nTX PARAMS:\n ${JSON.stringify(debugParams, null, 4)}`;
1620
+ throw error;
1621
+ }
1622
+ const baseFee = error.fee || error.result.fee;
1623
+ let totalFee = baseFee;
1624
+ if (error.result.bitgoFee && error.result.bitgoFee.amount) {
1625
+ totalFee += error.result.bitgoFee.amount;
1626
+ txParams.bitgoFee = error.result.bitgoFee;
1627
+ }
1628
+ // Need to clear these out since only 1 may be set
1629
+ delete txParams.fee;
1630
+ txParams.originalFeeRate = txParams.feeRate;
1631
+ delete txParams.feeRate;
1632
+ delete txParams.feeTxConfirmTarget;
1633
+ txParams.fee = baseFee;
1634
+ // in order to maintain the equal distribution, we need to subtract the fee from the cumulative funds
1635
+ // in case some unspents got pruned, we need to use error.result.available
1636
+ const netAmount = error.result.available - totalFee; // after fees
1637
+ // that means that the distribution has to be recalculated
1638
+ const remainingSplitAmounts = splitNumberIntoCloseNaturalNumbers(netAmount, target);
1639
+ // and the distribution again mapped to the new addresses
1640
+ txParams.recipients = _.zipObject(_.map(newAddresses, 'address'), remainingSplitAmounts);
1641
+ }
1642
+ // this time, the transaction creation should work
1643
+ let fanoutTx;
1644
+ try {
1645
+ fanoutTx = yield self.sendMany(txParams);
1646
+ }
1647
+ catch (e) {
1648
+ const debugParams = _.omit(txParams, ['walletPassphrase', 'xprv']);
1649
+ e.message += `\n\nTX PARAMS:\n ${JSON.stringify(debugParams, null, 4)}`;
1650
+ throw e;
1651
+ }
1652
+ return Bluebird.resolve(fanoutTx).asCallback(callback);
1653
+ })().asCallback(callback);
1654
+ };
1655
+ /**
1656
+ * Determine whether to fan out or coalesce a wallet's unspents
1657
+ * @param params
1658
+ * @param callback
1659
+ * @returns {Request|Promise.<T>|*}
1660
+ */
1661
+ Wallet.prototype.regroupUnspents = function (params, callback) {
1662
+ params = params || {};
1663
+ const target = params.target;
1664
+ if (!_.isNumber(target) || target < 1 || target % 1 !== 0) {
1665
+ // the target must be defined, be a number, be at least one, and be a natural number
1666
+ throw new Error('Target needs to be a positive integer');
1667
+ }
1668
+ let minConfirms = params.minConfirms;
1669
+ if (minConfirms === undefined) {
1670
+ minConfirms = 1;
1671
+ }
1672
+ if (!_.isNumber(minConfirms) || minConfirms < 0) {
1673
+ throw new Error('minConfirms needs to be an integer equal to or bigger than 0');
1674
+ }
1675
+ const self = this;
1676
+ return self.unspents({ minConfirms: minConfirms }).then(function (unspents) {
1677
+ if (unspents.length === target) {
1678
+ return unspents;
1679
+ }
1680
+ else if (unspents.length > target) {
1681
+ return self.consolidateUnspents(params, callback);
1682
+ }
1683
+ else if (unspents.length < target) {
1684
+ return self.fanOutUnspents(params, callback);
1685
+ }
1686
+ });
1687
+ };
1688
+ /**
1689
+ * Consolidate a wallet's unspents into fewer unspents
1690
+ * @param params
1691
+ * target: set how many unspents you want to have in the end
1692
+ * maxInputCountPerConsolidation: set how many maximum inputs are to be permitted per consolidation batch
1693
+ * xprv: private key to sign transaction
1694
+ * walletPassphrase: wallet passphrase to decrypt the wallet's private key
1695
+ * maxIterationCount: maximum number of iterations to be performed until function stops
1696
+ * progressCallback: method to be called with object outlining current progress details
1697
+ * @param callback
1698
+ * @returns {*}
1699
+ */
1700
+ Wallet.prototype.consolidateUnspents = function (params, callback) {
1701
+ params = params || {};
1702
+ sdk_core_1.common.validateParams(params, [], ['walletPassphrase', 'xprv'], callback);
1703
+ const validate = params.validate === undefined ? true : params.validate;
1704
+ let target = params.target;
1705
+ if (target === undefined) {
1706
+ target = 1;
1707
+ }
1708
+ else if (!_.isNumber(target) || target < 1 || target % 1 !== 0) {
1709
+ // the target must be defined, be a number, be at least one, and be a natural number
1710
+ throw new Error('Target needs to be a positive integer');
1711
+ }
1712
+ if (params.maxSize && !_.isNumber(params.maxSize)) {
1713
+ throw new Error('maxSize should be a number');
1714
+ }
1715
+ if (params.minSize && !_.isNumber(params.minSize)) {
1716
+ throw new Error('minSize should be a number');
1717
+ }
1718
+ // maximum number of inputs per transaction for consolidation
1719
+ const MAX_INPUT_COUNT = 200;
1720
+ let maxInputCount = params.maxInputCountPerConsolidation;
1721
+ if (maxInputCount === undefined) {
1722
+ // null or unidentified, because equality to zero returns true in if(! clause
1723
+ maxInputCount = MAX_INPUT_COUNT;
1724
+ }
1725
+ if (typeof maxInputCount !== 'number' || maxInputCount < 2 || maxInputCount % 1 !== 0) {
1726
+ throw new Error('Maximum consolidation input count needs to be an integer equal to or bigger than 2');
1727
+ }
1728
+ else if (maxInputCount > MAX_INPUT_COUNT) {
1729
+ throw new Error('Maximum consolidation input count cannot be bigger than ' + MAX_INPUT_COUNT);
1730
+ }
1731
+ const maxIterationCount = params.maxIterationCount || -1;
1732
+ if ((params.maxIterationCount && (!_.isNumber(maxIterationCount) || maxIterationCount < 1)) ||
1733
+ maxIterationCount % 1 !== 0) {
1734
+ throw new Error('Maximum iteration count needs to be an integer equal to or bigger than 1');
1735
+ }
1736
+ let minConfirms = params.minConfirms;
1737
+ if (minConfirms === undefined) {
1738
+ minConfirms = 1;
1739
+ }
1740
+ if (!_.isNumber(minConfirms) || minConfirms < 0) {
1741
+ throw new Error('minConfirms needs to be an integer equal to or bigger than 0');
1742
+ }
1743
+ let minSize = params.minSize || 0;
1744
+ if (params.feeRate) {
1745
+ // fee rate is in satoshis per kB, input size in bytes
1746
+ const feeBasedMinSize = Math.ceil((unspents_1.VirtualSizes.txP2shInputSize * params.feeRate) / 1000);
1747
+ if (params.minSize && minSize < feeBasedMinSize) {
1748
+ throw new Error('provided minSize too low due to too high fee rate');
1749
+ }
1750
+ minSize = Math.max(feeBasedMinSize, minSize);
1751
+ if (!params.minSize) {
1752
+ // fee rate-based min size needs no logging if it was set explicitly
1753
+ console.log('Only consolidating unspents larger than ' +
1754
+ minSize +
1755
+ ' satoshis to avoid wasting money on fees. To consolidate smaller unspents, use a lower fee rate.');
1756
+ }
1757
+ }
1758
+ let iterationCount = 0;
1759
+ const self = this;
1760
+ let consolidationIndex = 0;
1761
+ /**
1762
+ * Consolidate one batch of up to MAX_INPUT_COUNT unspents.
1763
+ * @returns {*}
1764
+ */
1765
+ const runNextConsolidation = co(function* () {
1766
+ const consolidationTransactions = [];
1767
+ let isFinalConsolidation = false;
1768
+ iterationCount++;
1769
+ /*
1770
+ We take a maximum of unspentBulkSizeLimit unspents from the wallet. We want to make sure that we swipe the wallet
1771
+ clean of all excessive unspents, so we add 1 to the target unspent count to make sure we haven't missed anything.
1772
+ In case there are even more unspents than that, to make the consolidation as fast as possible, we expand our
1773
+ selection to include as many as the maximum permissible number of inputs per consolidation batch.
1774
+ Should the target number of unspents be higher than the maximum number if inputs per consolidation,
1775
+ we still want to fetch them all simply to be able to determine whether or not a consolidation can be performed
1776
+ at all, which is dependent on the number of all unspents being higher than the target.
1777
+ In the next version of the unspents version SDK, we will know the total number of unspents without having to fetch
1778
+ them, and therefore will be able to simplify this method.
1779
+ */
1780
+ const queryParams = {
1781
+ limit: target + maxInputCount,
1782
+ minConfirms: minConfirms,
1783
+ minSize: minSize,
1784
+ };
1785
+ if (params.maxSize) {
1786
+ queryParams.maxSize = params.maxSize;
1787
+ }
1788
+ const allUnspents = (yield self.unspents(queryParams));
1789
+ // this consolidation is essentially just a waste of money
1790
+ if (allUnspents.length <= target) {
1791
+ if (iterationCount <= 1) {
1792
+ // this is the first iteration, so the method is incorrect
1793
+ throw new Error('Fewer unspents than consolidation target. Use fanOutUnspents instead.');
1794
+ }
1795
+ else {
1796
+ // it's a later iteration, so the target may have been surpassed (due to confirmations in the background)
1797
+ throw new Error('Done');
1798
+ }
1799
+ }
1800
+ const allUnspentsCount = allUnspents.length;
1801
+ // how many of the unspents do we want to consolidate?
1802
+ // the +1 is because the consolidated block becomes a new unspent later
1803
+ let targetInputCount = allUnspentsCount - target + 1;
1804
+ targetInputCount = Math.min(targetInputCount, allUnspents.length);
1805
+ // if the targetInputCount requires more inputs than we allow per batch, we reduce the number
1806
+ const inputCount = Math.min(targetInputCount, maxInputCount);
1807
+ // if either the number of inputs left to coalesce equals the number we will coalesce in this iteration
1808
+ // or if the number of iterations matches the maximum permitted number
1809
+ isFinalConsolidation = inputCount === targetInputCount || iterationCount === maxIterationCount;
1810
+ const currentChunk = allUnspents.splice(0, inputCount);
1811
+ const changeChain = self.getChangeChain(params);
1812
+ const newAddress = (yield self.createAddress({ chain: changeChain, validate: validate }));
1813
+ const txParams = _.extend({}, params);
1814
+ const currentAddress = newAddress;
1815
+ // the total amount that we are consolidating within this batch
1816
+ const grossAmount = _(currentChunk).map('value').sum(); // before fees
1817
+ txParams.unspents = currentChunk;
1818
+ txParams.recipients = {};
1819
+ txParams.recipients[newAddress.address] = grossAmount;
1820
+ txParams.noSplitChange = true;
1821
+ if (txParams.unspents.length <= 1) {
1822
+ throw new Error('Done');
1823
+ }
1824
+ // let's attempt to create this transaction. We expect it to fail because no fee is set.
1825
+ try {
1826
+ yield self.sendMany(txParams);
1827
+ }
1828
+ catch (error) {
1829
+ // this error should occur due to insufficient funds
1830
+ // however, let's make sure it wasn't something else
1831
+ if (!error.fee && (!error.result || !error.result.fee)) {
1832
+ // if the error does not contain a fee property, it is something else that has gone awry, and we throw it
1833
+ const debugParams = _.omit(txParams, ['walletPassphrase', 'xprv']);
1834
+ error.message += `\n\nTX PARAMS:\n ${JSON.stringify(debugParams, null, 4)}`;
1835
+ throw error;
1836
+ }
1837
+ const baseFee = error.fee || error.result.fee;
1838
+ let bitgoFee = 0;
1839
+ let totalFee = baseFee;
1840
+ if (error.result.bitgoFee && error.result.bitgoFee.amount) {
1841
+ bitgoFee = error.result.bitgoFee.amount;
1842
+ totalFee += bitgoFee;
1843
+ txParams.bitgoFee = error.result.bitgoFee;
1844
+ }
1845
+ // if the net amount is negative, it should be replaced with the minimum output size
1846
+ const netAmount = Math.max(error.result.available - totalFee, self.bitgo.getConstants().minOutputSize);
1847
+ // Need to clear these out since only 1 may be set
1848
+ delete txParams.fee;
1849
+ txParams.originalFeeRate = txParams.feeRate;
1850
+ delete txParams.feeRate;
1851
+ delete txParams.feeTxConfirmTarget;
1852
+ // we set the fee explicitly
1853
+ txParams.fee = error.result.available - netAmount - bitgoFee;
1854
+ txParams.recipients[newAddress.address] = netAmount;
1855
+ }
1856
+ // this transaction, on the other hand, should be created with no issues, because an appropriate fee is set
1857
+ let sentTx;
1858
+ try {
1859
+ sentTx = yield self.sendMany(txParams);
1860
+ }
1861
+ catch (e) {
1862
+ const debugParams = _.omit(txParams, ['walletPassphrase', 'xprv']);
1863
+ e.message += `\n\nTX PARAMS:\n ${JSON.stringify(debugParams, null, 4)}`;
1864
+ throw e;
1865
+ }
1866
+ consolidationTransactions.push(sentTx);
1867
+ if (_.isFunction(params.progressCallback)) {
1868
+ params.progressCallback({
1869
+ txid: sentTx.hash,
1870
+ destination: currentAddress,
1871
+ amount: grossAmount,
1872
+ fee: sentTx.fee,
1873
+ inputCount: inputCount,
1874
+ index: consolidationIndex,
1875
+ });
1876
+ }
1877
+ consolidationIndex++;
1878
+ if (!isFinalConsolidation) {
1879
+ // this last consolidation has not yet brought the unspents count down to the target unspent count
1880
+ // therefore, we proceed by consolidating yet another batch
1881
+ // before we do that, we wait 1 second so that the newly created unspent will be fetched in the next batch
1882
+ yield Bluebird.delay(1000);
1883
+ consolidationTransactions.push(...(yield runNextConsolidation()));
1884
+ }
1885
+ // this is the final consolidation transaction. We return all the ones we've had so far
1886
+ return consolidationTransactions;
1887
+ });
1888
+ return runNextConsolidation(this, target)
1889
+ .catch(function (err) {
1890
+ if (err.message === 'Done') {
1891
+ return;
1892
+ }
1893
+ throw err;
1894
+ })
1895
+ .nodeify(callback);
1896
+ };
1897
+ Wallet.prototype.shareWallet = function (params, callback) {
1898
+ params = params || {};
1899
+ sdk_core_1.common.validateParams(params, ['email', 'permissions'], ['walletPassphrase', 'message'], callback);
1900
+ if (params.reshare !== undefined && !_.isBoolean(params.reshare)) {
1901
+ throw new Error('Expected reshare to be a boolean.');
1902
+ }
1903
+ if (params.skipKeychain !== undefined && !_.isBoolean(params.skipKeychain)) {
1904
+ throw new Error('Expected skipKeychain to be a boolean. ');
1905
+ }
1906
+ const needsKeychain = !params.skipKeychain && params.permissions.indexOf('spend') !== -1;
1907
+ if (params.disableEmail !== undefined && !_.isBoolean(params.disableEmail)) {
1908
+ throw new Error('Expected disableEmail to be a boolean.');
1909
+ }
1910
+ const self = this;
1911
+ let sharing;
1912
+ let sharedKeychain;
1913
+ return this.bitgo
1914
+ .getSharingKey({ email: params.email.toLowerCase() })
1915
+ .then(function (result) {
1916
+ sharing = result;
1917
+ if (needsKeychain) {
1918
+ return self.getEncryptedUserKeychain({}).then(function (keychain) {
1919
+ // Decrypt the user key with a passphrase
1920
+ if (keychain.encryptedXprv) {
1921
+ if (!params.walletPassphrase) {
1922
+ throw new Error('Missing walletPassphrase argument');
1923
+ }
1924
+ try {
1925
+ keychain.xprv = self.bitgo.decrypt({ password: params.walletPassphrase, input: keychain.encryptedXprv });
1926
+ }
1927
+ catch (e) {
1928
+ throw new Error('Unable to decrypt user keychain');
1929
+ }
1930
+ const eckey = sdk_core_1.makeRandomKey();
1931
+ const secret = sdk_core_1.getSharedSecret(eckey, Buffer.from(sharing.pubkey, 'hex')).toString('hex');
1932
+ const newEncryptedXprv = self.bitgo.encrypt({ password: secret, input: keychain.xprv });
1933
+ sharedKeychain = {
1934
+ xpub: keychain.xpub,
1935
+ encryptedXprv: newEncryptedXprv,
1936
+ fromPubKey: eckey.publicKey.toString('hex'),
1937
+ toPubKey: sharing.pubkey,
1938
+ path: sharing.path,
1939
+ };
1940
+ }
1941
+ });
1942
+ }
1943
+ })
1944
+ .then(function () {
1945
+ const options = {
1946
+ user: sharing.userId,
1947
+ permissions: params.permissions,
1948
+ reshare: params.reshare,
1949
+ message: params.message,
1950
+ disableEmail: params.disableEmail,
1951
+ };
1952
+ if (sharedKeychain) {
1953
+ options.keychain = sharedKeychain;
1954
+ }
1955
+ else if (params.skipKeychain) {
1956
+ options.keychain = {};
1957
+ }
1958
+ return self.createShare(options);
1959
+ })
1960
+ .nodeify(callback);
1961
+ };
1962
+ Wallet.prototype.removeUser = function (params, callback) {
1963
+ params = params || {};
1964
+ sdk_core_1.common.validateParams(params, ['user'], [], callback);
1965
+ return Bluebird.resolve(this.bitgo
1966
+ .del(this.url('/user/' + params.user))
1967
+ .send()
1968
+ .result()).nodeify(callback);
1969
+ };
1970
+ Wallet.prototype.getPolicy = function (params, callback) {
1971
+ params = params || {};
1972
+ sdk_core_1.common.validateParams(params, [], [], callback);
1973
+ return Bluebird.resolve(this.bitgo.get(this.url('/policy')).send().result()).nodeify(callback);
1974
+ };
1975
+ Wallet.prototype.getPolicyStatus = function (params, callback) {
1976
+ params = params || {};
1977
+ sdk_core_1.common.validateParams(params, [], [], callback);
1978
+ return Bluebird.resolve(this.bitgo.get(this.url('/policy/status')).send().result()).nodeify(callback);
1979
+ };
1980
+ Wallet.prototype.setPolicyRule = function (params, callback) {
1981
+ params = params || {};
1982
+ sdk_core_1.common.validateParams(params, ['id', 'type'], ['message'], callback);
1983
+ if (!_.isObject(params.condition)) {
1984
+ throw new Error('missing parameter: conditions object');
1985
+ }
1986
+ if (!_.isObject(params.action)) {
1987
+ throw new Error('missing parameter: action object');
1988
+ }
1989
+ return Bluebird.resolve(this.bitgo.put(this.url('/policy/rule')).send(params).result()).nodeify(callback);
1990
+ };
1991
+ Wallet.prototype.removePolicyRule = function (params, callback) {
1992
+ params = params || {};
1993
+ sdk_core_1.common.validateParams(params, ['id'], ['message'], callback);
1994
+ return Bluebird.resolve(this.bitgo.del(this.url('/policy/rule')).send(params).result()).nodeify(callback);
1995
+ };
1996
+ Wallet.prototype.listWebhooks = function (params, callback) {
1997
+ params = params || {};
1998
+ sdk_core_1.common.validateParams(params, [], [], callback);
1999
+ return Bluebird.resolve(this.bitgo.get(this.url('/webhooks')).send().result()).nodeify(callback);
2000
+ };
2001
+ /**
2002
+ * Simulate wallet webhook, currently for webhooks of type transaction and pending approval
2003
+ * @param params
2004
+ * - webhookId (required): id of the webhook to be simulated
2005
+ * - txHash (optional but required for transaction webhooks) hash of the simulated transaction
2006
+ * - pendingApprovalId (optional but required for pending approval webhooks) id of the simulated pending approval
2007
+ * @param callback
2008
+ * @returns {*}
2009
+ */
2010
+ Wallet.prototype.simulateWebhook = function (params, callback) {
2011
+ params = params || {};
2012
+ sdk_core_1.common.validateParams(params, ['webhookId'], ['txHash', 'pendingApprovalId'], callback);
2013
+ const hasTxHash = !!params.txHash;
2014
+ const hasPendingApprovalId = !!params.pendingApprovalId;
2015
+ if ((hasTxHash && hasPendingApprovalId) || (!hasTxHash && !hasPendingApprovalId)) {
2016
+ throw new Error('must supply either txHash or pendingApprovalId, but not both');
2017
+ }
2018
+ // depending on the coin type of the wallet, the txHash has to adhere to its respective format
2019
+ // but the server takes care of that
2020
+ // only take the txHash and pendingApprovalId properties
2021
+ const filteredParams = _.pick(params, ['txHash', 'pendingApprovalId']);
2022
+ const webhookId = params.webhookId;
2023
+ return Bluebird.resolve(this.bitgo
2024
+ .post(this.url('/webhooks/' + webhookId + '/simulate'))
2025
+ .send(filteredParams)
2026
+ .result()).nodeify(callback);
2027
+ };
2028
+ Wallet.prototype.addWebhook = function (params, callback) {
2029
+ params = params || {};
2030
+ sdk_core_1.common.validateParams(params, ['url', 'type'], [], callback);
2031
+ return Bluebird.resolve(this.bitgo.post(this.url('/webhooks')).send(params).result()).nodeify(callback);
2032
+ };
2033
+ Wallet.prototype.removeWebhook = function (params, callback) {
2034
+ params = params || {};
2035
+ sdk_core_1.common.validateParams(params, ['url', 'type'], [], callback);
2036
+ return Bluebird.resolve(this.bitgo.del(this.url('/webhooks')).send(params).result()).nodeify(callback);
2037
+ };
2038
+ Wallet.prototype.estimateFee = function (params, callback) {
2039
+ sdk_core_1.common.validateParams(params, [], [], callback);
2040
+ if (params.amount && params.recipients) {
2041
+ throw new Error('cannot specify both amount as well as recipients');
2042
+ }
2043
+ if (params.recipients && !_.isObject(params.recipients)) {
2044
+ throw new Error('recipients must be array of { address: abc, amount: 100000 } objects');
2045
+ }
2046
+ if (params.amount && !_.isNumber(params.amount)) {
2047
+ throw new Error('invalid amount argument, expecting number');
2048
+ }
2049
+ const recipients = params.recipients || [];
2050
+ if (params.amount) {
2051
+ // only the amount was passed in, so we need to make a false recipient to run createTransaction with
2052
+ recipients.push({
2053
+ address: sdk_core_1.common.Environments[this.bitgo.env].signingAddress,
2054
+ amount: params.amount,
2055
+ });
2056
+ }
2057
+ const transactionParams = _.extend({}, params);
2058
+ transactionParams.amount = undefined;
2059
+ transactionParams.recipients = recipients;
2060
+ return this.createTransaction(transactionParams).then(function (tx) {
2061
+ return {
2062
+ estimatedSize: tx.estimatedSize,
2063
+ fee: tx.fee,
2064
+ feeRate: tx.feeRate,
2065
+ };
2066
+ });
2067
+ };
2068
+ // Not fully implemented / released on SDK. Testing for now.
2069
+ Wallet.prototype.updatePolicyRule = function (params, callback) {
2070
+ params = params || {};
2071
+ sdk_core_1.common.validateParams(params, ['id', 'type'], [], callback);
2072
+ return Bluebird.resolve(this.bitgo.put(this.url('/policy/rule')).send(params).result()).nodeify(callback);
2073
+ };
2074
+ Wallet.prototype.deletePolicyRule = function (params, callback) {
2075
+ params = params || {};
2076
+ sdk_core_1.common.validateParams(params, ['id'], [], callback);
2077
+ return Bluebird.resolve(this.bitgo.del(this.url('/policy/rule')).send(params).result()).nodeify(callback);
2078
+ };
2079
+ //
2080
+ // getBitGoFee
2081
+ // Get the required on-transaction BitGo fee
2082
+ //
2083
+ Wallet.prototype.getBitGoFee = function (params, callback) {
2084
+ params = params || {};
2085
+ sdk_core_1.common.validateParams(params, [], [], callback);
2086
+ if (!_.isNumber(params.amount)) {
2087
+ throw new Error('invalid amount argument');
2088
+ }
2089
+ if (params.instant && !_.isBoolean(params.instant)) {
2090
+ throw new Error('invalid instant argument');
2091
+ }
2092
+ return Bluebird.resolve(this.bitgo.get(this.url('/billing/fee')).query(params).result()).nodeify(callback);
2093
+ };
2094
+ module.exports = Wallet;
2095
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbGV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3YxL3dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7QUFFSDtHQUNHO0FBQ0gsRUFBRTtBQUNGLGdCQUFnQjtBQUNoQix1Q0FBdUM7QUFDdkMsRUFBRTtBQUNGLG9EQUFvRDtBQUNwRCxFQUFFO0FBRUYsOENBQStDO0FBRS9DLDhDQUF3QztBQUN4QyxNQUFNLGtCQUFrQixHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBQzNELDJDQUEyQztBQUMzQyxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUVyRCw4Q0FBeUc7QUFDekcscUNBQXFDO0FBQ3JDLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUM7QUFDOUIsNEJBQTRCO0FBQzVCLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO0FBQ3RHLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUV0QyxFQUFFO0FBQ0YsY0FBYztBQUNkLEVBQUU7QUFDRixNQUFNLE1BQU0sR0FBRyxVQUFVLEtBQUssRUFBRSxNQUFNO0lBQ3BDLHNDQUFzQztJQUNyQyxJQUFJLENBQUMsS0FBYSxHQUFHLEtBQUssQ0FBQztJQUM1QixzQ0FBc0M7SUFDdEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDckIsc0NBQXNDO0lBQ3RDLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBRXBCLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUNsQixzQ0FBc0M7UUFDdEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQztLQUMzQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0s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RCxPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUM3RyxDQUFDLENBQUM7QUFFRixpQkFBUyxNQUFNLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBoaWRkZW5cbiAqL1xuXG4vKipcbiAqL1xuLy9cbi8vIFdhbGxldCBPYmplY3Rcbi8vIEJpdEdvIGFjY2Vzc29yIGZvciBhIHNwZWNpZmljIHdhbGxldFxuLy9cbi8vIENvcHlyaWdodCAyMDE0LCBCaXRHbywgSW5jLiAgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vXG5cbmltcG9ydCB7IFZpcnR1YWxTaXplcyB9IGZyb20gJ0BiaXRnby91bnNwZW50cyc7XG5cbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmNvbnN0IFRyYW5zYWN0aW9uQnVpbGRlciA9IHJlcXVpcmUoJy4vdHJhbnNhY3Rpb25CdWlsZGVyJyk7XG5pbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby91dHhvLWxpYic7XG5jb25zdCBQZW5kaW5nQXBwcm92YWwgPSByZXF1aXJlKCcuL3BlbmRpbmdhcHByb3ZhbCcpO1xuXG5pbXBvcnQgeyBjb21tb24sIGdldE5ldHdvcmssIGdldFNoYXJlZFNlY3JldCwgbWFrZVJhbmRvbUtleSwgc2FuaXRpemVMZWdhY3lQYXRoIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCAqIGFzIEJsdWViaXJkIGZyb20gJ2JsdWViaXJkJztcbmNvbnN0IGNvID0gQmx1ZWJpcmQuY29yb3V0aW5lO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuY29uc3QgeyBnZXRFeHRlcm5hbENoYWluQ29kZSwgZ2V0SW50ZXJuYWxDaGFpbkNvZGUsIGlzQ2hhaW5Db2RlLCBzY3JpcHRUeXBlRm9yQ2hhaW4gfSA9IHV0eG9saWIuYml0Z287XG5jb25zdCByZXF1ZXN0ID0gcmVxdWlyZSgnc3VwZXJhZ2VudCcpO1xuXG4vL1xuLy8gQ29uc3RydWN0b3Jcbi8vXG5jb25zdCBXYWxsZXQgPSBmdW5jdGlvbiAoYml0Z28sIHdhbGxldCkge1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAodGhpcy5iaXRnbyBhcyBhbnkpID0gYml0Z287XG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gIHRoaXMud2FsbGV0ID0gd2FsbGV0O1xuICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICB0aGlzLmtleWNoYWlucyA9IFtdO1xuXG4gIGlmICh3YWxsZXQucHJpdmF0ZSkge1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgdGhpcy5rZXljaGFpbnMgPSB3YWxsZXQucHJpdmF0ZS5rZXljaGFpbnM7XG4gIH1cbn07XG5cbldhbGxldC5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy53YWxsZXQ7XG59O1xuXG4vL1xuLy8gaWRcbi8vIEdldCB0aGUgaWQgb2YgdGhpcyB3YWxsZXQuXG4vL1xuV2FsbGV0LnByb3RvdHlwZS5pZCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMud2FsbGV0LmlkO1xufTtcblxuLy9cbi8vIGxhYmVsXG4vLyBHZXQgdGhlIGxhYmVsIG9mIHRoaXMgd2FsbGV0LlxuLy9cbldhbGxldC5wcm90b3R5cGUubGFiZWwgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLndhbGxldC5sYWJlbDtcbn07XG5cbi8vXG4vLyBiYWxhbmNlXG4vLyBHZXQgdGhlIGJhbGFuY2Ugb2YgdGhpcyB3YWxsZXQuXG4vL1xuV2FsbGV0LnByb3RvdHlwZS5iYWxhbmNlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy53YWxsZXQuYmFsYW5jZTtcbn07XG5cbi8vXG4vLyBiYWxhbmNlXG4vLyBHZXQgdGhlIHNwZW5kYWJsZSBiYWxhbmNlIG9mIHRoaXMgd2FsbGV0LlxuLy8gVGhpcyBpcyB0aGUgdG90YWwgb2YgYWxsIHVuc3BlbnRzIGV4Y2VwdCB0aG9zZSB0aGF0IGFyZSB1bmNvbmZpcm1lZCBhbmQgZXh0ZXJuYWxcbi8vXG5XYWxsZXQucHJvdG90eXBlLnNwZW5kYWJsZUJhbGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLndhbGxldC5zcGVuZGFibGVCYWxhbmNlO1xufTtcblxuLy9cbi8vIGNvbmZpcm1lZEJhbGFuY2Vcbi8vIEdldCB0aGUgY29uZmlybWVkQmFsYW5jZSBvZiB0aGlzIHdhbGxldC5cbi8vXG5XYWxsZXQucHJvdG90eXBlLmNvbmZpcm1lZEJhbGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLndhbGxldC5jb25maXJtZWRCYWxhbmNlO1xufTtcblxuLy9cbi8vIGNhblNlbmRJbnN0YW50XG4vLyBSZXR1cm5zIGlmIHRoZSB3YWxsZXQgY2FuIHNlbmQgaW5zdGFudCB0cmFuc2FjdGlvbnNcbi8vIFRoaXMgaXMgaW1wYWN0ZWQgYnkgdGhlIGNob2ljZSBvZiBiYWNrdXAga2V5IHByb3ZpZGVyXG4vL1xuV2FsbGV0LnByb3RvdHlwZS5jYW5TZW5kSW5zdGFudCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMud2FsbGV0ICYmIHRoaXMud2FsbGV0LmNhblNlbmRJbnN0YW50O1xufTtcblxuLy9cbi8vIGluc3RhbnQgYmFsYW5jZVxuLy8gR2V0IHRoZSBpbnN0YW50IGJhbGFuY2Ugb2YgdGhpcyB3YWxsZXQuXG4vLyBUaGlzIGlzIHRoZSB0b3RhbCBvZiBhbGwgdW5zcGVudHMgdGhhdCBtYXkgYmUgc3BlbnQgaW5zdGFudGx5LlxuLy9cbldhbGxldC5wcm90b3R5cGUuaW5zdGFudEJhbGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gIGlmICghdGhpcy5jYW5TZW5kSW5zdGFudCgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdub3QgYW4gaW5zdGFudCB3YWxsZXQnKTtcbiAgfVxuICByZXR1cm4gdGhpcy53YWxsZXQuaW5zdGFudEJhbGFuY2U7XG59O1xuXG4vL1xuLy8gdW5jb25maXJtZWRTZW5kc1xuLy8gR2V0IHRoZSBiYWxhbmNlIG9mIHVuY29uZmlybWVkU2VuZHMgb2YgdGhpcyB3YWxsZXQuXG4vL1xuV2FsbGV0LnByb3RvdHlwZS51bmNvbmZpcm1lZFNlbmRzID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy53YWxsZXQudW5jb25maXJtZWRTZW5kcztcbn07XG5cbi8vXG4vLyB1bmNvbmZpcm1lZFJlY2VpdmVzXG4vLyBHZXQgdGhlIGJhbGFuY2Ugb2YgdW5jb25maXJtZWRSZWNlaXZlcyBiYWxhbmNlIG9mIHRoaXMgd2FsbGV0LlxuLy9cbldhbGxldC5wcm90b3R5cGUudW5jb25maXJtZWRSZWNlaXZlcyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMud2FsbGV0LnVuY29uZmlybWVkUmVjZWl2ZXM7XG59O1xuXG4vL1xuLy8gdHlwZVxuLy8gR2V0IHRoZSB0eXBlIG9mIHRoaXMgd2FsbGV0LCBlLmcuICdzYWZlaGQnXG4vL1xuV2FsbGV0LnByb3RvdHlwZS50eXBlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy53YWxsZXQudHlwZTtcbn07XG5cbldhbGxldC5wcm90b3R5cGUudXJsID0gZnVuY3Rpb24gKGV4dHJhKSB7XG4gIGV4dHJhID0gZXh0cmEgfHwgJyc7XG4gIHJldHVybiB0aGlzLmJpdGdvLnVybCgnL3dhbGxldC8nICsgdGhpcy5pZCgpICsgZXh0cmEpO1xufTtcblxuLy9cbi8vIHBlbmRpbmdBcHByb3ZhbHNcbi8vIHJldHVybnMgdGhlIHBlbmRpbmcgYXBwcm92YWxzIGxpc3QgZm9yIHRoaXMgd2FsbGV0IGFzIHBlbmRpbmcgYXBwcm92YWwgb2JqZWN0c1xuLy9cbldhbGxldC5wcm90b3R5cGUucGVuZGluZ0FwcHJvdmFscyA9IGZ1bmN0aW9uICgpIHtcbiAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gIHJldHVybiB0aGlzLndhbGxldC5wZW5kaW5nQXBwcm92YWxzLm1hcChmdW5jdGlvbiAocCkge1xuICAgIHJldHVybiBuZXcgUGVuZGluZ0FwcHJvdmFsKHNlbGYuYml0Z28sIHAsIHNlbGYpO1xuICB9KTtcbn07XG5cbi8vXG4vLyBhcHByb3ZhbHNSZXF1aXJlZFxuLy8gcmV0dXJucyB0aGUgbnVtYmVyIG9mIGFwcHJvdmFscyByZXF1aXJlZCB0byBhcHByb3ZlIHBlbmRpbmcgYXBwcm92YWxzIGludm9sdmluZyB0aGlzIHdhbGxldFxuLy9cbldhbGxldC5wcm90b3R5cGUuYXBwcm92YWxzUmVxdWlyZWQgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLndhbGxldC5hcHByb3ZhbHNSZXF1aXJlZCB8fCAxO1xufTtcblxuLy9cbi8vIGdldFxuLy8gUmVmZXRjaGVzIHRoaXMgd2FsbGV0IGFuZCByZXR1cm5zIGl0XG4vL1xuV2FsbGV0LnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjayk6IEJsdWViaXJkPGFueT4ge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKFxuICAgIHRoaXMuYml0Z29cbiAgICAgIC5nZXQodGhpcy51cmwoKSlcbiAgICAgIC5yZXN1bHQoKVxuICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgICBzZWxmLndhbGxldCA9IHJlcztcbiAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICB9KVxuICApLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHVwZGF0ZUFwcHJvdmFsc1JlcXVpcmVkXG4vLyBVcGRhdGVzIHRoZSBudW1iZXIgb2YgYXBwcm92YWxzIHJlcXVpcmVkIG9uIGEgcGVuZGluZyBhcHByb3ZhbCBpbnZvbHZpbmcgdGhpcyB3YWxsZXQuXG4vLyBUaGUgYXBwcm92YWxzIHJlcXVpcmVkIGlzIGJ5IGRlZmF1bHQgMSwgYnV0IHRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byB1cGRhdGUgdGhlXG4vLyBudW1iZXIgc3VjaCB0aGF0IDEgPD0gYXBwcm92YWxzUmVxdWlyZWQgPD0gd2FsbGV0QWRtaW5zLmxlbmd0aCAtIDFcbi8vXG5XYWxsZXQucHJvdG90eXBlLnVwZGF0ZUFwcHJvdmFsc1JlcXVpcmVkID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spOiBCbHVlYmlyZDxhbnk+IHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgW10sIGNhbGxiYWNrKTtcbiAgaWYgKFxuICAgIHBhcmFtcy5hcHByb3ZhbHNSZXF1aXJlZCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgIV8uaXNJbnRlZ2VyKHBhcmFtcy5hcHByb3ZhbHNSZXF1aXJlZCkgfHxcbiAgICBwYXJhbXMuYXBwcm92YWxzUmVxdWlyZWQgPCAxXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcHByb3ZhbHNSZXF1aXJlZDogbXVzdCBiZSBhIG5vbnplcm8gcG9zaXRpdmUgbnVtYmVyJyk7XG4gIH1cblxuICBjb25zdCBzZWxmID0gdGhpcztcbiAgY29uc3QgY3VycmVudEFwcHJvdmFsc1JlcXVpcmVkID0gdGhpcy5hcHByb3ZhbHNSZXF1aXJlZCgpO1xuICBpZiAoY3VycmVudEFwcHJvdmFsc1JlcXVpcmVkID09PSBwYXJhbXMuYXBwcm92YWxzUmVxdWlyZWQpIHtcbiAgICAvLyBuby1vcCwganVzdCByZXR1cm4gdGhlIGN1cnJlbnQgd2FsbGV0XG4gICAgcmV0dXJuIEJsdWViaXJkLnRyeShmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gc2VsZi53YWxsZXQ7XG4gICAgfSkubm9kZWlmeShjYWxsYmFjayk7XG4gIH1cblxuICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZSh0aGlzLmJpdGdvLnB1dCh0aGlzLnVybCgpKS5zZW5kKHBhcmFtcykucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjb3JyZWN0IGNoYWluIGZvciBjaGFuZ2UsIHRha2luZyBpbnRvIGNvbnNpZGVyYXRpb24gc2Vnd2l0XG4gKi9cbldhbGxldC5wcm90b3R5cGUuZ2V0Q2hhbmdlQ2hhaW4gPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gIGxldCB1c2VTZWd3aXRDaGFuZ2UgPSAhIXRoaXMuYml0Z28uZ2V0Q29uc3RhbnRzKCkuZW5hYmxlU2Vnd2l0O1xuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLnNlZ3dpdENoYW5nZSkpIHtcbiAgICBpZiAoIV8uaXNCb29sZWFuKHBhcmFtcy5zZWd3aXRDaGFuZ2UpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NlZ3dpdENoYW5nZSBtdXN0IGJlIGEgYm9vbGVhbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHNlZ3dpdCBpcyBkaXNhYmxlZCB0aHJvdWdoIHRoZSBjb25zdGFudHMsIHNlZ3dpdCBjaGFuZ2Ugc2hvdWxkIHN0aWxsIG5vdCBiZSBjcmVhdGVkXG4gICAgdXNlU2Vnd2l0Q2hhbmdlID0gdGhpcy5iaXRnby5nZXRDb25zdGFudHMoKS5lbmFibGVTZWd3aXQgJiYgcGFyYW1zLnNlZ3dpdENoYW5nZTtcbiAgfVxuICByZXR1cm4gdXNlU2Vnd2l0Q2hhbmdlID8gZ2V0SW50ZXJuYWxDaGFpbkNvZGUoJ3Ayc2hQMndzaCcpIDogZ2V0SW50ZXJuYWxDaGFpbkNvZGUoJ3Ayc2gnKTtcbn07XG5cbi8vXG4vLyBjcmVhdGVBZGRyZXNzXG4vLyBDcmVhdGVzIGEgbmV3IGFkZHJlc3MgZm9yIHVzZSB3aXRoIHRoaXMgd2FsbGV0LlxuLy9cbldhbGxldC5wcm90b3R5cGUuY3JlYXRlQWRkcmVzcyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuICBpZiAodGhpcy50eXBlKCkgPT09ICdzYWZlJykge1xuICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSB1c2luZyBhIGxlZ2FjeSB3YWxsZXQgdGhhdCBjYW5ub3QgY3JlYXRlIGEgbmV3IGFkZHJlc3MnKTtcbiAgfVxuXG4gIC8vIERlZmF1bHQgdG8gY2xpZW50LXNpZGUgYWRkcmVzcyB2YWxpZGF0aW9uIG9uLCBmb3Igc2FmZXR5LiBVc2UgdmFsaWRhdGU9ZmFsc2UgdG8gZGlzYWJsZS5cbiAgY29uc3Qgc2hvdWxkVmFsaWRhdGUgPSBwYXJhbXMudmFsaWRhdGUgIT09IHVuZGVmaW5lZCA/IHBhcmFtcy52YWxpZGF0ZSA6IHRoaXMuYml0Z28uZ2V0VmFsaWRhdGUoKTtcblxuICBjb25zdCBhbGxvd0V4aXN0aW5nID0gcGFyYW1zLmFsbG93RXhpc3Rpbmc7XG4gIGlmICh0eXBlb2YgYWxsb3dFeGlzdGluZyAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgcGFyYW1zLmFsbG93RXhpc3RpbmcgPSBhbGxvd0V4aXN0aW5nID09PSAndHJ1ZSc7XG4gIH1cblxuICBjb25zdCBpc1NlZ3dpdCA9IHRoaXMuYml0Z28uZ2V0Q29uc3RhbnRzKCkuZW5hYmxlU2Vnd2l0O1xuICBjb25zdCBkZWZhdWx0Q2hhaW4gPSBpc1NlZ3dpdCA/IGdldEV4dGVybmFsQ2hhaW5Db2RlKCdwMnNoUDJ3c2gnKSA6IGdldEV4dGVybmFsQ2hhaW5Db2RlKCdwMnNoJyk7XG5cbiAgbGV0IGNoYWluID0gcGFyYW1zLmNoYWluO1xuICBpZiAoY2hhaW4gPT09IG51bGwgfHwgY2hhaW4gPT09IHVuZGVmaW5lZCkge1xuICAgIGNoYWluID0gZGVmYXVsdENoYWluO1xuICB9XG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKFxuICAgIHRoaXMuYml0Z29cbiAgICAgIC5wb3N0KHRoaXMudXJsKCcvYWRkcmVzcy8nICsgY2hhaW4pKVxuICAgICAgLnNlbmQocGFyYW1zKVxuICAgICAgLnJlc3VsdCgpXG4gICAgICAudGhlbihmdW5jdGlvbiAoYWRkcikge1xuICAgICAgICBpZiAoc2hvdWxkVmFsaWRhdGUpIHtcbiAgICAgICAgICBzZWxmLnZhbGlkYXRlQWRkcmVzcyhhZGRyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWRkcjtcbiAgICAgIH0pXG4gICkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlIGFkZHJlc3MgbG9jYWxseSB3aXRob3V0IGNhbGxpbmcgc2VydmVyXG4gKiBAcGFyYW0gcGFyYW1zXG4gKlxuICovXG5XYWxsZXQucHJvdG90eXBlLmdlbmVyYXRlQWRkcmVzcyA9IGZ1bmN0aW9uICh7IHNlZ3dpdCwgcGF0aCwga2V5Y2hhaW5zLCB0aHJlc2hvbGQgfSkge1xuICBjb25zdCBpc1NlZ3dpdCA9ICEhc2Vnd2l0O1xuICBsZXQgc2lnbmF0dXJlVGhyZXNob2xkID0gMjtcbiAgaWYgKF8uaXNJbnRlZ2VyKHRocmVzaG9sZCkpIHtcbiAgICBzaWduYXR1cmVUaHJlc2hvbGQgPSB0aHJlc2hvbGQ7XG4gICAgaWYgKHNpZ25hdHVyZVRocmVzaG9sZCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RocmVzaG9sZCBoYXMgdG8gYmUgcG9zaXRpdmUnKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBwYXRoUmVnZXggPSAvXlxcLzE/WzAxXVxcL1xcZCskLztcbiAgaWYgKCFwYXRoLm1hdGNoKHBhdGhSZWdleCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc3VwcG9ydGVkIHBhdGg6ICcgKyBwYXRoKTtcbiAgfVxuXG4gIGxldCByb290S2V5cyA9IHRoaXMua2V5Y2hhaW5zO1xuICBpZiAoQXJyYXkuaXNBcnJheShrZXljaGFpbnMpKSB7XG4gICAgcm9vdEtleXMgPSBrZXljaGFpbnM7XG4gIH1cblxuICBjb25zdCBuZXR3b3JrID0gY29tbW9uLkVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS5uZXR3b3JrO1xuXG4gIGNvbnN0IGRlcml2ZWRLZXlzID0gcm9vdEtleXMubWFwKGZ1bmN0aW9uIChrKSB7XG4gICAgY29uc3QgaGRub2RlID0gYmlwMzIuZnJvbUJhc2U1OChrLnhwdWIpO1xuICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gay5wYXRoICsgKGsud2FsbGV0U3ViUGF0aCB8fCAnJykgKyBwYXRoO1xuICAgIHJldHVybiBoZG5vZGUuZGVyaXZlUGF0aChzYW5pdGl6ZUxlZ2FjeVBhdGgoZGVyaXZhdGlvblBhdGgpKS5wdWJsaWNLZXk7XG4gIH0pO1xuXG4gIGNvbnN0IHBhdGhDb21wb25lbnRzID0gcGF0aC5zcGxpdCgnLycpO1xuICBjb25zdCBub3JtYWxpemVkUGF0aENvbXBvbmVudHMgPSBfLm1hcChwYXRoQ29tcG9uZW50cywgKGNvbXBvbmVudCkgPT4ge1xuICAgIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50Lmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBwYXJzZUludChjb21wb25lbnQsIDEwKTtcbiAgICB9XG4gIH0pO1xuICBjb25zdCBwYXRoRGV0YWlscyA9IF8uZmlsdGVyKG5vcm1hbGl6ZWRQYXRoQ29tcG9uZW50cywgXy5pc0ludGVnZXIpO1xuXG4gIGNvbnN0IGFkZHJlc3NEZXRhaWxzOiBhbnkgPSB7XG4gICAgY2hhaW5QYXRoOiBwYXRoLFxuICAgIHBhdGg6IHBhdGgsXG4gICAgY2hhaW46IHBhdGhEZXRhaWxzWzBdLFxuICAgIGluZGV4OiBwYXRoRGV0YWlsc1sxXSxcbiAgICB3YWxsZXQ6IHRoaXMuaWQoKSxcbiAgfTtcblxuICBjb25zdCB7XG4gICAgc2NyaXB0UHViS2V5OiBvdXRwdXRTY3JpcHQsXG4gICAgcmVkZWVtU2NyaXB0LFxuICAgIHdpdG5lc3NTY3JpcHQsXG4gIH0gPSB1dHhvbGliLmJpdGdvLm91dHB1dFNjcmlwdHMuY3JlYXRlT3V0cHV0U2NyaXB0Mm9mMyhkZXJpdmVkS2V5cywgaXNTZWd3aXQgPyAncDJzaFAyd3NoJyA6ICdwMnNoJyk7XG5cbiAgYWRkcmVzc0RldGFpbHMud2l0bmVzc1NjcmlwdCA9IHdpdG5lc3NTY3JpcHQ/LnRvU3RyaW5nKCdoZXgnKTtcbiAgYWRkcmVzc0RldGFpbHMucmVkZWVtU2NyaXB0ID0gcmVkZWVtU2NyaXB0Py50b1N0cmluZygnaGV4Jyk7XG4gIGFkZHJlc3NEZXRhaWxzLm91dHB1dFNjcmlwdCA9IG91dHB1dFNjcmlwdC50b1N0cmluZygnaGV4Jyk7XG4gIGFkZHJlc3NEZXRhaWxzLmFkZHJlc3MgPSB1dHhvbGliLmFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChvdXRwdXRTY3JpcHQsIGdldE5ldHdvcmsobmV0d29yaykpO1xuXG4gIHJldHVybiBhZGRyZXNzRGV0YWlscztcbn07XG5cbi8vXG4vLyB2YWxpZGF0ZUFkZHJlc3Ncbi8vIFZhbGlkYXRlcyBhbiBhZGRyZXNzIGFuZCBwYXRoIGJ5IGNhbGN1bGF0aW5nIGl0IGxvY2FsbHkgZnJvbSB0aGUga2V5Y2hhaW4geHB1YnNcbi8vXG5XYWxsZXQucHJvdG90eXBlLnZhbGlkYXRlQWRkcmVzcyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWydhZGRyZXNzJywgJ3BhdGgnXSwgW10pO1xuICBjb25zdCBpc1NlZ3dpdCA9ICEhcGFyYW1zLndpdG5lc3NTY3JpcHQgJiYgcGFyYW1zLndpdG5lc3NTY3JpcHQubGVuZ3RoID4gMDtcblxuICBjb25zdCBnZW5lcmF0ZWRBZGRyZXNzID0gdGhpcy5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiBwYXJhbXMucGF0aCwgc2Vnd2l0OiBpc1NlZ3dpdCB9KTtcbiAgaWYgKGdlbmVyYXRlZEFkZHJlc3MuYWRkcmVzcyAhPT0gcGFyYW1zLmFkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2FkZHJlc3MgdmFsaWRhdGlvbiBmYWlsdXJlOiAnICsgcGFyYW1zLmFkZHJlc3MgKyAnIHZzLiAnICsgZ2VuZXJhdGVkQWRkcmVzcy5hZGRyZXNzKTtcbiAgfVxufTtcblxuLy9cbi8vIGFkZHJlc3Nlc1xuLy8gR2V0cyB0aGUgYWRkcmVzc2VzIG9mIGEgSEQgd2FsbGV0LlxuLy8gT3B0aW9ucyBpbmNsdWRlOlxuLy8gIGxpbWl0OiB0aGUgbnVtYmVyIG9mIGFkZHJlc3NlcyB0byBnZXRcbi8vXG5XYWxsZXQucHJvdG90eXBlLmFkZHJlc3NlcyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgY29uc3QgcXVlcnk6IGFueSA9IHt9O1xuICBpZiAocGFyYW1zLmRldGFpbHMpIHtcbiAgICBxdWVyeS5kZXRhaWxzID0gMTtcbiAgfVxuXG4gIGNvbnN0IGNoYWluID0gcGFyYW1zLmNoYWluO1xuICBpZiAoY2hhaW4gIT09IG51bGwgJiYgY2hhaW4gIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNoYWluKSkge1xuICAgICAgcXVlcnkuY2hhaW4gPSBfLnVuaXEoXy5maWx0ZXIoY2hhaW4sIF8uaXNJbnRlZ2VyKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChjaGFpbiAhPT0gMCAmJiBjaGFpbiAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgY2hhaW4gYXJndW1lbnQsIGV4cGVjdGluZyAwIG9yIDEnKTtcbiAgICAgIH1cbiAgICAgIHF1ZXJ5LmNoYWluID0gY2hhaW47XG4gICAgfVxuICB9XG4gIGlmIChwYXJhbXMubGltaXQpIHtcbiAgICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5saW1pdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBsaW1pdCBhcmd1bWVudCwgZXhwZWN0aW5nIG51bWJlcicpO1xuICAgIH1cbiAgICBxdWVyeS5saW1pdCA9IHBhcmFtcy5saW1pdDtcbiAgfVxuICBpZiAocGFyYW1zLnNraXApIHtcbiAgICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5za2lwKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNraXAgYXJndW1lbnQsIGV4cGVjdGluZyBudW1iZXInKTtcbiAgICB9XG4gICAgcXVlcnkuc2tpcCA9IHBhcmFtcy5za2lwO1xuICB9XG4gIGlmIChwYXJhbXMuc29ydCkge1xuICAgIGlmICghXy5pc051bWJlcihwYXJhbXMuc29ydCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzb3J0IGFyZ3VtZW50LCBleHBlY3RpbmcgbnVtYmVyJyk7XG4gICAgfVxuICAgIHF1ZXJ5LnNvcnQgPSBwYXJhbXMuc29ydDtcbiAgfVxuXG4gIGNvbnN0IHVybCA9IHRoaXMudXJsKCcvYWRkcmVzc2VzJyk7XG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHVybCkucXVlcnkocXVlcnkpLnJlc3VsdCgpKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbldhbGxldC5wcm90b3R5cGUuc3RhdHMgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuICBjb25zdCBhcmdzOiBzdHJpbmdbXSA9IFtdO1xuICBpZiAocGFyYW1zLmxpbWl0KSB7XG4gICAgaWYgKCFfLmlzSW50ZWdlcihwYXJhbXMubGltaXQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgbGltaXQgYXJndW1lbnQsIGV4cGVjdGluZyBudW1iZXInKTtcbiAgICB9XG4gICAgYXJncy5wdXNoKCdsaW1pdD0nICsgcGFyYW1zLmxpbWl0KTtcbiAgfVxuICBsZXQgcXVlcnkgPSAnJztcbiAgaWYgKGFyZ3MubGVuZ3RoKSB7XG4gICAgcXVlcnkgPSAnPycgKyBhcmdzLmpvaW4oJyYnKTtcbiAgfVxuXG4gIGNvbnN0IHVybCA9IHRoaXMudXJsKCcvc3RhdHMnICsgcXVlcnkpO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHVybCkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBSZWZyZXNoIHRoZSB3YWxsZXQgb2JqZWN0IGJ5IHN5bmNpbmcgd2l0aCB0aGUgYmFjay1lbmRcbiAqIEBwYXJhbSBjYWxsYmFja1xuICogQHJldHVybnMge1dhbGxldH1cbiAqL1xuV2FsbGV0LnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcmV0dXJuIGNvKGZ1bmN0aW9uKiAoKSB7XG4gICAgLy8gd2hlbiBzZXQgdG8gdHJ1ZSwgZ3BrIHJldHVybnMgdGhlIHByaXZhdGUgZGF0YSBvZiBzYWZlIHdhbGxldHNcbiAgICBjb25zdCBxdWVyeSA9IF8uZXh0ZW5kKHt9LCBfLnBpY2socGFyYW1zLCBbJ2dwayddKSk7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIG5vIGltcGxpY2l0IHRoaXNcbiAgICBjb25zdCByZXMgPSB5aWVsZCB0aGlzLmJpdGdvLmdldCh0aGlzLnVybCgpKS5xdWVyeShxdWVyeSkucmVzdWx0KCk7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIG5vIGltcGxpY2l0IHRoaXNcbiAgICB0aGlzLndhbGxldCA9IHJlcztcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIHJldHVybiB0aGlzO1xuICB9KVxuICAgIC5jYWxsKHRoaXMpXG4gICAgLmFzQ2FsbGJhY2soY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGFkZHJlc3Ncbi8vIEdldHMgaW5mb3JtYXRpb24gYWJvdXQgYSBzaW5nbGUgYWRkcmVzcyBvbiBhIEhEIHdhbGxldC5cbi8vIEluZm9ybWF0aW9uIGluY2x1ZGVzIGluZGV4LCBwYXRoLCByZWRlZW1TY3JpcHQsIHNlbnQsIHJlY2VpdmVkLCB0eENvdW50IGFuZCBiYWxhbmNlXG4vLyBPcHRpb25zIGluY2x1ZGU6XG4vLyAgYWRkcmVzczogdGhlIGFkZHJlc3Mgb24gdGhpcyB3YWxsZXQgdG8gZ2V0XG4vL1xuV2FsbGV0LnByb3RvdHlwZS5hZGRyZXNzID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ2FkZHJlc3MnXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCB1cmwgPSB0aGlzLnVybCgnL2FkZHJlc3Nlcy8nICsgcGFyYW1zLmFkZHJlc3MpO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHVybCkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBGcmVlemUgdGhlIHdhbGxldCBmb3IgYSBkdXJhdGlvbiBvZiBjaG9pY2UsIHN0b3BwaW5nIEJpdEdvIGZyb20gc2lnbmluZyBhbnkgdHJhbnNhY3Rpb25zLlxuICogQHBhcmFtIHtudW1iZXJ9IGxpbWl0IFRoZSBkdXJhdGlvbiB0byBmcmVlemUgdGhlIHdhbGxldCBmb3IgaW4gc2Vjb25kcywgZGVmYXVsdHMgdG8gMzYwMC5cbiAqL1xuV2FsbGV0LnByb3RvdHlwZS5mcmVlemUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIGlmIChwYXJhbXMuZHVyYXRpb24pIHtcbiAgICBpZiAoIV8uaXNOdW1iZXIocGFyYW1zLmR1cmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGR1cmF0aW9uIC0gc2hvdWxkIGJlIG51bWJlciBvZiBzZWNvbmRzJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5wb3N0KHRoaXMudXJsKCcvZnJlZXplJykpLnNlbmQocGFyYW1zKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gZGVsZXRlXG4vLyBEZWxldGVzIHRoZSB3YWxsZXRcbi8vXG5XYWxsZXQucHJvdG90eXBlLmRlbGV0ZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5kZWwodGhpcy51cmwoKSkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGxhYmVsc1xuLy8gTGlzdCB0aGUgbGFiZWxzIGZvciB0aGUgYWRkcmVzc2VzIGluIGEgZ2l2ZW4gd2FsbGV0XG4vL1xuV2FsbGV0LnByb3RvdHlwZS5sYWJlbHMgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IHVybCA9IHRoaXMuYml0Z28udXJsKCcvbGFiZWxzLycgKyB0aGlzLmlkKCkpO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHVybCkucmVzdWx0KCdsYWJlbHMnKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG4vKipcbiAqIFJlbmFtZSBhIHdhbGxldFxuICogQHBhcmFtIHBhcmFtc1xuICogIC0gbGFiZWw6IHRoZSB3YWxsZXQncyBpbnRlbmRlZCBuZXcgbmFtZVxuICogQHBhcmFtIGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuV2FsbGV0LnByb3RvdHlwZS5zZXRXYWxsZXROYW1lID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ2xhYmVsJ10sIFtdLCBjYWxsYmFjayk7XG5cbiAgY29uc3QgdXJsID0gdGhpcy5iaXRnby51cmwoJy93YWxsZXQvJyArIHRoaXMuaWQoKSk7XG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28ucHV0KHVybCkuc2VuZCh7IGxhYmVsOiBwYXJhbXMubGFiZWwgfSkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHNldExhYmVsXG4vLyBTZXRzIGEgbGFiZWwgb24gdGhlIHByb3ZpZGVkIGFkZHJlc3Ncbi8vXG5XYWxsZXQucHJvdG90eXBlLnNldExhYmVsID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ2FkZHJlc3MnLCAnbGFiZWwnXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCBzZWxmID0gdGhpcztcblxuICBpZiAoIXNlbGYuYml0Z28udmVyaWZ5QWRkcmVzcyh7IGFkZHJlc3M6IHBhcmFtcy5hZGRyZXNzIH0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGJpdGNvaW4gYWRkcmVzczogJyArIHBhcmFtcy5hZGRyZXNzKTtcbiAgfVxuXG4gIGNvbnN0IHVybCA9IHRoaXMuYml0Z28udXJsKCcvbGFiZWxzLycgKyB0aGlzLmlkKCkgKyAnLycgKyBwYXJhbXMuYWRkcmVzcyk7XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5wdXQodXJsKS5zZW5kKHsgbGFiZWw6IHBhcmFtcy5sYWJlbCB9KS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gZGVsZXRlTGFiZWxcbi8vIERlbGV0ZXMgdGhlIGxhYmVsIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJvdmlkZWQgYWRkcmVzc1xuLy9cbldhbGxldC5wcm90b3R5cGUuZGVsZXRlTGFiZWwgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnYWRkcmVzcyddLCBbXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gIGlmICghc2VsZi5iaXRnby52ZXJpZnlBZGRyZXNzKHsgYWRkcmVzczogcGFyYW1zLmFkZHJlc3MgfSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYml0Y29pbiBhZGRyZXNzOiAnICsgcGFyYW1zLmFkZHJlc3MpO1xuICB9XG5cbiAgY29uc3QgdXJsID0gdGhpcy5iaXRnby51cmwoJy9sYWJlbHMvJyArIHRoaXMuaWQoKSArICcvJyArIHBhcmFtcy5hZGRyZXNzKTtcblxuICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZSh0aGlzLmJpdGdvLmRlbCh1cmwpLnJlc3VsdCgpKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyB1bnNwZW50c1xuLy8gTGlzdCBBTEwgdGhlIHVuc3BlbnRzIGZvciBhIGdpdmVuIHdhbGxldFxuLy8gVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gYSBwYWdlZCBsaXN0IG9mIGFsbCB1bnNwZW50c1xuLy9cbi8vIFBhcmFtZXRlcnMgaW5jbHVkZTpcbi8vICAgbGltaXQ6ICB0aGUgb3B0aW9uYWwgbGltaXQgb2YgdW5zcGVudHMgdG8gY29sbGVjdCBpbiBCVENcbi8vICAgbWluQ29uZjogb25seSBpbmNsdWRlIHJlc3VsdHMgd2l0aCB0aGlzIG51bWJlciBvZiBjb25maXJtYXRpb25zXG4vLyAgIHRhcmdldDogdGhlIGFtb3VudCBvZiBidGMgdG8gZmluZCB0byBzcGVuZFxuLy8gICBpbnN0YW50OiBvbmx5IGZpbmQgaW5zdGFudCB0cmFuc2FjdGlvbnMgKG11c3Qgc3BlY2lmeSBhIHRhcmdldClcbi8vXG5XYWxsZXQucHJvdG90eXBlLnVuc3BlbnRzID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCBhbGxVbnNwZW50czogYW55W10gPSBbXTtcbiAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgY29uc3QgZ2V0VW5zcGVudHNCYXRjaCA9IGZ1bmN0aW9uIChza2lwLCBsaW1pdD8pIHtcbiAgICBjb25zdCBxdWVyeU9iamVjdCA9IF8uY2xvbmVEZWVwKHBhcmFtcyk7XG4gICAgaWYgKHNraXAgPiAwKSB7XG4gICAgICBxdWVyeU9iamVjdC5za2lwID0gc2tpcDtcbiAgICB9XG4gICAgaWYgKGxpbWl0ICYmIGxpbWl0ID4gMCkge1xuICAgICAgcXVlcnlPYmplY3QubGltaXQgPSBsaW1pdDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZi51bnNwZW50c1BhZ2VkKHF1ZXJ5T2JqZWN0KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgIC8vIFRoZSBBUEkgaGFzIGl0cyBvd24gbGltaXQgaGFuZGxpbmcuIEZvciBleGFtcGxlLCB0aGUgQVBJIGRvZXMgbm90IHN1cHBvcnQgbGltaXRzIGJpZ2dlciB0aGFuIDUwMC4gSWYgdGhlIGxpbWl0XG4gICAgICAvLyBzcGVjaWZpZWQgaGVyZSBpcyBiaWdnZXIgdGhhbiB0aGF0LCB3ZSB3aWxsIGhhdmUgdG8gZG8gbXVsdGlwbGUgcmVxdWVzdHMgd2l0aCBuZWNlc3NhcnkgbGltaXQgYWRqdXN0bWVudC5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVzdWx0LnVuc3BlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHVuc3BlbnQgPSByZXN1bHQudW5zcGVudHNbaV07XG4gICAgICAgIGFsbFVuc3BlbnRzLnB1c2godW5zcGVudCk7XG4gICAgICB9XG5cbiAgICAgIC8vIE91ciBsaW1pdCBhZGp1c3RtZW50IG1ha2VzIHN1cmUgdGhhdCB3ZSBuZXZlciBmZXRjaCBtb3JlIHVuc3BlbnRzIHRoYW4gd2UgbmVlZCwgbWVhbmluZyB0aGF0IGlmIHdlIGhpdCB0aGVcbiAgICAgIC8vIGxpbWl0LCB3ZSBoaXQgaXQgcHJlY2lzZWx5XG4gICAgICBpZiAoYWxsVW5zcGVudHMubGVuZ3RoID49IHBhcmFtcy5saW1pdCkge1xuICAgICAgICByZXR1cm4gYWxsVW5zcGVudHM7IC8vIHdlIGFyZW4ndCBpbnRlcmVzdGVkIGluIGFueSBmdXJ0aGVyIHVuc3BlbnRzXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRvdGFsVW5zcGVudENvdW50ID0gcmVzdWx0LnRvdGFsO1xuICAgICAgLy8gaWYgbm8gdGFyZ2V0IGlzIHNwZWNpZmllZCBhbmQgdGhlIFNESyBpbmRpY2F0ZXMgdGhhdCB0aGVyZSBoYXMgYmVlbiBhIGxpbWl0LCB3ZSBuZWVkIHRvIGZldGNoIGFub3RoZXIgYmF0Y2hcbiAgICAgIGlmICghcGFyYW1zLnRhcmdldCAmJiB0b3RhbFVuc3BlbnRDb3VudCAmJiB0b3RhbFVuc3BlbnRDb3VudCA+IGFsbFVuc3BlbnRzLmxlbmd0aCkge1xuICAgICAgICAvLyB3ZSBuZWVkIHRvIGZldGNoIHRoZSBuZXh0IGJhdGNoXG4gICAgICAgIC8vIGxldCdzIGp1c3Qgb2Zmc2V0IHRoZSBjdXJyZW50IHNraXAgYnkgdGhlIGNvdW50XG4gICAgICAgIGNvbnN0IG5ld1NraXAgPSBza2lwICsgcmVzdWx0LmNvdW50O1xuICAgICAgICBsZXQgbmV3TGltaXQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGxpbWl0ID4gMCkge1xuICAgICAgICAgIC8vIHdlIHNldCB0aGUgbmV3IGxpbWl0IHRvIGJlIHByZWNpc2VseSB0aGUgbnVtYmVyIG9mIG1pc3NpbmcgdW5zcGVudHMgdG8gaGl0IG91ciBvd24gbGltaXRcbiAgICAgICAgICBuZXdMaW1pdCA9IGxpbWl0IC0gYWxsVW5zcGVudHMubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnZXRVbnNwZW50c0JhdGNoKG5ld1NraXAsIG5ld0xpbWl0KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGFsbFVuc3BlbnRzO1xuICAgIH0pO1xuICB9O1xuXG4gIHJldHVybiBnZXRVbnNwZW50c0JhdGNoKDAsIHBhcmFtcy5saW1pdCkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG4vKipcbiAqIExpc3QgdGhlIHVuc3BlbnRzIChwYWdlZCkgZm9yIGEgZ2l2ZW4gd2FsbGV0LCByZXR1cm5pbmcgdGhlIHJlc3VsdCBhcyBhbiBvYmplY3Qgb2YgdW5zcGVudHMsIGNvdW50LCBza2lwIGFuZCB0b3RhbFxuICogVGhpcyBtZXRob2QgbWF5IG5vdCByZXR1cm4gYWxsIHRoZSB1bnNwZW50cyBhcyB0aGUgbGlzdCBpcyBwYWdlZCBieSB0aGUgQVBJXG4gKiBAcGFyYW0gcGFyYW1zXG4gKiBAcGFyYW0gcGFyYW1zLmxpbWl0IHRoZSBvcHRpb25hbCBsaW1pdCBvZiB1bnNwZW50cyB0byBjb2xsZWN0IGluIEJUQ1xuICogQHBhcmFtIHBhcmFtcy5za2lwIGluZGV4IGluIGxpc3Qgb2YgdW5zcGVudHMgdG8gc3RhcnQgcGFnaW5nIGZyb21cbiAqIEBwYXJhbSBwYXJhbXMubWluQ29uZmlybXMgb25seSBpbmNsdWRlIHJlc3VsdHMgd2l0aCB0aGlzIG51bWJlciBvZiBjb25maXJtYXRpb25zXG4gKiBAcGFyYW0gcGFyYW1zLnRhcmdldCB0aGUgYW1vdW50IG9mIGJ0YyB0byBmaW5kIHRvIHNwZW5kXG4gKiBAcGFyYW0gcGFyYW1zLmluc3RhbnQgb25seSBmaW5kIGluc3RhbnQgdHJhbnNhY3Rpb25zIChtdXN0IHNwZWNpZnkgYSB0YXJnZXQpXG4gKiBAcGFyYW0gcGFyYW1zLnRhcmdldFdhbGxldFVuc3BlbnRzIGRlc2lyZWQgbnVtYmVyIG9mIHVuc3BlbnRzIHRvIGhhdmUgaW4gdGhlIHdhbGxldCBhZnRlciB0aGUgdHggZ29lcyB0aHJvdWdoIChyZXF1aXJlcyB0YXJnZXQpXG4gKiBAcGFyYW0gcGFyYW1zLm1pblNpemUgbWluaW11bSB1bnNwZW50IHNpemUgaW4gc2F0b3NoaXNcbiAqIEBwYXJhbSBwYXJhbXMuc2Vnd2l0IHJlcXVlc3Qgc2Vnd2l0IHVuc3BlbnRzIChkZWZhdWx0cyB0byB0cnVlIGlmIHVuZGVmaW5lZClcbiAqIEBwYXJhbSBwYXJhbXMuYWxsb3dMZWRnZXJTZWd3aXQgYWxsb3cgc2Vnd2l0IHVuc3BlbnRzIGZvciBsZWRnZXIgZGV2aWNlcyAoZGVmYXVsdHMgdG8gZmFsc2UgaWYgdW5kZWZpbmVkKVxuICogQHBhcmFtIGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuV2FsbGV0LnByb3RvdHlwZS51bnNwZW50c1BhZ2VkID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgW10sIGNhbGxiYWNrKTtcblxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmxpbWl0KSAmJiAhXy5pc0ludGVnZXIocGFyYW1zLmxpbWl0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBsaW1pdCAtIHNob3VsZCBiZSBudW1iZXInKTtcbiAgfVxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLnNraXApICYmICFfLmlzSW50ZWdlcihwYXJhbXMuc2tpcCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2tpcCAtIHNob3VsZCBiZSBudW1iZXInKTtcbiAgfVxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLm1pbkNvbmZpcm1zKSAmJiAhXy5pc0ludGVnZXIocGFyYW1zLm1pbkNvbmZpcm1zKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBtaW5Db25maXJtcyAtIHNob3VsZCBiZSBudW1iZXInKTtcbiAgfVxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLnRhcmdldCkgJiYgIV8uaXNOdW1iZXIocGFyYW1zLnRhcmdldCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgdGFyZ2V0IC0gc2hvdWxkIGJlIG51bWJlcicpO1xuICB9XG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMuaW5zdGFudCkgJiYgIV8uaXNCb29sZWFuKHBhcmFtcy5pbnN0YW50KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnN0YW50IGZsYWcgLSBzaG91bGQgYmUgYm9vbGVhbicpO1xuICB9XG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMuc2Vnd2l0KSAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLnNlZ3dpdCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vnd2l0IGZsYWcgLSBzaG91bGQgYmUgYm9vbGVhbicpO1xuICB9XG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMudGFyZ2V0V2FsbGV0VW5zcGVudHMpICYmICFfLmlzSW50ZWdlcihwYXJhbXMudGFyZ2V0V2FsbGV0VW5zcGVudHMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHRhcmdldFdhbGxldFVuc3BlbnRzIGZsYWcgLSBzaG91bGQgYmUgbnVtYmVyJyk7XG4gIH1cbiAgaWYgKCFfLmlzVW5kZWZpbmVkKHBhcmFtcy5taW5TaXplKSAmJiAhXy5pc051bWJlcihwYXJhbXMubWluU2l6ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYXJndW1lbnQ6IG1pblNpemUgbXVzdCBiZSBhIG51bWJlcicpO1xuICB9XG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMuaW5zdGFudCkgJiYgIV8uaXNVbmRlZmluZWQocGFyYW1zLm1pbkNvbmZpcm1zKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignb25seSBvbmUgb2YgaW5zdGFudCBhbmQgbWluQ29uZmlybXMgbWF5IGJlIGRlZmluZWQnKTtcbiAgfVxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLnRhcmdldFdhbGxldFVuc3BlbnRzKSAmJiBfLmlzVW5kZWZpbmVkKHBhcmFtcy50YXJnZXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXRXYWxsZXRVbnNwZW50cyBjYW4gb25seSBiZSBzcGVjaWZpZWQgaW4gY29uanVuY3Rpb24gd2l0aCBhIHRhcmdldCcpO1xuICB9XG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMuYWxsb3dMZWRnZXJTZWd3aXQpICYmICFfLmlzQm9vbGVhbihwYXJhbXMuYWxsb3dMZWRnZXJTZWd3aXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFyZ3VtZW50OiBhbGxvd0xlZGdlclNlZ3dpdCBtdXN0IGJlIGEgYm9vbGVhbicpO1xuICB9XG5cbiAgY29uc3QgcXVlcnlPYmplY3QgPSBfLmNsb25lRGVlcChwYXJhbXMpO1xuXG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMudGFyZ2V0KSkge1xuICAgIC8vIHNraXAgYW5kIGxpbWl0IGFyZSB1bmF2YWlsYWJsZSB3aGVuIGEgdGFyZ2V0IGlzIHNwZWNpZmllZFxuICAgIGRlbGV0ZSBxdWVyeU9iamVjdC5za2lwO1xuICAgIGRlbGV0ZSBxdWVyeU9iamVjdC5saW1pdDtcbiAgfVxuXG4gIHF1ZXJ5T2JqZWN0LnNlZ3dpdCA9IHRydWU7XG4gIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMuc2Vnd2l0KSkge1xuICAgIHF1ZXJ5T2JqZWN0LnNlZ3dpdCA9IHBhcmFtcy5zZWd3aXQ7XG4gIH1cblxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmFsbG93TGVkZ2VyU2Vnd2l0KSkge1xuICAgIHF1ZXJ5T2JqZWN0LmFsbG93TGVkZ2VyU2Vnd2l0ID0gcGFyYW1zLmFsbG93TGVkZ2VyU2Vnd2l0O1xuICB9XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5nZXQodGhpcy51cmwoJy91bnNwZW50cycpKS5xdWVyeShxdWVyeU9iamVjdCkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHRyYW5zYWN0aW9uc1xuLy8gTGlzdCB0aGUgdHJhbnNhY3Rpb25zIGZvciBhIGdpdmVuIHdhbGxldFxuLy8gT3B0aW9ucyBpbmNsdWRlOlxuLy8gICAgIFRPRE86ICBBZGQgaXRlcmF0b3JzIGZvciBzdGFydC9jb3VudC9ldGNcbldhbGxldC5wcm90b3R5cGUudHJhbnNhY3Rpb25zID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCBhcmdzOiBzdHJpbmdbXSA9IFtdO1xuICBpZiAocGFyYW1zLmxpbWl0KSB7XG4gICAgaWYgKCFfLmlzSW50ZWdlcihwYXJhbXMubGltaXQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgbGltaXQgYXJndW1lbnQsIGV4cGVjdGluZyBudW1iZXInKTtcbiAgICB9XG4gICAgYXJncy5wdXNoKCdsaW1pdD0nICsgcGFyYW1zLmxpbWl0KTtcbiAgfVxuICBpZiAocGFyYW1zLnNraXApIHtcbiAgICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5za2lwKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNraXAgYXJndW1lbnQsIGV4cGVjdGluZyBudW1iZXInKTtcbiAgICB9XG4gICAgYXJncy5wdXNoKCdza2lwPScgKyBwYXJhbXMuc2tpcCk7XG4gIH1cbiAgaWYgKHBhcmFtcy5taW5IZWlnaHQpIHtcbiAgICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5taW5IZWlnaHQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgbWluSGVpZ2h0IGFyZ3VtZW50LCBleHBlY3RpbmcgbnVtYmVyJyk7XG4gICAgfVxuICAgIGFyZ3MucHVzaCgnbWluSGVpZ2h0PScgKyBwYXJhbXMubWluSGVpZ2h0KTtcbiAgfVxuICBpZiAocGFyYW1zLm1heEhlaWdodCkge1xuICAgIGlmICghXy5pc0ludGVnZXIocGFyYW1zLm1heEhlaWdodCkgfHwgcGFyYW1zLm1heEhlaWdodCA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBtYXhIZWlnaHQgYXJndW1lbnQsIGV4cGVjdGluZyBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gICAgfVxuICAgIGFyZ3MucHVzaCgnbWF4SGVpZ2h0PScgKyBwYXJhbXMubWF4SGVpZ2h0KTtcbiAgfVxuICBpZiAocGFyYW1zLm1pbkNvbmZpcm1zKSB7XG4gICAgaWYgKCFfLmlzSW50ZWdlcihwYXJhbXMubWluQ29uZmlybXMpIHx8IHBhcmFtcy5taW5Db25maXJtcyA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBtaW5Db25maXJtcyBhcmd1bWVudCwgZXhwZWN0aW5nIHBvc2l0aXZlIGludGVnZXInKTtcbiAgICB9XG4gICAgYXJncy5wdXNoKCdtaW5Db25maXJtcz0nICsgcGFyYW1zLm1pbkNvbmZpcm1zKTtcbiAgfVxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmNvbXBhY3QpKSB7XG4gICAgaWYgKCFfLmlzQm9vbGVhbihwYXJhbXMuY29tcGFjdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBjb21wYWN0IGFyZ3VtZW50LCBleHBlY3RpbmcgYm9vbGVhbicpO1xuICAgIH1cbiAgICBhcmdzLnB1c2goJ2NvbXBhY3Q9JyArIHBhcmFtcy5jb21wYWN0KTtcbiAgfVxuICBsZXQgcXVlcnkgPSAnJztcbiAgaWYgKGFyZ3MubGVuZ3RoKSB7XG4gICAgcXVlcnkgPSAnPycgKyBhcmdzLmpvaW4oJyYnKTtcbiAgfVxuXG4gIGNvbnN0IHVybCA9IHRoaXMudXJsKCcvdHgnICsgcXVlcnkpO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHVybCkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHRyYW5zYWN0aW9uXG4vLyBHZXQgYSB0cmFuc2FjdGlvbiBieSBJRCBmb3IgYSBnaXZlbiB3YWxsZXRcbldhbGxldC5wcm90b3R5cGUuZ2V0VHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnaWQnXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCB1cmwgPSB0aGlzLnVybCgnL3R4LycgKyBwYXJhbXMuaWQpO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHVybCkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHBvbGxGb3JUcmFuc2FjdGlvblxuLy8gUG9sbCBhIHRyYW5zYWN0aW9uIHVudGlsIHN1Y2Nlc3NmdWwgb3IgdGltZXMgb3V0XG4vLyBQYXJhbWV0ZXJzOlxuLy8gICBpZDogdGhlIHR4aWRcbi8vICAgZGVsYXk6IGRlbGF5IGJldHdlZW4gcG9sbHMgaW4gbXMgKGRlZmF1bHQ6IDEwMDApXG4vLyAgIHRpbWVvdXQ6IHRpbWVvdXQgaW4gbXMgKGRlZmF1bHQ6IDEwMDAwKVxuV2FsbGV0LnByb3RvdHlwZS5wb2xsRm9yVHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBjb25zdCBzZWxmID0gdGhpcztcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ2lkJ10sIFtdLCBjYWxsYmFjayk7XG4gIGlmIChwYXJhbXMuZGVsYXkgJiYgIV8uaXNOdW1iZXIocGFyYW1zLmRlbGF5KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBkZWxheSBwYXJhbWV0ZXInKTtcbiAgfVxuICBpZiAocGFyYW1zLnRpbWVvdXQgJiYgIV8uaXNOdW1iZXIocGFyYW1zLnRpbWVvdXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHRpbWVvdXQgcGFyYW1ldGVyJyk7XG4gIH1cbiAgcGFyYW1zLmRlbGF5ID0gcGFyYW1zLmRlbGF5IHx8IDEwMDA7XG4gIHBhcmFtcy50aW1lb3V0ID0gcGFyYW1zLnRpbWVvdXQgfHwgMTAwMDA7XG5cbiAgY29uc3Qgc3RhcnQgPSBuZXcgRGF0ZSgpO1xuXG4gIGNvbnN0IGRvTmV4dFBvbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHNlbGZcbiAgICAgIC5nZXRUcmFuc2FjdGlvbihwYXJhbXMpXG4gICAgICAudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGVyci5zdGF0dXMgIT09IDQwNCB8fCBuZXcgRGF0ZSgpLnZhbHVlT2YoKSAtIHN0YXJ0LnZhbHVlT2YoKSA+IHBhcmFtcy50aW1lb3V0KSB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBCbHVlYmlyZC5kZWxheShwYXJhbXMuZGVsYXkpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBkb05leHRQb2xsKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIGRvTmV4dFBvbGwoKTtcbn07XG5cbi8vXG4vLyB0cmFuc2FjdGlvbiBieSBzZXF1ZW5jZSBpZFxuLy8gR2V0IGEgdHJhbnNhY3Rpb24gYnkgc2VxdWVuY2UgaWQgZm9yIGEgZ2l2ZW4gd2FsbGV0XG5XYWxsZXQucHJvdG90eXBlLmdldFdhbGxldFRyYW5zYWN0aW9uQnlTZXF1ZW5jZUlkID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ3NlcXVlbmNlSWQnXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCB1cmwgPSB0aGlzLnVybCgnL3R4L3NlcXVlbmNlLycgKyBwYXJhbXMuc2VxdWVuY2VJZCk7XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5nZXQodXJsKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gS2V5IGNoYWluc1xuLy8gR2V0cyB0aGUgdXNlciBrZXkgY2hhaW4gZm9yIHRoaXMgd2FsbGV0XG4vLyBUaGUgdXNlciBrZXkgY2hhaW4gaXMgdHlwaWNhbGx5IHRoZSBmaXJzdCBrZXljaGFpbiBvZiB0aGUgd2FsbGV0IGFuZCBoYXMgdGhlIGVuY3J5cHRlZCB4cHJpdiBzdG9yZWQgb24gQml0R28uXG4vLyBVc2VmdWwgd2hlbiB0cnlpbmcgdG8gZ2V0IHRoZSB1c2Vycycga2V5Y2hhaW4gZnJvbSB0aGUgc2VydmVyIGJlZm9yZSBkZWNyeXB0aW5nIHRvIHNpZ24gYSB0cmFuc2FjdGlvbi5cbldhbGxldC5wcm90b3R5cGUuZ2V0RW5jcnlwdGVkVXNlcktleWNoYWluID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcmV0dXJuIGNvKGZ1bmN0aW9uKiAoKSB7XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBjb25zdCB0cnlLZXlDaGFpbiA9IGNvKGZ1bmN0aW9uKiAoaW5kZXgpIHtcbiAgICAgIGlmICghc2VsZi5rZXljaGFpbnMgfHwgaW5kZXggPj0gc2VsZi5rZXljaGFpbnMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGVycm9yOiBhbnkgPSBuZXcgRXJyb3IoJ05vIGVuY3J5cHRlZCBrZXljaGFpbnMgb24gdGhpcyB3YWxsZXQuJyk7XG4gICAgICAgIGVycm9yLmNvZGUgPSAnbm9fZW5jcnlwdGVkX2tleWNoYWluX29uX3dhbGxldCc7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJhbXMgPSB7IHhwdWI6IHNlbGYua2V5Y2hhaW5zW2luZGV4XS54cHViIH07XG5cbiAgICAgIGNvbnN0IGtleWNoYWluID0geWllbGQgc2VsZi5iaXRnby5rZXljaGFpbnMoKS5nZXQocGFyYW1zKTtcbiAgICAgIC8vIElmIHdlIGZpbmQgdGhlIHhwcnYsIHRoZW4gdGhpcyBpcyBwcm9iYWJseSB0aGUgdXNlciBrZXljaGFpbiB3ZSdyZSBsb29raW5nIGZvclxuICAgICAga2V5Y2hhaW4ud2FsbGV0U3ViUGF0aCA9IHNlbGYua2V5Y2hhaW5zW2luZGV4XS5wYXRoO1xuICAgICAgaWYgKGtleWNoYWluLmVuY3J5cHRlZFhwcnYpIHtcbiAgICAgICAgcmV0dXJuIGtleWNoYWluO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRyeUtleUNoYWluKGluZGV4ICsgMSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdHJ5S2V5Q2hhaW4oMCk7XG4gIH0pXG4gICAgLmNhbGwodGhpcylcbiAgICAuYXNDYWxsYmFjayhjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gY3JlYXRlVHJhbnNhY3Rpb25cbi8vIENyZWF0ZSBhIHRyYW5zYWN0aW9uICh1bnNpZ25lZCkuIFRvIHNpZ24gaXQsIGRvIHNpZ25UcmFuc2FjdGlvblxuLy8gUGFyYW1ldGVyczpcbi8vICAgcmVjaXBpZW50cyAtIG9iamVjdCBvZiByZWNpcGllbnQgYWRkcmVzc2VzIGFuZCB0aGUgYW1vdW50IHRvIHNlbmQgdG8gZWFjaCBlLmcuIHthZGRyZXNzOjE1MDAsIGFkZHJlc3MyOjE1MDB9XG4vLyAgIGZlZSAgICAgIC0gdGhlIGJsb2NrY2hhaW4gZmVlIHRvIHNlbmQgKG9wdGlvbmFsKVxuLy8gICBmZWVSYXRlICAtIHRoZSBmZWUgcGVyIGtiIHRvIHNlbmQgKG9wdGlvbmFsKVxuLy8gICBtaW5Db25maXJtcyAtIG1pbmltdW0gbnVtYmVyIG9mIGNvbmZpcm1zIHRvIHVzZSB3aGVuIGdhdGhlcmluZyB1bnNwZW50c1xuLy8gICBmb3JjZUNoYW5nZUF0RW5kIC0gZm9yY2UgY2hhbmdlIGFkZHJlc3MgdG8gYmUgbGFzdCBvdXRwdXQgKG9wdGlvbmFsKVxuLy8gICBub1NwbGl0Q2hhbmdlIC0gZGlzYWJsZSBhdXRvbWF0aWMgY2hhbmdlIHNwbGl0dGluZyBmb3IgcHVycG9zZXMgb2YgdW5zcGVudCBtYW5hZ2VtZW50XG4vLyAgIGNoYW5nZUFkZHJlc3MgLSBvdmVycmlkZSB0aGUgY2hhbmdlIGFkZHJlc3MgKG9wdGlvbmFsKVxuLy8gICB2YWxpZGF0ZSAtIGV4dHJhIHZlcmlmaWNhdGlvbiBvZiBjaGFuZ2UgYWRkcmVzc2VzICh3aGljaCBhcmUgYWx3YXlzIHZlcmlmaWVkIHNlcnZlci1zaWRlKSAoZGVmYXVsdHMgdG8gZ2xvYmFsIGNvbmZpZylcbi8vIFJldHVybnM6XG4vLyAgIGNhbGxiYWNrKGVyciwgeyB0cmFuc2FjdGlvbkhleDogc3RyaW5nLCB1bnNwZW50czogW2lucHV0c10sIGZlZTogc2F0b3NoaXMgfSlcbldhbGxldC5wcm90b3R5cGUuY3JlYXRlVHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBfLmV4dGVuZCh7fSwgcGFyYW1zKTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgaWYgKFxuICAgICghXy5pc051bWJlcihwYXJhbXMuZmVlKSAmJiAhXy5pc1VuZGVmaW5lZChwYXJhbXMuZmVlKSkgfHxcbiAgICAoIV8uaXNOdW1iZXIocGFyYW1zLmZlZVJhdGUpICYmICFfLmlzVW5kZWZpbmVkKHBhcmFtcy5mZWVSYXRlKSkgfHxcbiAgICAoIV8uaXNOdW1iZXIocGFyYW1zLm1pbkNvbmZpcm1zKSAmJiAhXy5pc1VuZGVmaW5lZChwYXJhbXMubWluQ29uZmlybXMpKSB8fFxuICAgICghXy5pc0Jvb2xlYW4ocGFyYW1zLmZvcmNlQ2hhbmdlQXRFbmQpICYmICFfLmlzVW5kZWZpbmVkKHBhcmFtcy5mb3JjZUNoYW5nZUF0RW5kKSkgfHxcbiAgICAoIV8uaXNTdHJpbmcocGFyYW1zLmNoYW5nZUFkZHJlc3MpICYmICFfLmlzVW5kZWZpbmVkKHBhcmFtcy5jaGFuZ2VBZGRyZXNzKSkgfHxcbiAgICAoIV8uaXNCb29sZWFuKHBhcmFtcy52YWxpZGF0ZSkgJiYgIV8uaXNVbmRlZmluZWQocGFyYW1zLnZhbGlkYXRlKSkgfHxcbiAgICAoIV8uaXNCb29sZWFuKHBhcmFtcy5pbnN0YW50KSAmJiAhXy5pc1VuZGVmaW5lZChwYXJhbXMuaW5zdGFudCkpXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcmd1bWVudCcpO1xuICB9XG5cbiAgaWYgKCFfLmlzT2JqZWN0KHBhcmFtcy5yZWNpcGllbnRzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0aW5nIHJlY2lwaWVudHMgb2JqZWN0Jyk7XG4gIH1cblxuICBwYXJhbXMudmFsaWRhdGUgPSBwYXJhbXMudmFsaWRhdGUgIT09IHVuZGVmaW5lZCA/IHBhcmFtcy52YWxpZGF0ZSA6IHRoaXMuYml0Z28uZ2V0VmFsaWRhdGUoKTtcbiAgcGFyYW1zLndhbGxldCA9IHRoaXM7XG5cbiAgcmV0dXJuIFRyYW5zYWN0aW9uQnVpbGRlci5jcmVhdGVUcmFuc2FjdGlvbihwYXJhbXMpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHNpZ25UcmFuc2FjdGlvblxuLy8gU2lnbiBhIHByZXZpb3VzbHkgY3JlYXRlZCB0cmFuc2FjdGlvbiB3aXRoIGEga2V5Y2hhaW5cbi8vIFBhcmFtZXRlcnM6XG4vLyB0cmFuc2FjdGlvbkhleCAtIHNlcmlhbGl6ZWQgZm9ybSBvZiB0aGUgdHJhbnNhY3Rpb24gaW4gaGV4XG4vLyB1bnNwZW50cyAtIGFycmF5IG9mIHVuc3BlbnQgaW5mb3JtYXRpb24sIHdoZXJlIGVhY2ggdW5zcGVudCBpcyBhIGNoYWluUGF0aFxuLy8gICAgICAgICAgICBhbmQgcmVkZWVtU2NyaXB0IHdpdGggdGhlIHNhbWUgaW5kZXggYXMgdGhlIGlucHV0cyBpbiB0aGVcbi8vICAgICAgICAgICAgdHJhbnNhY3Rpb25IZXhcbi8vIGtleWNoYWluIC0gS2V5Y2hhaW4gY29udGFpbmluZyB0aGUgeHBydiB0byBzaWduIHdpdGguXG4vLyBzaWduaW5nS2V5IC0gRm9yIGxlZ2FjeSBzYWZlIHdhbGxldHMsIHRoZSBwcml2YXRlIGtleSBzdHJpbmcuXG4vLyB2YWxpZGF0ZSAtIGV4dHJhIHZlcmlmaWNhdGlvbiBvZiBzaWduYXR1cmVzICh3aGljaCBhcmUgYWx3YXlzIHZlcmlmaWVkIHNlcnZlci1zaWRlKSAoZGVmYXVsdHMgdG8gZ2xvYmFsIGNvbmZpZylcbi8vIFJldHVybnM6XG4vLyAgIGNhbGxiYWNrKGVyciwgdHJhbnNhY3Rpb24pXG5XYWxsZXQucHJvdG90eXBlLnNpZ25UcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IF8uZXh0ZW5kKHt9LCBwYXJhbXMpO1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ3RyYW5zYWN0aW9uSGV4J10sIFtdLCBjYWxsYmFjayk7XG5cbiAgaWYgKCFBcnJheS5pc0FycmF5KHBhcmFtcy51bnNwZW50cykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGluZyB0aGUgdW5zcGVudHMgYXJyYXknKTtcbiAgfVxuXG4gIGlmICgoIV8uaXNPYmplY3QocGFyYW1zLmtleWNoYWluKSB8fCAhcGFyYW1zLmtleWNoYWluLnhwcnYpICYmICFfLmlzU3RyaW5nKHBhcmFtcy5zaWduaW5nS2V5KSkge1xuICAgIC8vIGFsbG93IHBhc3NpbmcgaW4gYSBXSUYgcHJpdmF0ZSBrZXkgZm9yIGxlZ2FjeSBzYWZlIHdhbGxldCBzdXBwb3J0XG4gICAgY29uc3QgZXJyb3I6IGFueSA9IG5ldyBFcnJvcignZXhwZWN0aW5nIGtleWNoYWluIG9iamVjdCB3aXRoIHhwcnYgb3Igc2lnbmluZ0tleSBXSUYnKTtcbiAgICBlcnJvci5jb2RlID0gJ21pc3Npbmdfa2V5Y2hhaW5fb3Jfc2lnbmluZ0tleSc7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICBwYXJhbXMudmFsaWRhdGUgPSBwYXJhbXMudmFsaWRhdGUgIT09IHVuZGVmaW5lZCA/IHBhcmFtcy52YWxpZGF0ZSA6IHRoaXMuYml0Z28uZ2V0VmFsaWRhdGUoKTtcbiAgcGFyYW1zLmJpdGdvID0gdGhpcy5iaXRnbztcbiAgcmV0dXJuIFRyYW5zYWN0aW9uQnVpbGRlci5zaWduVHJhbnNhY3Rpb24ocGFyYW1zKVxuICAgIC50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR4OiByZXN1bHQudHJhbnNhY3Rpb25IZXgsXG4gICAgICB9O1xuICAgIH0pXG4gICAgLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHNlbmRcbi8vIFNlbmQgYSB0cmFuc2FjdGlvbiB0byB0aGUgQml0Y29pbiBuZXR3b3JrIHZpYSBCaXRHby5cbi8vIE9uZSBvZiB0aGUga2V5cyBpcyB0eXBpY2FsbHkgc2lnbmVkLCBhbmQgQml0R28gd2lsbCBzaWduIHRoZSBvdGhlciAoaWYgYXBwcm92ZWQpIGFuZCByZWxheSBpdCB0byB0aGUgUDJQIG5ldHdvcmsuXG4vLyBQYXJhbWV0ZXJzOlxuLy8gICB0eCAgLSB0aGUgaGV4IGVuY29kZWQsIHNpZ25lZCB0cmFuc2FjdGlvbiB0byBzZW5kXG4vLyBSZXR1cm5zOlxuLy9cbldhbGxldC5wcm90b3R5cGUuc2VuZFRyYW5zYWN0aW9uID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbJ3R4J10sIFsnbWVzc2FnZScsICdvdHAnXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28ucG9zdCh0aGlzLmJpdGdvLnVybCgnL3R4L3NlbmQnKSkuc2VuZChwYXJhbXMpLnJlc3VsdCgpKVxuICAgIC50aGVuKGZ1bmN0aW9uIChib2R5KSB7XG4gICAgICBpZiAoYm9keS5wZW5kaW5nQXBwcm92YWwpIHtcbiAgICAgICAgcmV0dXJuIF8uZXh0ZW5kKGJvZHksIHsgc3RhdHVzOiAncGVuZGluZ0FwcHJvdmFsJyB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGJvZHkub3RwKSB7XG4gICAgICAgIHJldHVybiBfLmV4dGVuZChib2R5LCB7IHN0YXR1czogJ290cCcgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN0YXR1czogJ2FjY2VwdGVkJyxcbiAgICAgICAgdHg6IGJvZHkudHJhbnNhY3Rpb24sXG4gICAgICAgIGhhc2g6IGJvZHkudHJhbnNhY3Rpb25IYXNoLFxuICAgICAgICBpbnN0YW50OiBib2R5Lmluc3RhbnQsXG4gICAgICAgIGluc3RhbnRJZDogYm9keS5pbnN0YW50SWQsXG4gICAgICB9O1xuICAgIH0pXG4gICAgLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBTaGFyZSB0aGUgd2FsbGV0IHdpdGggYW4gZXhpc3RpbmcgQml0R28gdXNlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyIFRoZSByZWNpcGllbnQncyB1c2VyIGlkLCBtdXN0IGhhdmUgYSBjb3JyZXNwb25kaW5nIHVzZXIgcmVjb3JkIGluIG91ciBkYXRhYmFzZS5cbiAqIEBwYXJhbSB7a2V5Y2hhaW59IGtleWNoYWluIFRoZSBrZXljaGFpbiB0byBiZSBzaGFyZWQgd2l0aCB0aGUgcmVjaXBpZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IHBlcm1pc3Npb25zIEEgY29tbWEtc2VwYXJhdGVkIHZhbHVlIHN0cmluZyB0aGF0IHNwZWNpZmllcyB0aGUgcmVjaXBpZW50J3MgcGVybWlzc2lvbnMgaWYgdGhlIHNoYXJlIGlzIGFjY2VwdGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gYmUgdXNlZCBmb3IgdGhpcyBzaGFyZS5cbiAqL1xuV2FsbGV0LnByb3RvdHlwZS5jcmVhdGVTaGFyZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd1c2VyJywgJ3Blcm1pc3Npb25zJ10sIFtdLCBjYWxsYmFjayk7XG5cbiAgaWYgKHBhcmFtcy5rZXljaGFpbiAmJiAhXy5pc0VtcHR5KHBhcmFtcy5rZXljaGFpbikpIHtcbiAgICBpZiAoXG4gICAgICAhcGFyYW1zLmtleWNoYWluLnhwdWIgfHxcbiAgICAgICFwYXJhbXMua2V5Y2hhaW4uZW5jcnlwdGVkWHBydiB8fFxuICAgICAgIXBhcmFtcy5rZXljaGFpbi5mcm9tUHViS2V5IHx8XG4gICAgICAhcGFyYW1zLmtleWNoYWluLnRvUHViS2V5IHx8XG4gICAgICAhcGFyYW1zLmtleWNoYWluLnBhdGhcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncmVxdWlyZXMga2V5Y2hhaW4gcGFyYW1ldGVycyAtIHhwdWIsIGVuY3J5cHRlZFhwcnYsIGZyb21QdWJLZXksIHRvUHViS2V5LCBwYXRoJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5wb3N0KHRoaXMudXJsKCcvc2hhcmUnKSkuc2VuZChwYXJhbXMpLnJlc3VsdCgpKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBjcmVhdGVJbnZpdGVcbi8vIGludml0ZSBhIG5vbiBCaXRHbyBjdXN0b21lciB0byBqb2luIGEgd2FsbGV0XG4vLyBQYXJhbWV0ZXJzOlxuLy8gICBlbWFpbCAtIHRoZSByZWNpcGllbnQncyBlbWFpbCBhZGRyZXNzXG4vLyAgIHBlcm1pc3Npb25zIC0gdGhlIHJlY2lwaWVudCdzIHBlcm1pc3Npb25zIGlmIHRoZSBzaGFyZSBpcyBhY2NlcHRlZFxuLy8gUmV0dXJuczpcbi8vXG5XYWxsZXQucHJvdG90eXBlLmNyZWF0ZUludml0ZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWydlbWFpbCcsICdwZXJtaXNzaW9ucyddLCBbJ21lc3NhZ2UnXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IG9wdGlvbnM6IGFueSA9IHtcbiAgICB0b0VtYWlsOiBwYXJhbXMuZW1haWwsXG4gICAgcGVybWlzc2lvbnM6IHBhcmFtcy5wZXJtaXNzaW9ucyxcbiAgfTtcblxuICBpZiAocGFyYW1zLm1lc3NhZ2UpIHtcbiAgICBvcHRpb25zLm1lc3NhZ2UgPSBwYXJhbXMubWVzc2FnZTtcbiAgfVxuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28ucG9zdCh0aGlzLnVybCgnL2ludml0ZScpKS5zZW5kKG9wdGlvbnMpLnJlc3VsdCgpKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBjb25maXJtSW52aXRlQW5kU2hhcmVXYWxsZXRcbi8vIGNvbmZpcm0gbXkgaW52aXRlIG9uIHRoaXMgd2FsbGV0IHRvIGEgcmVjaXBpZW50IHdobyBoYXNcbi8vIHN1YnNlcXVlbnRseSBzaWduZWQgdXAgYnkgY3JlYXRpbmcgdGhlIGFjdHVhbCB3YWxsZXQgc2hhcmVcbi8vIFBhcmFtZXRlcnM6XG4vLyAgIHdhbGxldEludml0ZUlkIC0gdGhlIHdhbGxldCBpbnZpdGUgaWRcbi8vICAgd2FsbGV0UGFzc3BocmFzZSAtIHJlcXVpcmVkIGlmIHRoZSB3YWxsZXQgc2hhcmUgc3VjY2VzcyBpcyBleHBlY3RlZFxuLy8gUmV0dXJuczpcbi8vXG5XYWxsZXQucHJvdG90eXBlLmNvbmZpcm1JbnZpdGVBbmRTaGFyZVdhbGxldCA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd3YWxsZXRJbnZpdGVJZCddLCBbJ3dhbGxldFBhc3NwaHJhc2UnXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICByZXR1cm4gdGhpcy5iaXRnb1xuICAgIC53YWxsZXRzKClcbiAgICAubGlzdEludml0ZXMoKVxuICAgIC50aGVuKGZ1bmN0aW9uIChpbnZpdGVzKSB7XG4gICAgICBjb25zdCBvdXRnb2luZyA9IGludml0ZXMub3V0Z29pbmc7XG4gICAgICBjb25zdCBpbnZpdGUgPSBfLmZpbmQob3V0Z29pbmcsIGZ1bmN0aW9uIChvdXQpIHtcbiAgICAgICAgcmV0dXJuIG91dC5pZCA9PT0gcGFyYW1zLndhbGxldEludml0ZUlkO1xuICAgICAgfSk7XG4gICAgICBpZiAoIWludml0ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3dhbGxldCBpbnZpdGUgbm90IGZvdW5kJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgIGVtYWlsOiBpbnZpdGUudG9FbWFpbCxcbiAgICAgICAgcGVybWlzc2lvbnM6IGludml0ZS5wZXJtaXNzaW9ucyxcbiAgICAgICAgbWVzc2FnZTogaW52aXRlLm1lc3NhZ2UsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIHNlbGYuc2hhcmVXYWxsZXQob3B0aW9ucyk7XG4gICAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgICAgcmV0dXJuIHRoaXMuYml0Z28ucHV0KHRoaXMuYml0Z28udXJsKCcvd2FsbGV0aW52aXRlLycgKyBwYXJhbXMud2FsbGV0SW52aXRlSWQpKTtcbiAgICB9KVxuICAgIC5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBzZW5kQ29pbnNcbi8vIFNlbmQgY29pbnMgdG8gYSBkZXN0aW5hdGlvbiBhZGRyZXNzIGZyb20gdGhpcyB3YWxsZXQgdXNpbmcgdGhlIHVzZXIga2V5LlxuLy8gMS4gR2V0cyB0aGUgdXNlciBrZXljaGFpbiBieSBjaGVja2luZyB0aGUgd2FsbGV0IGZvciBhIGtleSB3aGljaCBoYXMgYW4gZW5jcnlwdGVkIHhwcml2XG4vLyAyLiBEZWNyeXB0cyB1c2VyIGtleVxuLy8gMy4gQ3JlYXRlcyB0aGUgdHJhbnNhY3Rpb24gd2l0aCBkZWZhdWx0IGZlZVxuLy8gNC4gU2lnbnMgdHJhbnNhY3Rpb24gd2l0aCBkZWNyeXB0ZWQgdXNlciBrZXlcbi8vIDMuIFNlbmRzIHRoZSB0cmFuc2FjdGlvbiB0byBCaXRHb1xuLy9cbi8vIFBhcmFtZXRlcnM6XG4vLyAgIGFkZHJlc3MgLSB0aGUgZGVzdGluYXRpb24gYWRkcmVzc1xuLy8gICBhbW91bnQgLSB0aGUgYW1vdW50IGluIHNhdG9zaGlzIHRvIGJlIHNlbnRcbi8vICAgbWVzc2FnZSAtIG9wdGlvbmFsIG1lc3NhZ2UgdG8gYXR0YWNoIHRvIHRyYW5zYWN0aW9uXG4vLyAgIHdhbGxldFBhc3NwaHJhc2UgLSB0aGUgcGFzc3BocmFzZSB0byBiZSB1c2VkIHRvIGRlY3J5cHQgdGhlIHVzZXIga2V5IG9uIHRoaXMgd2FsbGV0XG4vLyAgIHhwcnYgLSB0aGUgcHJpdmF0ZSBrZXkgaW4gc3RyaW5nIGZvcm0sIGlmIHdhbGxldFBhc3NwaHJhc2UgaXMgbm90IGF2YWlsYWJsZVxuLy8gICAoU2VlIHRyYW5zYWN0aW9uQnVpbGRlci5jcmVhdGVUcmFuc2FjdGlvbiBmb3Igb3RoZXIgcGFzc3Rocm91Z2ggcGFyYW1zKVxuLy8gUmV0dXJuczpcbi8vXG5XYWxsZXQucHJvdG90eXBlLnNlbmRDb2lucyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWydhZGRyZXNzJ10sIFsnbWVzc2FnZSddLCBjYWxsYmFjayk7XG5cbiAgaWYgKCFfLmlzTnVtYmVyKHBhcmFtcy5hbW91bnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFyZ3VtZW50IGZvciBhbW91bnQgLSBudW1iZXIgZXhwZWN0ZWQnKTtcbiAgfVxuXG4gIHBhcmFtcy5yZWNpcGllbnRzID0ge307XG4gIHBhcmFtcy5yZWNpcGllbnRzW3BhcmFtcy5hZGRyZXNzXSA9IHBhcmFtcy5hbW91bnQ7XG5cbiAgcmV0dXJuIHRoaXMuc2VuZE1hbnkocGFyYW1zKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBzZW5kTWFueVxuLy8gU2VuZCBjb2lucyB0byBtdWx0aXBsZSBkZXN0aW5hdGlvbiBhZGRyZXNzZXMgZnJvbSB0aGlzIHdhbGxldCB1c2luZyB0aGUgdXNlciBrZXkuXG4vLyAxLiBHZXRzIHRoZSB1c2VyIGtleWNoYWluIGJ5IGNoZWNraW5nIHRoZSB3YWxsZXQgZm9yIGEga2V5IHdoaWNoIGhhcyBhbiBlbmNyeXB0ZWQgeHByaXZcbi8vIDIuIERlY3J5cHRzIHVzZXIga2V5XG4vLyAzLiBDcmVhdGVzIHRoZSB0cmFuc2FjdGlvbiB3aXRoIGRlZmF1bHQgZmVlXG4vLyA0LiBTaWducyB0cmFuc2FjdGlvbiB3aXRoIGRlY3J5cHRlZCB1c2VyIGtleVxuLy8gMy4gU2VuZHMgdGhlIHRyYW5zYWN0aW9uIHRvIEJpdEdvXG4vL1xuLy8gUGFyYW1ldGVyczpcbi8vICAgcmVjaXBpZW50cyAtIGFycmF5IG9mIHsgYWRkcmVzczogc3RyaW5nLCBhbW91bnQ6IG51bWJlciwgdHJhdmVsSW5mbzogb2JqZWN0IH0gdG8gc2VuZCB0b1xuLy8gICB3YWxsZXRQYXNzcGhyYXNlIC0gdGhlIHBhc3NwaHJhc2UgdG8gYmUgdXNlZCB0byBkZWNyeXB0IHRoZSB1c2VyIGtleSBvbiB0aGlzIHdhbGxldFxuLy8gICB4cHJ2IC0gdGhlIHByaXZhdGUga2V5IGluIHN0cmluZyBmb3JtLCBpZiB3YWxsZXRQYXNzcGhyYXNlIGlzIG5vdCBhdmFpbGFibGVcbi8vICAgKFNlZSB0cmFuc2FjdGlvbkJ1aWxkZXIuY3JlYXRlVHJhbnNhY3Rpb24gZm9yIG90aGVyIHBhc3N0aHJvdWdoIHBhcmFtcylcbi8vIFJldHVybnM6XG4vL1xuV2FsbGV0LnByb3RvdHlwZS5zZW5kTWFueSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFsnbWVzc2FnZScsICdvdHAnXSwgY2FsbGJhY2spO1xuICBjb25zdCBzZWxmID0gdGhpcztcblxuICBpZiAoIV8uaXNPYmplY3QocGFyYW1zLnJlY2lwaWVudHMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgcmVjaXBpZW50cyBvYmplY3QnKTtcbiAgfVxuXG4gIGlmIChwYXJhbXMuZmVlICYmICFfLmlzTnVtYmVyKHBhcmFtcy5mZWUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFyZ3VtZW50IGZvciBmZWUgLSBudW1iZXIgZXhwZWN0ZWQnKTtcbiAgfVxuXG4gIGlmIChwYXJhbXMuZmVlUmF0ZSAmJiAhXy5pc051bWJlcihwYXJhbXMuZmVlUmF0ZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYXJndW1lbnQgZm9yIGZlZVJhdGUgLSBudW1iZXIgZXhwZWN0ZWQnKTtcbiAgfVxuXG4gIGlmIChwYXJhbXMuaW5zdGFudCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmluc3RhbnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFyZ3VtZW50IGZvciBpbnN0YW50IC0gYm9vbGVhbiBleHBlY3RlZCcpO1xuICB9XG5cbiAgbGV0IGJpdGdvRmVlO1xuICBsZXQgdHJhdmVsSW5mb3M7XG4gIGxldCBmaW5hbFJlc3VsdDtcbiAgbGV0IHVuc3BlbnRzVXNlZDtcblxuICBjb25zdCBhY2NlcHRlZEJ1aWxkUGFyYW1zID0gW1xuICAgICdudW1CbG9ja3MnLFxuICAgICdmZWVSYXRlJyxcbiAgICAnbWluQ29uZmlybXMnLFxuICAgICdlbmZvcmNlTWluQ29uZmlybXNGb3JDaGFuZ2UnLFxuICAgICd0YXJnZXRXYWxsZXRVbnNwZW50cycsXG4gICAgJ21lc3NhZ2UnLFxuICAgICdtaW5WYWx1ZScsXG4gICAgJ21heFZhbHVlJyxcbiAgICAnbm9TcGxpdENoYW5nZScsXG4gICAgJ2NvbW1lbnQnLFxuICBdO1xuICBjb25zdCBwcmVzZXJ2ZWRCdWlsZFBhcmFtcyA9IF8ucGljayhwYXJhbXMsIGFjY2VwdGVkQnVpbGRQYXJhbXMpO1xuXG4gIC8vIEdldCB0aGUgdXNlciBrZXljaGFpblxuICBjb25zdCByZXRQcm9taXNlID0gdGhpcy5jcmVhdGVBbmRTaWduVHJhbnNhY3Rpb24ocGFyYW1zKVxuICAgIC50aGVuKGZ1bmN0aW9uICh0cmFuc2FjdGlvbikge1xuICAgICAgLy8gU2VuZCB0aGUgdHJhbnNhY3Rpb25cbiAgICAgIGJpdGdvRmVlID0gdHJhbnNhY3Rpb24uYml0Z29GZWU7XG4gICAgICB0cmF2ZWxJbmZvcyA9IHRyYW5zYWN0aW9uLnRyYXZlbEluZm9zO1xuICAgICAgdW5zcGVudHNVc2VkID0gdHJhbnNhY3Rpb24udW5zcGVudHM7XG4gICAgICByZXR1cm4gc2VsZi5zZW5kVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eDogdHJhbnNhY3Rpb24udHgsXG4gICAgICAgIG1lc3NhZ2U6IHBhcmFtcy5tZXNzYWdlLFxuICAgICAgICBzZXF1ZW5jZUlkOiBwYXJhbXMuc2VxdWVuY2VJZCxcbiAgICAgICAgaW5zdGFudDogcGFyYW1zLmluc3RhbnQsXG4gICAgICAgIG90cDogcGFyYW1zLm90cCxcbiAgICAgICAgLy8gVGhlIGJlbG93IHBhcmFtcyBhcmUgZm9yIGxvZ2dpbmcgb25seSwgYW5kIGRvIG5vdCBpbXBhY3QgdGhlIEFQSSBjYWxsXG4gICAgICAgIGVzdGltYXRlZFNpemU6IHRyYW5zYWN0aW9uLmVzdGltYXRlZFNpemUsXG4gICAgICAgIGJ1aWxkUGFyYW1zOiBwcmVzZXJ2ZWRCdWlsZFBhcmFtcyxcbiAgICAgIH0pO1xuICAgIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgY29uc3QgdHggPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleChyZXN1bHQudHgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICBjb25zdCBpbnB1dHNTdW0gPSBfLnN1bUJ5KHVuc3BlbnRzVXNlZCwgJ3ZhbHVlJyk7XG4gICAgICBjb25zdCBvdXRwdXRzU3VtID0gXy5zdW1CeSh0eC5vdXRzLCAndmFsdWUnKTtcbiAgICAgIGNvbnN0IGZlZVVzZWQgPSBpbnB1dHNTdW0gLSBvdXRwdXRzU3VtO1xuICAgICAgaWYgKGlzTmFOKGZlZVVzZWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBmZWVVc2VkJyk7XG4gICAgICB9XG4gICAgICAocmVzdWx0LmZlZSA9IGZlZVVzZWQpLCAocmVzdWx0LmZlZVJhdGUgPSAoZmVlVXNlZCAqIDEwMDApIC8gdHgudmlydHVhbFNpemUoKSk7XG4gICAgICByZXN1bHQudHJhdmVsSW5mb3MgPSB0cmF2ZWxJbmZvcztcbiAgICAgIGlmIChiaXRnb0ZlZSkge1xuICAgICAgICByZXN1bHQuYml0Z29GZWUgPSBiaXRnb0ZlZTtcbiAgICAgIH1cbiAgICAgIGZpbmFsUmVzdWx0ID0gcmVzdWx0O1xuXG4gICAgICAvLyBIYW5kbGUgc2VuZGluZyB0cmF2ZWwgaW5mb3MgaWYgdGhleSBleGlzdCwgYnV0IG1ha2Ugc3VyZSB3ZSBuZXZlciBmYWlsIGhlcmUuXG4gICAgICAvLyBFcnJvciBvciByZXN1bHQgKHdpdGggcG9zc2libGUgc3ViLWVycm9ycykgd2lsbCBiZSBwcm92aWRlZCBpbiB0cmF2ZWxSZXN1bHRcbiAgICAgIGlmICh0cmF2ZWxJbmZvcyAmJiB0cmF2ZWxJbmZvcy5sZW5ndGgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gc2VsZlxuICAgICAgICAgICAgLnBvbGxGb3JUcmFuc2FjdGlvbih7IGlkOiByZXN1bHQuaGFzaCB9KVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICByZXR1cm4gc2VsZi5iaXRnby50cmF2ZWxSdWxlKCkuc2VuZE1hbnkocmVzdWx0KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICAgICAgICAgIGZpbmFsUmVzdWx0LnRyYXZlbFJlc3VsdCA9IHJlcztcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAvLyBjYXRjaCBhc3luYyBlcnJvcnNcbiAgICAgICAgICAgICAgZmluYWxSZXN1bHQudHJhdmVsUmVzdWx0ID0geyBlcnJvcjogZXJyLm1lc3NhZ2UgfTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAvLyBjYXRjaCBzeW5jaHJvbm91cyBlcnJvcnNcbiAgICAgICAgICBmaW5hbFJlc3VsdC50cmF2ZWxSZXN1bHQgPSB7IGVycm9yOiBlcnIubWVzc2FnZSB9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gZmluYWxSZXN1bHQ7XG4gICAgfSk7XG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHJldFByb21pc2UpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBBY2NlbGVyYXRlIGEgc3R1Y2sgdHJhbnNhY3Rpb24gdXNpbmcgQ2hpbGQtUGF5cy1Gb3ItUGFyZW50IChDUEZQKS5cbiAqXG4gKiBUaGlzIHNob3VsZCBvbmx5IGJlIHVzZWQgZm9yIHN0dWNrIHRyYW5zYWN0aW9ucyB3aGljaCBoYXZlIG5vIHVuY29uZmlybWVkIGlucHV0cy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIC0gSW5wdXQgcGFyYW1ldGVyc1xuICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy50cmFuc2FjdGlvbklEIC0gSUQgb2YgdHJhbnNhY3Rpb24gdG8gYWNjZWxlcmF0ZVxuICogQHBhcmFtIHtOdW1iZXJ9IHBhcmFtcy5mZWVSYXRlIC0gTmV3IGVmZmVjdGl2ZSBmZWUgcmF0ZSBmb3Igc3R1Y2sgdHJhbnNhY3Rpb24gKHNhdCBwZXIgMTAwMCBieXRlcylcbiAqIEBwYXJhbSB7TnVtYmVyfSBwYXJhbXMubWF4QWRkaXRpb25hbFVuc3BlbnRzIC0gTWF4aW11bSBhZGRpdGlvbmFsIHVuc3BlbnRzIHRvIHVzZSBmcm9tIHRoZSB3YWxsZXQgdG8gY292ZXIgYW55IGNoaWxkIGZlZXMgdGhhdCB0aGUgcGFyZW50IHVuc3BlbnQgb3V0cHV0IGNhbm5vdCBjb3Zlci4gRGVmYXVsdHMgdG8gMTAwLlxuICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlIC0gVGhlIHBhc3NwaHJhc2Ugd2hpY2ggc2hvdWxkIGJlIHVzZWQgdG8gZGVjcnlwdCB0aGUgd2FsbGV0IHByaXZhdGUga2V5LiBPbmUgb2YgZWl0aGVyIHdhbGxldFBhc3NwaHJhc2Ugb3IgeHBydiBpcyByZXF1aXJlZC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXJhbXMueHBydiAtIFRoZSBwcml2YXRlIGtleSBmb3IgdGhlIHdhbGxldC4gT25lIG9mIGVpdGhlciB3YWxsZXRQYXNzcGhyYXNlIG9yIHhwcnYgaXMgcmVxdWlyZWQuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICogQHJldHVybnMgUmVzdWx0IG9mIHNlbmRUcmFuc2FjdGlvbigpIG9uIHRoZSBjaGlsZCB0cmFuc2FjdGlvblxuICovXG5XYWxsZXQucHJvdG90eXBlLmFjY2VsZXJhdGVUcmFuc2FjdGlvbiA9IGZ1bmN0aW9uIGFjY2VsZXJhdGVUcmFuc2FjdGlvbihwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGVzdGltYXRlIGEgdHJhbnNhY3Rpb25zIHNpemUgaW4gdmlydHVhbCBieXRlcy5cbiAgICogQWN0dWFsIHRyYW5zYWN0aW9ucyBtYXkgYmUgc2xpZ2h0bHkgZmV3ZXIgdmlydHVhbCBieXRlcywgZHVlIHRvXG4gICAqIHRoZSBmYWN0IHRoYXQgdmFsaWQgRUNTREEgc2lnbmF0dXJlcyBoYXZlIGEgdmFyaWFibGUgbGVuZ3RoXG4gICAqIGJldHdlZW4gOCBhbmQgNzMgdmlydHVhbCBieXRlcy5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0cy5zZWd3aXQgVGhlIG51bWJlciBvZiBzZWd3aXQgaW5wdXRzIHRvIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gaW5wdXRzLlAyU0ggVGhlIG51bWJlciBvZiBQMlNIIGlucHV0cyB0byB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGlucHV0cy5QMlBLSCBUaGUgbnVtYmVyIG9mIFAyUEtIIGlucHV0cyB0byB0aGUgdHJhbnNhY3Rpb25cbiAgICovXG4gIGNvbnN0IGVzdGltYXRlVHhWU2l6ZSA9IChpbnB1dHMpID0+IHtcbiAgICBjb25zdCBzZWd3aXQgPSBpbnB1dHMuc2Vnd2l0IHx8IDA7XG4gICAgY29uc3QgUDJTSCA9IGlucHV0cy5QMlNIIHx8IDA7XG4gICAgY29uc3QgUDJQS0ggPSBpbnB1dHMuUDJQS0ggfHwgMDtcblxuICAgIGNvbnN0IGNoaWxkRmVlSW5mbyA9IFRyYW5zYWN0aW9uQnVpbGRlci5jYWxjdWxhdGVNaW5lckZlZUluZm8oe1xuICAgICAgblAyc2hJbnB1dHM6IFAyU0gsXG4gICAgICBuUDJwa2hJbnB1dHM6IFAyUEtILFxuICAgICAgblAyc2hQMndzaElucHV0czogc2Vnd2l0LFxuICAgICAgbk91dHB1dHM6IDEsXG4gICAgICBmZWVSYXRlOiAxLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNoaWxkRmVlSW5mby5zaXplO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiBzYXRvc2hpcyB0aGF0IHNob3VsZCBiZSBwYWlkIGluIGZlZXMgYnkgdGhlIGNoaWxkIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBpbnB1dHMgSW5wdXRzIHRvIHRoZSBjaGlsZCB0cmFuc2FjdGlvbiB3aGljaCBhcmUgcGFzc2VkIHRvIGVzdGltYXRlVHhWU2l6ZVxuICAgKiBAcGFyYW0gcGFyZW50RmVlIFRoZSBudW1iZXIgb2Ygc2F0b3NoaXMgdGhlIHBhcmVudCB0eCBvcmlnaW5hbGx5IHBhaWQgaW4gZmVlc1xuICAgKiBAcGFyYW0gcGFyZW50VlNpemUgVGhlIG51bWJlciBvZiB2aXJ0dWFsIGJ5dGVzIGluIHRoZSBwYXJlbnQgdHhcbiAgICogQHBhcmFtIGZlZVJhdGUgVGhlIG5ldyBmZWUgcmF0ZSB3aGljaCBzaG91bGQgYmUgcGFpZCBieSB0aGUgY29tYmluZWQgQ1BGUCB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIHNhdG9zaGlzIHRoZSBjaGlsZCB0eCBzaG91bGQgcGF5IGluIGZlZXNcbiAgICovXG4gIGNvbnN0IGVzdGltYXRlQ2hpbGRGZWUgPSAoeyBpbnB1dHMsIHBhcmVudEZlZSwgcGFyZW50VlNpemUsIGZlZVJhdGUgfSkgPT4ge1xuICAgIC8vIGNhbGN1bGF0ZSBob3cgbXVjaCBtb3JlIHdlICpzaG91bGQqIGhhdmUgcGFpZCBpbiBwYXJlbnQgZmVlcyxcbiAgICAvLyBoYWQgdGhlIHBhcmVudCBiZWVuIG9yaWdpbmFsbHkgc2VudCB3aXRoIHRoZSBuZXcgZmVlIHJhdGVcbiAgICBjb25zdCBhZGRpdGlvbmFsUGFyZW50RmVlID0gXy5jZWlsKChwYXJlbnRWU2l6ZSAqIGZlZVJhdGUpIC8gMTAwMCkgLSBwYXJlbnRGZWU7XG5cbiAgICAvLyBjYWxjdWxhdGUgaG93IG11Y2ggd2Ugd291bGQgcGF5IGluIGZlZXMgZm9yIHRoZSBjaGlsZCxcbiAgICAvLyBpZiBpdCB3ZXJlIG9ubHkgcGF5aW5nIGZvciBpdHNlbGYgYXQgdGhlIG5ldyBmZWUgcmF0ZVxuICAgIGNvbnN0IGNoaWxkRmVlID0gKGVzdGltYXRlVHhWU2l6ZShpbnB1dHMpICogZmVlUmF0ZSkgLyAxMDAwO1xuXG4gICAgcmV0dXJuIF8uY2VpbChjaGlsZEZlZSArIGFkZGl0aW9uYWxQYXJlbnRGZWUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gZmluZCBhZGRpdGlvbmFsIHVuc3BlbnRzIHRvIHVzZSB0byBwYXkgdGhlIGNoaWxkIHR4IGZlZXMuXG4gICAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIHdoZW4gdGhlIHRoZSBwYXJlbnQgdHggb3V0cHV0IGlzIG5vdCBzdWZmaWNpZW50IHRvXG4gICAqIGNvdmVyIHRoZSB0b3RhbCBmZWVzIHdoaWNoIHNob3VsZCBiZSBwYWlkIGJ5IHRoZSBjaGlsZCB0eC5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0cyBJbnB1dHMgdG8gdGhlIGNoaWxkIHRyYW5zYWN0aW9uIHdoaWNoIGFyZSBwYXNzZWQgdG8gZXN0aW1hdGVUeFZTaXplXG4gICAqIEBwYXJhbSBwYXJlbnRPdXRwdXRWYWx1ZSBUaGUgdmFsdWUgb2YgdGhlIG91dHB1dCBmcm9tIHRoZSBwYXJlbnQgdHggd2hpY2ggd2UgYXJlIHVzaW5nIGFzIGFuIGlucHV0IHRvIHRoZSBjaGlsZCB0eFxuICAgKiBAcGFyYW0gcGFyZW50RmVlIFRoZSBudW1iZXIgb2Ygc2F0b3NoaXMgdGhlIHBhcmVudCB0eCBvcmlnaW5hbGx5IHBhaWQgaW4gZmVlc1xuICAgKiBAcGFyYW0gcGFyZW50VlNpemUgVGhlIG51bWJlciBvZiB2aXJ0dWFsIGJ5dGVzIGluIHRoZSBwYXJlbnQgdHhcbiAgICogQHBhcmFtIG1heFVuc3BlbnRzIFRoZSBtYXhpbXVtIG51bWJlciBvZiBhZGRpdGlvbmFsIHVuc3BlbnRzIHdoaWNoIHNob3VsZCBiZSB1c2VkIHRvIGNvdmVyIHRoZSByZW1haW5pbmcgY2hpbGQgZmVlc1xuICAgKiBAcmV0dXJucyBBbiBvYmplY3Qgd2l0aCB0aGUgYWRkaXRpb25hbCB1bnNwZW50cyB0byB1c2UsIHRoZSB1cGRhdGVkIG51bWJlciBvZiBzYXRvc2hpcyB3aGljaCBzaG91bGQgYmUgcGFpZCBieVxuICAgKiAgICAgICAgICB0aGUgY2hpbGQgdHgsIGFuZCB0aGUgdXBkYXRlZCBpbnB1dHMgZm9yIHRoZSBjaGlsZCB0eC5cbiAgICovXG4gIGNvbnN0IGZpbmRBZGRpdGlvbmFsVW5zcGVudHMgPSAoeyBpbnB1dHMsIHBhcmVudE91dHB1dFZhbHVlLCBwYXJlbnRGZWUsIHBhcmVudFZTaXplLCBtYXhVbnNwZW50cyB9KSA9PiB7XG4gICAgcmV0dXJuIGNvKGZ1bmN0aW9uKiBjb0ZpbmRBZGRpdGlvbmFsVW5zcGVudHMoKSB7XG4gICAgICBjb25zdCBhZGRpdGlvbmFsVW5zcGVudHM6IGFueVtdID0gW107XG5cbiAgICAgIC8vIGFzayB0aGUgc2VydmVyIGZvciBlbm91Z2ggdW5zcGVudHMgdG8gY292ZXIgdGhlIGNoaWxkIGZlZSwgYXNzdW1pbmdcbiAgICAgIC8vIHRoYXQgaXQgY2FuIGJlIGRvbmUgd2l0aG91dCBhZGRpdGlvbmFsIHVuc3BlbnRzICh3aGljaCBpcyBub3QgcG9zc2libGUsXG4gICAgICAvLyBzaW5jZSBpZiB0aGF0IHdlcmUgdGhlIGNhc2UsIGZpbmRBZGRpdGlvbmFsVW5zcGVudHMgd291bGQgbm90IGhhdmUgYmVlblxuICAgICAgLy8gY2FsbGVkIGluIHRoZSBmaXJzdCBwbGFjZS4gVGhpcyB3aWxsIGJlIGNvcnJlY3RlZCBiZWZvcmUgcmV0dXJuaW5nKVxuICAgICAgbGV0IGN1cnJlbnRDaGlsZEZlZUVzdGltYXRlID0gZXN0aW1hdGVDaGlsZEZlZSh7IGlucHV0cywgcGFyZW50RmVlLCBwYXJlbnRWU2l6ZSwgZmVlUmF0ZTogcGFyYW1zLmZlZVJhdGUgfSk7XG4gICAgICBsZXQgdW5jb3ZlcmVkQ2hpbGRGZWUgPSBjdXJyZW50Q2hpbGRGZWVFc3RpbWF0ZSAtIHBhcmVudE91dHB1dFZhbHVlO1xuXG4gICAgICB3aGlsZSAodW5jb3ZlcmVkQ2hpbGRGZWUgPiAwICYmIGFkZGl0aW9uYWxVbnNwZW50cy5sZW5ndGggPCBtYXhVbnNwZW50cykge1xuICAgICAgICAvLyB0cnkgdG8gZ2V0IGVub3VnaCB1bnNwZW50cyB0byBjb3ZlciB0aGUgcmVzdCBvZiB0aGUgY2hpbGQgZmVlXG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgICAgIGNvbnN0IHVuc3BlbnRzID0gKHlpZWxkIHRoaXMudW5zcGVudHMoe1xuICAgICAgICAgIG1pbkNvbmZpcm1zOiAxLFxuICAgICAgICAgIHRhcmdldDogdW5jb3ZlcmVkQ2hpbGRGZWUsXG4gICAgICAgICAgbGltaXQ6IG1heFVuc3BlbnRzIC0gYWRkaXRpb25hbFVuc3BlbnRzLmxlbmd0aCxcbiAgICAgICAgfSkpIGFzIGFueTtcblxuICAgICAgICBpZiAodW5zcGVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgLy8gbm8gbW9yZSB1bnNwZW50cyBhcmUgYXZhaWxhYmxlXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgYWRkaXRpb25hbFVuc3BlbnRWYWx1ZSA9IDA7XG5cbiAgICAgICAgLy8gY29uc3VtZSBhbGwgdW5zcGVudHMgcmV0dXJuZWQgYnkgdGhlIHNlcnZlciwgZXZlbiBpZiB3ZSBkb24ndCBuZWVkXG4gICAgICAgIC8vIGFsbCBvZiB0aGVtIHRvIGNvdmVyIHRoZSBjaGlsZCBmZWUuIFRoaXMgaXMgYmVjYXVzZSB0aGUgc2VydmVyIHdpbGxcbiAgICAgICAgLy8gcmV0dXJuIGVub3VnaCB1bnNwZW50IHZhbHVlIHRvIGVuc3VyZSB0aGF0IHRoZSBtaW5pbXVtIGNoYW5nZSBhbW91bnRcbiAgICAgICAgLy8gaXMgYWNoaWV2ZWQgZm9yIHRoZSBjaGlsZCB0eCwgYW5kIHdlIGNhbid0IGxlYXZlIG91dCB0aG9zZSB1bnNwZW50c1xuICAgICAgICAvLyBvciBlbHNlIHRoZSBtaW5pbXVtIGNoYW5nZSBhbW91bnQgY29uc3RyYWludCBjb3VsZCBiZSB2aW9sYXRlZFxuICAgICAgICBfLmZvckVhY2godW5zcGVudHMsICh1bnNwZW50KSA9PiB7XG4gICAgICAgICAgLy8gdXBkYXRlIHRoZSBjaGlsZCB0eCBpbnB1dHNcbiAgICAgICAgICBjb25zdCB1bnNwZW50Q2hhaW4gPSBnZXRDaGFpbih1bnNwZW50KTtcbiAgICAgICAgICBpZiAoaXNDaGFpbkNvZGUodW5zcGVudENoYWluKSAmJiBzY3JpcHRUeXBlRm9yQ2hhaW4odW5zcGVudENoYWluKSA9PT0gJ3Ayc2hQMndzaCcpIHtcbiAgICAgICAgICAgIGlucHV0cy5zZWd3aXQrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5wdXRzLlAyU0grKztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBhZGRpdGlvbmFsVW5zcGVudHMucHVzaCh1bnNwZW50KTtcbiAgICAgICAgICBhZGRpdGlvbmFsVW5zcGVudFZhbHVlICs9IHVuc3BlbnQudmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGN1cnJlbnRDaGlsZEZlZUVzdGltYXRlID0gZXN0aW1hdGVDaGlsZEZlZSh7IGlucHV0cywgcGFyZW50RmVlLCBwYXJlbnRWU2l6ZSwgZmVlUmF0ZTogcGFyYW1zLmZlZVJhdGUgfSk7XG4gICAgICAgIHVuY292ZXJlZENoaWxkRmVlID0gY3VycmVudENoaWxkRmVlRXN0aW1hdGUgLSBwYXJlbnRPdXRwdXRWYWx1ZSAtIGFkZGl0aW9uYWxVbnNwZW50VmFsdWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh1bmNvdmVyZWRDaGlsZEZlZSA+IDApIHtcbiAgICAgICAgLy8gVW5hYmxlIHRvIGZpbmQgZW5vdWdoIHVuc3BlbnRzIHRvIGNvdmVyIHRoZSBjaGlsZCBmZWVcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnN1ZmZpY2llbnQgY29uZmlybWVkIHVuc3BlbnRzIGF2YWlsYWJsZSB0byBjb3ZlciB0aGUgY2hpbGQgZmVlYCk7XG4gICAgICB9XG5cbiAgICAgIC8vIGZvdW5kIGVub3VnaCB1bnNwZW50c1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkaXRpb25hbDogYWRkaXRpb25hbFVuc3BlbnRzLFxuICAgICAgICBuZXdDaGlsZEZlZTogY3VycmVudENoaWxkRmVlRXN0aW1hdGUsXG4gICAgICAgIG5ld0lucHV0czogaW5wdXRzLFxuICAgICAgfTtcbiAgICB9KS5jYWxsKHRoaXMpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IGEgZnVsbCBjb3B5IChpbmNsdWRpbmcgd2l0bmVzcyBkYXRhKSBvZiBhbiBhcmJpdHJhcnkgdHggdXNpbmcgb25seSB0aGUgdHggaWQuXG4gICAqXG4gICAqIFdlIGhhdmUgdG8gdXNlIGFuIGV4dGVybmFsIHNlcnZpY2UgZm9yIHRoaXMgKGN1cnJlbnRseSBibG9ja3N0cmVhbS5pbmZvKSwgc2luY2VcbiAgICogdGhlIHYxIGluZGV4ZXIgc2VydmljZSAoYmFzZWQgb24gYml0Y29pbmopIGRvZXMgbm90IGhhdmUgc2Vnd2l0IHN1cHBvcnQgYW5kXG4gICAqIGRvZXMgbm90IHJldHVybiBhbnkgc2Vnd2l0IHJlbGF0ZWQgZmllbGRzIGluIHRoZSB0eCBoZXguXG4gICAqXG4gICAqIEBwYXJhbSBwYXJlbnRUeElkIFRoZSBJRCBvZiB0aGUgdHJhbnNhY3Rpb24gdG8gZ2V0IHRoZSBmdWxsIGhleCBvZlxuICAgKiBAcmV0dXJucyB7Qmx1ZWJpcmQ8YW55Pn0gVGhlIGZ1bGwgaGV4IGZvciB0aGUgc3BlY2lmaWVkIHRyYW5zYWN0aW9uXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBnZXRQYXJlbnRUeEhleCh7IHBhcmVudFR4SWQgfTogeyBwYXJlbnRUeElkOiBzdHJpbmcgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgZXhwbG9yZXJCYXNlVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tzZWxmLmJpdGdvLmdldEVudigpXS5idGNFeHBsb3JlckJhc2VVcmw7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVxdWVzdC5nZXQoYCR7ZXhwbG9yZXJCYXNlVXJsfS90eC8ke3BhcmVudFR4SWR9L2hleGApO1xuXG4gICAgaWYgKCFyZXN1bHQudGV4dCB8fCAhLyhbYS1mMC05XXsyfSkrLy50ZXN0KHJlc3VsdC50ZXh0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRGlkIG5vdCBzdWNjZXNzZnVsbHkgcmVjZWl2ZSBwYXJlbnQgdHggaGV4LiBSZWNlaXZlZCAnJHtfLnRydW5jYXRlKHJlc3VsdC50ZXh0LCB7IGxlbmd0aDogMTAwIH0pfScgaW5zdGVhZC5gXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQudGV4dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IHRoZSBjaGFpbiBmcm9tIGFuIHVuc3BlbnQgb3IgdHggb3V0cHV0LlxuICAgKlxuICAgKiBAcGFyYW0gb3V0cHV0T3JVbnNwZW50IFRoZSBvdXRwdXQgb3IgdW5zcGVudCB3aG9zZSBjaGFpbiBzaG91bGQgYmUgZGV0ZXJtaW5lZFxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgY2hhaW4gZm9yIHRoZSBnaXZlbiBvdXRwdXQgb3IgdW5zcGVudFxuICAgKi9cbiAgY29uc3QgZ2V0Q2hhaW4gPSAob3V0cHV0T3JVbnNwZW50KSA9PiB7XG4gICAgaWYgKG91dHB1dE9yVW5zcGVudC5jaGFpbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gb3V0cHV0T3JVbnNwZW50LmNoYWluO1xuICAgIH1cblxuICAgIGlmIChvdXRwdXRPclVuc3BlbnQuY2hhaW5QYXRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBfLnRvTnVtYmVyKG91dHB1dE9yVW5zcGVudC5jaGFpblBhdGguc3BsaXQoJy8nKVsxXSk7XG4gICAgfVxuXG4gICAgLy8gbm8gd2F5IHRvIHRlbGwgdGhlIGNoYWluLCBsZXQncyBqdXN0IGJsb3cgdXAgbm93IGluc3RlYWRcbiAgICAvLyBvZiBibG93aW5nIHVwIGxhdGVyIHdoZW4gdGhlIHVuZGVmaW5lZCByZXR1cm4gdmFsdWUgaXMgdXNlZC5cbiAgICAvLyBOb3RlOiBmb3IgdW5zcGVudHMgdGhlIGZpZWxkIHRvIHVzZSBpcyAnYWRkcmVzcycsIGJ1dCBmb3Igb3V0cHV0c1xuICAgIC8vIHRoZSBmaWVsZCB0byB1c2UgaXMgJ2FjY291bnQnXG4gICAgdGhyb3cgRXJyb3IoYENvdWxkIG5vdCBnZXQgY2hhaW4gZm9yIG91dHB1dCBvbiBhY2NvdW50ICR7b3V0cHV0T3JVbnNwZW50LmFjY291bnQgfHwgb3V0cHV0T3JVbnNwZW50LmFkZHJlc3N9YCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEhlbHBlciBmdW5jdGlvbiB0byBjYWxjdWxhdGUgdGhlIGFjdHVhbCB2YWx1ZSBjb250cmlidXRpb24gYW4gb3V0cHV0IG9yIHVuc3BlbnQgd2lsbFxuICAgKiBjb250cmlidXRlIHRvIGEgdHJhbnNhY3Rpb24sIHdlcmUgaXQgdG8gYmUgdXNlZC4gRWFjaCB0eXBlIG9mIG91dHB1dCBvciB1bnNwZW50XG4gICAqIHdpbGwgaGF2ZSBhIGRpZmZlcmVudCB2YWx1ZSBjb250cmlidXRpb24gc2luY2UgZWFjaCB0eXBlIGhhcyBhIGRpZmZlcmVudCBudW1iZXJcbiAgICogb2YgdmlydHVhbCBieXRlcywgYW5kIHRodXMgd2lsbCBjYXVzZSBhIGRpZmZlcmVudCBmZWUgdG8gYmUgcGFpZC5cbiAgICpcbiAgICogQHBhcmFtIG91dHB1dE9yVW5zcGVudCBPdXRwdXQgb3IgdW5zcGVudCB3aG9zZSBlZmZlY3RpdmUgdmFsdWUgc2hvdWxkIGJlIGRldGVybWluZWRcbiAgICogQHJldHVybnMge251bWJlcn0gVGhlIGFjdHVhbCBudW1iZXIgb2Ygc2F0b3NoaXMgdGhhdCB0aGlzIHVuc3BlbnQgb3Igb3V0cHV0XG4gICAqICAgICAgICAgICAgICAgICAgIHdvdWxkIGNvbnRyaWJ1dGUgdG8gYSB0cmFuc2FjdGlvbiwgd2VyZSBpdCB0byBiZSB1c2VkLlxuICAgKi9cbiAgY29uc3QgZWZmZWN0aXZlVmFsdWUgPSAob3V0cHV0T3JVbnNwZW50KSA9PiB7XG4gICAgY29uc3QgY2hhaW4gPSBnZXRDaGFpbihvdXRwdXRPclVuc3BlbnQpO1xuICAgIGlmIChpc0NoYWluQ29kZShjaGFpbikgJiYgc2NyaXB0VHlwZUZvckNoYWluKGNoYWluKSA9PT0gJ3Ayc2hQMndzaCcpIHtcbiAgICAgIC8vIFZpcnR1YWxTaXplcy50eFAyc2hQMndzaElucHV0U2l6ZSBpcyBpbiBieXRlcywgc28gd2UgbmVlZCB0byBjb252ZXJ0IHRvIGtCXG4gICAgICByZXR1cm4gb3V0cHV0T3JVbnNwZW50LnZhbHVlIC0gKFZpcnR1YWxTaXplcy50eFAyc2hQMndzaElucHV0U2l6ZSAqIHBhcmFtcy5mZWVSYXRlKSAvIDEwMDA7XG4gICAgfVxuICAgIC8vIFZpcnR1YWxTaXplcy50eFAyc2hJbnB1dFNpemUgaXMgaW4gYnl0ZXMsIHNvIHdlIG5lZWQgdG8gY29udmVydCB0byBrQlxuICAgIHJldHVybiBvdXRwdXRPclVuc3BlbnQudmFsdWUgLSAoVmlydHVhbFNpemVzLnR4UDJzaElucHV0U2l6ZSAqIHBhcmFtcy5mZWVSYXRlKSAvIDEwMDA7XG4gIH07XG5cbiAgLyoqXG4gICAqIENvcm91dGluZSB3aGljaCBhY3R1YWxseSBpbXBsZW1lbnRzIHRoZSBhY2NlbGVyYXRlVHJhbnNhY3Rpb24gYWxnb3JpdGhtXG4gICAqXG4gICAqIERlc2NyaWJlZCBhdCBhIGhpZ2ggbGV2ZWwsIHRoZSBhbGdvcml0aG0gaXMgYXMgZm9sbG93czpcbiAgICogMSkgRmluZCBhcHByb3ByaWF0ZSBvdXRwdXQgZnJvbSBwYXJlbnQgdHJhbnNhY3Rpb24gdG8gdXNlIGFzIGNoaWxkIHRyYW5zYWN0aW9uIGlucHV0XG4gICAqIDIpIEZpbmQgdW5zcGVudCBjb3JyZXNwb25kaW5nIHRvIHBhcmVudCB0cmFuc2FjdGlvbiBvdXRwdXQuIElmIG5vdCBmb3VuZCwgcmV0dXJuIHRvIHN0ZXAgMS5cbiAgICogMykgRGV0ZXJtaW5lIGlmIHBhcmVudCB0cmFuc2FjdGlvbiB1bnNwZW50IGNhbiBjb3ZlciBlbnRpcmUgY2hpbGQgZmVlLCBwbHVzIG1pbmltdW0gY2hhbmdlXG4gICAqIDQpIElmIHllcywgZ28gdG8gc3RlcCA2XG4gICAqIDUpIE90aGVyd2lzZSwgZmluZCBhZGRpdGlvbmFsIHVuc3BlbnRzIGZyb20gdGhlIHdhbGxldCB0byB1c2UgdG8gY292ZXIgdGhlIHJlbWFpbmluZyBjaGlsZCBmZWVcbiAgICogNikgQ3JlYXRlIGFuZCBzaWduIHRoZSBjaGlsZCB0cmFuc2FjdGlvbiwgdXNpbmcgdGhlIHBhcmVudCB0cmFuc2FjdGlvbiBvdXRwdXRcbiAgICogICAgKGFuZCwgaWYgbmVjZXNzYXJ5LCBhZGRpdGlvbmFsIHdhbGxldCB1bnNwZW50cykgYXMgaW5wdXRzXG4gICAqIDcpIEJyb2FkY2FzdCB0aGUgbmV3IGNoaWxkIHRyYW5zYWN0aW9uXG4gICAqL1xuICByZXR1cm4gY28oZnVuY3Rpb24qIGNvQWNjZWxlcmF0ZVRyYW5zYWN0aW9uKCk6IGFueSB7XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsndHJhbnNhY3Rpb25JRCddLCBbXSwgY2FsbGJhY2spO1xuXG4gICAgLy8gdmFsaWRhdGUgZmVlIHJhdGVcbiAgICBpZiAocGFyYW1zLmZlZVJhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHBhcmFtZXRlcjogZmVlUmF0ZScpO1xuICAgIH1cbiAgICBpZiAoIV8uaXNGaW5pdGUocGFyYW1zLmZlZVJhdGUpIHx8IHBhcmFtcy5mZWVSYXRlIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0aW5nIHBvc2l0aXZlIGZpbml0ZSBudW1iZXIgZm9yIHBhcmFtZXRlcjogZmVlUmF0ZScpO1xuICAgIH1cblxuICAgIC8vIHZhbGlkYXRlIG1heFVuc3BlbnRzXG4gICAgaWYgKHBhcmFtcy5tYXhBZGRpdGlvbmFsVW5zcGVudHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gYnkgZGVmYXVsdCwgdXNlIGF0IG1vc3QgMTAwIGFkZGl0aW9uYWwgdW5zcGVudHMgKG5vdCBpbmNsdWRpbmcgdGhlIHVuc3BlbnQgb3V0cHV0IGZyb20gdGhlIHBhcmVudCB0eClcbiAgICAgIHBhcmFtcy5tYXhBZGRpdGlvbmFsVW5zcGVudHMgPSAxMDA7XG4gICAgfVxuXG4gICAgaWYgKCFfLmlzSW50ZWdlcihwYXJhbXMubWF4QWRkaXRpb25hbFVuc3BlbnRzKSB8fCBwYXJhbXMubWF4QWRkaXRpb25hbFVuc3BlbnRzIDw9IDApIHtcbiAgICAgIHRocm93IEVycm9yKCdFeHBlY3RpbmcgcG9zaXRpdmUgaW50ZWdlciBmb3IgcGFyYW1ldGVyOiBtYXhBZGRpdGlvbmFsVW5zcGVudHMnKTtcbiAgICB9XG5cbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIGNvbnN0IHBhcmVudFR4ID0geWllbGQgdGhpcy5nZXRUcmFuc2FjdGlvbih7IGlkOiBwYXJhbXMudHJhbnNhY3Rpb25JRCB9KTtcbiAgICBpZiAocGFyZW50VHguY29uZmlybWF0aW9ucyA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVHJhbnNhY3Rpb24gJHtwYXJhbXMudHJhbnNhY3Rpb25JRH0gaXMgYWxyZWFkeSBjb25maXJtZWQgYW5kIGNhbm5vdCBiZSBhY2NlbGVyYXRlZGApO1xuICAgIH1cblxuICAgIC8vIGdldCB0aGUgb3V0cHV0cyBmcm9tIHRoZSBwYXJlbnQgdHggd2hpY2ggYXJlIHRvIG91ciB3YWxsZXRcbiAgICBjb25zdCB3YWxsZXRPdXRwdXRzID0gXy5maWx0ZXIocGFyZW50VHgub3V0cHV0cywgKG91dHB1dCkgPT4gb3V0cHV0LmlzTWluZSk7XG5cbiAgICBpZiAod2FsbGV0T3V0cHV0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRyYW5zYWN0aW9uICR7cGFyYW1zLnRyYW5zYWN0aW9uSUR9IGNvbnRhaW5zIG5vIG91dHB1dHMgdG8gdGhpcyB3YWxsZXQsIGFuZCB0aHVzIGNhbm5vdCBiZSBhY2NlbGVyYXRlZGBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gdXNlIGFuIG91dHB1dCBmcm9tIHRoZSBwYXJlbnQgd2l0aCBsYXJnZXN0IGVmZmVjdGl2ZSB2YWx1ZSxcbiAgICAvLyBidXQgY2hlY2sgdG8gbWFrZSBzdXJlIHRoZSBvdXRwdXQgaXMgYWN0dWFsbHkgdW5zcGVudC5cbiAgICAvLyBBbiBvdXRwdXQgY291bGQgYmUgc3BlbnQgYWxyZWFkeSBpZiB0aGUgb3V0cHV0IHdhcyB1c2VkIGluIGFcbiAgICAvLyBjaGlsZCB0eCB3aGljaCBpdHNlbGYgaGFzIGJlY29tZSBzdHVjayBkdWUgdG8gbG93IGZlZXMgYW5kIGlzXG4gICAgLy8gYWxzbyB1bmNvbmZpcm1lZC5cbiAgICBjb25zdCBzb3J0ZWRPdXRwdXRzID0gXy5zb3J0Qnkod2FsbGV0T3V0cHV0cywgZWZmZWN0aXZlVmFsdWUpO1xuICAgIGxldCBwYXJlbnRVbnNwZW50VG9Vc2U7XG4gICAgbGV0IG91dHB1dFRvVXNlO1xuXG4gICAgd2hpbGUgKHNvcnRlZE91dHB1dHMubGVuZ3RoID4gMCAmJiBwYXJlbnRVbnNwZW50VG9Vc2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgb3V0cHV0VG9Vc2UgPSBzb3J0ZWRPdXRwdXRzLnBvcCgpO1xuXG4gICAgICAvLyBmaW5kIHRoZSB1bnNwZW50IGNvcnJlc3BvbmRpbmcgdG8gdGhpcyBwYXJ0aWN1bGFyIG91dHB1dFxuICAgICAgLy8gVE9ETzogaXMgdGhlcmUgYSBiZXR0ZXIgd2F5IHRvIGdldCB0aGlzIHVuc3BlbnQ/XG4gICAgICAvLyBUT0RPOiBUaGUgYmVzdCB3ZSBjYW4gZG8gaGVyZSBpcyBzZXQgbWluU2l6ZSA9IG1heFNpemUgPSBvdXRwdXRUb1VzZS52YWx1ZVxuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIG5vIGltcGxpY2l0IHRoaXNcbiAgICAgIGNvbnN0IHVuc3BlbnRzUmVzdWx0ID0geWllbGQgdGhpcy51bnNwZW50cyh7XG4gICAgICAgIG1pblNpemU6IG91dHB1dFRvVXNlLnZhbHVlLFxuICAgICAgICBtYXhTaXplOiBvdXRwdXRUb1VzZS52YWx1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBwYXJlbnRVbnNwZW50VG9Vc2UgPSBfLmZpbmQodW5zcGVudHNSZXN1bHQsICh1bnNwZW50KSA9PiB7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSB1bnNwZW50IGJlbG9uZ3MgdG8gdGhlIGdpdmVuIHR4aWRcbiAgICAgICAgaWYgKHVuc3BlbnQudHhfaGFzaCAhPT0gcGFyYW1zLnRyYW5zYWN0aW9uSUQpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbWFrZSBzdXJlIHVuc3BlbnQgaGFzIGNvcnJlY3Qgdl9vdXQgaW5kZXhcbiAgICAgICAgcmV0dXJuIHVuc3BlbnQudHhfb3V0cHV0X24gPT09IG91dHB1dFRvVXNlLnZvdXQ7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocGFyZW50VW5zcGVudFRvVXNlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgdW5zcGVudCBvdXRwdXQgZnJvbSBwYXJlbnQgdHggdG8gdXNlIGFzIGNoaWxkIGlucHV0YCk7XG4gICAgfVxuXG4gICAgLy8gZ2V0IHRoZSBmdWxsIGhleCBmb3IgdGhlIHBhcmVudCB0eCBhbmQgZGVjb2RlIGl0IHRvIGdldCBpdHMgdnNpemVcbiAgICBjb25zdCBwYXJlbnRUeEhleCA9IHlpZWxkIGdldFBhcmVudFR4SGV4KHsgcGFyZW50VHhJZDogcGFyYW1zLnRyYW5zYWN0aW9uSUQgfSk7XG4gICAgY29uc3QgZGVjb2RlZFBhcmVudCA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4KHBhcmVudFR4SGV4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgIGNvbnN0IHBhcmVudFZTaXplID0gZGVjb2RlZFBhcmVudC52aXJ0dWFsU2l6ZSgpO1xuXG4gICAgLy8gbWFrZSBzdXJlIGlkIGZyb20gZGVjb2RlZCB0eCBhbmQgZ2l2ZW4gdHggaWQgbWF0Y2hcbiAgICAvLyB0aGlzIHNob3VsZCBjYXRjaCBwcm9ibGVtcyBlbWFuYXRpbmcgZnJvbSB0aGUgdXNlIG9mIGFuIGV4dGVybmFsIHNlcnZpY2VcbiAgICAvLyBmb3IgZ2V0dGluZyB0aGUgY29tcGxldGUgcGFyZW50IHR4IGhleFxuICAgIGlmIChkZWNvZGVkUGFyZW50LmdldElkKCkgIT09IHBhcmFtcy50cmFuc2FjdGlvbklEKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBEZWNvZGVkIHRyYW5zYWN0aW9uIGlkIGlzICR7ZGVjb2RlZFBhcmVudC5nZXRJZCgpfSwgd2hpY2ggZG9lcyBub3QgbWF0Y2ggZ2l2ZW4gdHhpZCAke3BhcmFtcy50cmFuc2FjdGlvbklEfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIG5ldyBmZWUgcmF0ZSBpcyBncmVhdGVyIHRoYW4gdGhlIHBhcmVudCdzIGN1cnJlbnQgZmVlIHJhdGVcbiAgICAvLyB2aXJ0dWFsU2l6ZSBpcyByZXR1cm5lZCBpbiB2Ynl0ZXMsIHNvIHdlIG5lZWQgdG8gY29udmVydCB0byBrdkJcbiAgICBjb25zdCBwYXJlbnRSYXRlID0gKDEwMDAgKiBwYXJlbnRUeC5mZWUpIC8gcGFyZW50VlNpemU7XG4gICAgaWYgKHBhcmFtcy5mZWVSYXRlIDw9IHBhcmVudFJhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENhbm5vdCBsb3dlciBmZWUgcmF0ZSEgKFBhcmVudCB0eCBmZWUgcmF0ZSBpcyAke3BhcmVudFJhdGV9IHNhdC9rQiwgYW5kIHJlcXVlc3RlZCBmZWUgcmF0ZSB3YXMgJHtwYXJhbXMuZmVlUmF0ZX0gc2F0L2tCKWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gZGV0ZXJtaW5lIGlmIHBhcmVudCBvdXRwdXQgY2FuIGNvdmVyIGNoaWxkIGZlZVxuICAgIGNvbnN0IGlzUGFyZW50T3V0cHV0U2Vnd2l0ID1cbiAgICAgIGlzQ2hhaW5Db2RlKG91dHB1dFRvVXNlLmNoYWluKSAmJiBzY3JpcHRUeXBlRm9yQ2hhaW4ob3V0cHV0VG9Vc2UuY2hhaW4pID09PSAncDJzaFAyd3NoJztcblxuICAgIGxldCBjaGlsZElucHV0cyA9IHtcbiAgICAgIHNlZ3dpdDogaXNQYXJlbnRPdXRwdXRTZWd3aXQgPyAxIDogMCxcbiAgICAgIFAyU0g6IGlzUGFyZW50T3V0cHV0U2Vnd2l0ID8gMCA6IDEsXG4gICAgfTtcblxuICAgIGxldCBjaGlsZEZlZSA9IGVzdGltYXRlQ2hpbGRGZWUoe1xuICAgICAgaW5wdXRzOiBjaGlsZElucHV0cyxcbiAgICAgIHBhcmVudEZlZTogcGFyZW50VHguZmVlLFxuICAgICAgZmVlUmF0ZTogcGFyYW1zLmZlZVJhdGUsXG4gICAgICBwYXJlbnRWU2l6ZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHVuc3BlbnRzVG9Vc2UgPSBbcGFyZW50VW5zcGVudFRvVXNlXTtcblxuICAgIC8vIHRyeSB0byBnZXQgdGhlIG1pbiBjaGFuZ2Ugc2l6ZSBmcm9tIHRoZSBzZXJ2ZXIsIG90aGVyd2lzZSBkZWZhdWx0IHRvIDAuMSBCVENcbiAgICAvLyBUT0RPOiBtaW5DaGFuZ2VTaXplIGlzIG5vdCBjdXJyZW50bHkgYSBjb25zdGFudCBkZWZpbmVkIG9uIHRoZSBjbGllbnQgYW5kIHNob3VsZCBiZSBhZGRlZFxuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgY29uc3QgbWluQ2hhbmdlU2l6ZSA9IHRoaXMuYml0Z28uZ2V0Q29uc3RhbnRzKCkubWluQ2hhbmdlU2l6ZSB8fCAxZTc7XG5cbiAgICBpZiAob3V0cHV0VG9Vc2UudmFsdWUgPCBjaGlsZEZlZSArIG1pbkNoYW5nZVNpemUpIHtcbiAgICAgIC8vIHBhcmVudCBvdXRwdXQgY2Fubm90IGNvdmVyIGNoaWxkIGZlZSBwbHVzIHRoZSBtaW5pbXVtIGNoYW5nZSxcbiAgICAgIC8vIG11c3QgZmluZCBhZGRpdGlvbmFsIHVuc3BlbnRzIHRvIGNvdmVyIHRoZSBkaWZmZXJlbmNlXG4gICAgICBjb25zdCB7IGFkZGl0aW9uYWwsIG5ld0NoaWxkRmVlLCBuZXdJbnB1dHMgfSA9IHlpZWxkIGZpbmRBZGRpdGlvbmFsVW5zcGVudHMoe1xuICAgICAgICBpbnB1dHM6IGNoaWxkSW5wdXRzLFxuICAgICAgICBwYXJlbnRPdXRwdXRWYWx1ZTogb3V0cHV0VG9Vc2UudmFsdWUsXG4gICAgICAgIHBhcmVudEZlZTogcGFyZW50VHguZmVlLFxuICAgICAgICBtYXhVbnNwZW50czogcGFyYW1zLm1heEFkZGl0aW9uYWxVbnNwZW50cyxcbiAgICAgICAgcGFyZW50VlNpemUsXG4gICAgICB9KTtcbiAgICAgIGNoaWxkRmVlID0gbmV3Q2hpbGRGZWU7XG4gICAgICBjaGlsZElucHV0cyA9IG5ld0lucHV0cztcbiAgICAgIHVuc3BlbnRzVG9Vc2UucHVzaCguLi5hZGRpdGlvbmFsKTtcbiAgICB9XG5cbiAgICAvLyBzYW5pdHkgY2hlY2sgdGhlIGZlZSByYXRlIHdlJ3JlIHBheWluZyBmb3IgdGhlIGNvbWJpbmVkIHR4XG4gICAgLy8gdG8gbWFrZSBzdXJlIGl0J3MgdW5kZXIgdGhlIG1heCBmZWUgcmF0ZS4gT25seSB0aGUgY2hpbGQgdHhcbiAgICAvLyBjYW4gYnJlYWsgdGhpcyBsaW1pdCwgYnV0IHRoZSBjb21iaW5lZCB0eCBzaGFsbCBub3RcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIGNvbnN0IG1heEZlZVJhdGUgPSB0aGlzLmJpdGdvLmdldENvbnN0YW50cygpLm1heEZlZVJhdGU7XG4gICAgY29uc3QgY2hpbGRWU2l6ZSA9IGVzdGltYXRlVHhWU2l6ZShjaGlsZElucHV0cyk7XG4gICAgY29uc3QgY29tYmluZWRWU2l6ZSA9IGNoaWxkVlNpemUgKyBwYXJlbnRWU2l6ZTtcbiAgICBjb25zdCBjb21iaW5lZEZlZSA9IHBhcmVudFR4LmZlZSArIGNoaWxkRmVlO1xuICAgIC8vIGNvbWJpbmVkIGZlZSByYXRlIG11c3QgYmUgaW4gc2F0L2tCLCBzbyB3ZSBuZWVkIHRvIGNvbnZlcnRcbiAgICBjb25zdCBjb21iaW5lZEZlZVJhdGUgPSAoMTAwMCAqIGNvbWJpbmVkRmVlKSAvIGNvbWJpbmVkVlNpemU7XG5cbiAgICBpZiAoY29tYmluZWRGZWVSYXRlID4gbWF4RmVlUmF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVHJhbnNhY3Rpb24gY2Fubm90IGJlIGFjY2VsZXJhdGVkLiBDb21iaW5lZCBmZWUgcmF0ZSBvZiAke2NvbWJpbmVkRmVlUmF0ZX0gc2F0L2tCIGV4Y2VlZHMgbWF4aW11bSBmZWUgcmF0ZSBvZiAke21heEZlZVJhdGV9IHNhdC9rQmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGEgbmV3IGNoYW5nZSBhZGRyZXNzIGFuZCBkZXRlcm1pbmUgY2hhbmdlIGFtb3VudC5cbiAgICAvLyB0aGUgdHggYnVpbGRlciB3aWxsIHJlamVjdCB0cmFuc2FjdGlvbnMgd2hpY2ggaGF2ZSBubyByZWNpcGllbnRzLFxuICAgIC8vIGFuZCBzdWNoIHplcm8tb3V0cHV0IHRyYW5zYWN0aW9ucyBhcmUgZm9yYmlkZGVuIGJ5IHRoZSBCaXRjb2luIHByb3RvY29sLFxuICAgIC8vIHNvIHdlIG5lZWQgYXQgbGVhc3QgYSBzaW5nbGUgcmVjaXBpZW50IGZvciB0aGUgY2hhbmdlIHdoaWNoIHdvbid0IGJlIHBydW5lZC5cbiAgICBjb25zdCBjaGFuZ2VBbW91bnQgPSBfLnN1bUJ5KHVuc3BlbnRzVG9Vc2UsICh1bnNwZW50KSA9PiB1bnNwZW50LnZhbHVlKSAtIGNoaWxkRmVlO1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgY29uc3QgY2hhbmdlQ2hhaW4gPSB0aGlzLmdldENoYW5nZUNoYWluKHt9KTtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIGNvbnN0IGNoYW5nZUFkZHJlc3MgPSB5aWVsZCB0aGlzLmNyZWF0ZUFkZHJlc3MoeyBjaGFpbjogY2hhbmdlQ2hhaW4gfSk7XG5cbiAgICAvLyBjcmVhdGUgdGhlIGNoaWxkIHR4IGFuZCBicm9hZGNhc3RcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIGNvbnN0IHR4ID0geWllbGQgdGhpcy5jcmVhdGVBbmRTaWduVHJhbnNhY3Rpb24oe1xuICAgICAgdW5zcGVudHM6IHVuc3BlbnRzVG9Vc2UsXG4gICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBjaGFuZ2VBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgICAgYW1vdW50OiBjaGFuZ2VBbW91bnQsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZmVlOiBjaGlsZEZlZSxcbiAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgYWRkcmVzczogJycsXG4gICAgICB9LFxuICAgICAgeHBydjogcGFyYW1zLnhwcnYsXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICB9KTtcblxuICAgIC8vIGNoaWxkIGZlZSByYXRlIG11c3QgYmUgaW4gc2F0L2tCLCBzbyB3ZSBuZWVkIHRvIGNvbnZlcnRcbiAgICBjb25zdCBjaGlsZEZlZVJhdGUgPSAoMTAwMCAqIGNoaWxkRmVlKSAvIGNoaWxkVlNpemU7XG4gICAgaWYgKGNoaWxkRmVlUmF0ZSA+IG1heEZlZVJhdGUpIHtcbiAgICAgIC8vIGNvbWJpbmVkIHR4IGlzIHdpdGhpbiBtYXggZmVlIHJhdGUgbGltaXRzLCBidXQgdGhlIGNoaWxkIHR4IGlzIG5vdC5cbiAgICAgIC8vIGluIHRoaXMgY2FzZSwgd2UgbmVlZCB0byB1c2UgdGhlIGlnbm9yZU1heEZlZVJhdGUgZmxhZyB0byBnZXQgdGhlIGNoaWxkIHR4IHRvIGJlIGFjY2VwdGVkXG4gICAgICB0eC5pZ25vcmVNYXhGZWVSYXRlID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIHJldHVybiB0aGlzLnNlbmRUcmFuc2FjdGlvbih0eCk7XG4gIH0pXG4gICAgLmNhbGwodGhpcylcbiAgICAuYXNDYWxsYmFjayhjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gY3JlYXRlQW5kU2lnblRyYW5zYWN0aW9uXG4vLyBJTlRFUk5BTCBmdW5jdGlvbiB0byBjcmVhdGUgYW5kIHNpZ24gYSB0cmFuc2FjdGlvblxuLy9cbi8vIFBhcmFtZXRlcnM6XG4vLyAgIHJlY2lwaWVudHMgLSBhcnJheSBvZiB7IGFkZHJlc3MsIGFtb3VudCB9IHRvIHNlbmQgdG9cbi8vICAgd2FsbGV0UGFzc3BocmFzZSAtIHRoZSBwYXNzcGhyYXNlIHRvIGJlIHVzZWQgdG8gZGVjcnlwdCB0aGUgdXNlciBrZXkgb24gdGhpcyB3YWxsZXRcbi8vICAgKFNlZSB0cmFuc2FjdGlvbkJ1aWxkZXIuY3JlYXRlVHJhbnNhY3Rpb24gZm9yIG90aGVyIHBhc3N0aHJvdWdoIHBhcmFtcylcbi8vIFJldHVybnM6XG4vL1xuV2FsbGV0LnByb3RvdHlwZS5jcmVhdGVBbmRTaWduVHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICByZXR1cm4gY28oZnVuY3Rpb24qICgpIHtcbiAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gICAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgICBpZiAoIV8uaXNPYmplY3QocGFyYW1zLnJlY2lwaWVudHMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGluZyByZWNpcGllbnRzIG9iamVjdCcpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuZmVlICYmICFfLmlzTnVtYmVyKHBhcmFtcy5mZWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYXJndW1lbnQgZm9yIGZlZSAtIG51bWJlciBleHBlY3RlZCcpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuZmVlUmF0ZSAmJiAhXy5pc051bWJlcihwYXJhbXMuZmVlUmF0ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcmd1bWVudCBmb3IgZmVlUmF0ZSAtIG51bWJlciBleHBlY3RlZCcpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuZHluYW1pY0ZlZUNvbmZpcm1UYXJnZXQgJiYgIV8uaXNOdW1iZXIocGFyYW1zLmR5bmFtaWNGZWVDb25maXJtVGFyZ2V0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFyZ3VtZW50IGZvciBjb25maXJtVGFyZ2V0IC0gbnVtYmVyIGV4cGVjdGVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHBhcmFtcy5pbnN0YW50ICYmICFfLmlzQm9vbGVhbihwYXJhbXMuaW5zdGFudCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcmd1bWVudCBmb3IgaW5zdGFudCAtIGJvb2xlYW4gZXhwZWN0ZWQnKTtcbiAgICB9XG5cbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKHlpZWxkIHRoaXMuY3JlYXRlVHJhbnNhY3Rpb24ocGFyYW1zKSkgYXMgYW55O1xuICAgIGNvbnN0IGZlZSA9IHRyYW5zYWN0aW9uLmZlZTtcbiAgICBjb25zdCBmZWVSYXRlID0gdHJhbnNhY3Rpb24uZmVlUmF0ZTtcbiAgICBjb25zdCBlc3RpbWF0ZWRTaXplID0gdHJhbnNhY3Rpb24uZXN0aW1hdGVkU2l6ZTtcbiAgICBjb25zdCBiaXRnb0ZlZSA9IHRyYW5zYWN0aW9uLmJpdGdvRmVlO1xuICAgIGNvbnN0IHRyYXZlbEluZm9zID0gdHJhbnNhY3Rpb24udHJhdmVsSW5mb3M7XG4gICAgY29uc3QgdW5zcGVudHMgPSB0cmFuc2FjdGlvbi51bnNwZW50cztcblxuICAgIC8vIFNpZ24gdGhlIHRyYW5zYWN0aW9uXG4gICAgdHJ5IHtcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgICBjb25zdCBrZXljaGFpbiA9IHlpZWxkIHRoaXMuZ2V0QW5kUHJlcGFyZVNpZ25pbmdLZXljaGFpbihwYXJhbXMpO1xuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSBrZXljaGFpbjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnbm9fZW5jcnlwdGVkX2tleWNoYWluX29uX3dhbGxldCcpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIC8vIHRoaXMgbWlnaHQgYmUgYSBzYWZlIHdhbGxldCwgc28gbGV0J3MgcmV0cmlldmUgdGhlIHByaXZhdGUga2V5IGluZm9cbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gICAgICB5aWVsZCB0aGlzLnJlZnJlc2goeyBncGs6IHRydWUgfSk7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgICAgY29uc3Qgc2FmZVVzZXJLZXkgPSBfLmdldCh0aGlzLndhbGxldCwgJ3ByaXZhdGUudXNlclByaXZLZXknKTtcbiAgICAgIGlmIChfLmlzU3RyaW5nKHNhZmVVc2VyS2V5KSAmJiBfLmlzU3RyaW5nKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSkge1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gbm8gaW1wbGljaXQgdGhpc1xuICAgICAgICB0cmFuc2FjdGlvbi5zaWduaW5nS2V5ID0gdGhpcy5iaXRnby5kZWNyeXB0KHsgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLCBpbnB1dDogc2FmZVVzZXJLZXkgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRyYW5zYWN0aW9uLmZlZVNpbmdsZUtleVdJRiA9IHBhcmFtcy5mZWVTaW5nbGVLZXlXSUY7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIG5vIGltcGxpY2l0IHRoaXNcbiAgICBjb25zdCByZXN1bHQgPSB5aWVsZCB0aGlzLnNpZ25UcmFuc2FjdGlvbih0cmFuc2FjdGlvbik7XG4gICAgcmV0dXJuIF8uZXh0ZW5kKHJlc3VsdCwge1xuICAgICAgZmVlLFxuICAgICAgZmVlUmF0ZSxcbiAgICAgIGluc3RhbnQ6IHBhcmFtcy5pbnN0YW50LFxuICAgICAgYml0Z29GZWUsXG4gICAgICB0cmF2ZWxJbmZvcyxcbiAgICAgIGVzdGltYXRlZFNpemUsXG4gICAgICB1bnNwZW50cyxcbiAgICB9KTtcbiAgfSlcbiAgICAuY2FsbCh0aGlzKVxuICAgIC5hc0NhbGxiYWNrKGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBnZXRBbmRQcmVwYXJlU2lnbmluZ0tleWNoYWluXG4vLyBJTlRFUk5BTCBmdW5jdGlvbiB0byBnZXQgdGhlIHVzZXIga2V5Y2hhaW4gZm9yIHNpZ25pbmcuXG4vLyBDYWxsZXIgbXVzdCBwcm92aWRlciBlaXRoZXIgYSBrZXljaGFpbiwgb3Igd2FsbGV0UGFzc3BocmFzZSBvciB4cHJ2IGFzIGEgc3RyaW5nXG4vLyBJZiB0aGUgY2FsbGVyIHByb3ZpZGVzIHRoZSBrZXljaGFpbiB3aXRoIHhwcnYsIGl0IGlzIHNpbXBseSByZXR1cm5lZC5cbi8vIElmIHRoZSBjYWxsZXIgcHJvdmlkZXMgdGhlIGVuY3J5cHRlZCB4cHJ2ICh3YWxsZXRQYXNzcGhyYXNlKSwgdGhlbiBmZXRjaCB0aGUga2V5Y2hhaW4gb2JqZWN0IGFuZCBkZWNyeXB0XG4vLyBPdGhlcndpc2UgaWYgdGhlIHhwcnYgaXMgcHJvdmlkZWQsIGZldGNoIHRoZSBrZXljaGFpbiBvYmplY3QgYW5kIGF1Z21lbnQgaXQgd2l0aCB0aGUgeHBydi5cbi8vXG4vLyBQYXJhbWV0ZXJzOlxuLy8gICBrZXljaGFpbiAtIGtleWNoYWluIHdpdGggeHBydlxuLy8gICB4cHJ2IC0gdGhlIHByaXZhdGUga2V5IGluIHN0cmluZyBmb3JtXG4vLyAgIHdhbGxldFBhc3NwaHJhc2UgLSB0aGUgcGFzc3BocmFzZSB0byBiZSB1c2VkIHRvIGRlY3J5cHQgdGhlIHVzZXIga2V5IG9uIHRoaXMgd2FsbGV0XG4vLyBSZXR1cm5zOlxuLy8gICBLZXljaGFpbiBvYmplY3QgY29udGFpbmluZyB4cHJ2LCB4cHViIGFuZCBwYXRoc1xuLy9cbldhbGxldC5wcm90b3R5cGUuZ2V0QW5kUHJlcGFyZVNpZ25pbmdLZXljaGFpbiA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAvLyBJZiBrZXljaGFpbiB3aXRoIHhwcnYgaXMgYWxyZWFkeSBwcm92aWRlZCwgdXNlIGl0XG4gIGlmIChfLmlzT2JqZWN0KHBhcmFtcy5rZXljaGFpbikgJiYgcGFyYW1zLmtleWNoYWluLnhwcnYpIHtcbiAgICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZShwYXJhbXMua2V5Y2hhaW4pO1xuICB9XG5cbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFsnd2FsbGV0UGFzc3BocmFzZScsICd4cHJ2J10sIGNhbGxiYWNrKTtcblxuICBpZiAoKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlICYmIHBhcmFtcy54cHJ2KSB8fCAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlICYmICFwYXJhbXMueHBydikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ211c3QgcHJvdmlkZSBleGFjdGx5IG9uZSBvZiB4cHJ2IG9yIHdhbGxldFBhc3NwaHJhc2UnKTtcbiAgfVxuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gIC8vIENhbGxlciBwcm92aWRlZCBhIHdhbGxldCBwYXNzcGhyYXNlXG4gIGlmIChwYXJhbXMud2FsbGV0UGFzc3BocmFzZSkge1xuICAgIHJldHVybiBzZWxmLmdldEVuY3J5cHRlZFVzZXJLZXljaGFpbigpLnRoZW4oZnVuY3Rpb24gKGtleWNoYWluKSB7XG4gICAgICAvLyBEZWNyeXB0IHRoZSB1c2VyIGtleSB3aXRoIGEgcGFzc3BocmFzZVxuICAgICAgdHJ5IHtcbiAgICAgICAga2V5Y2hhaW4ueHBydiA9IHNlbGYuYml0Z28uZGVjcnlwdCh7IHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSwgaW5wdXQ6IGtleWNoYWluLmVuY3J5cHRlZFhwcnYgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGRlY3J5cHQgdXNlciBrZXljaGFpbicpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGtleWNoYWluO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gQ2FsbGVyIHByb3ZpZGVkIGFuIHhwcnYgLSB2YWxpZGF0ZSBhbmQgY29uc3RydWN0IGtleWNoYWluIG9iamVjdFxuICBsZXQgeHB1YjtcbiAgdHJ5IHtcbiAgICB4cHViID0gYmlwMzIuZnJvbUJhc2U1OChwYXJhbXMueHBydikubmV1dGVyZWQoKS50b0Jhc2U1OCgpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gcGFyc2UgdGhlIHhwcnYnKTtcbiAgfVxuXG4gIGlmICh4cHViID09PSBwYXJhbXMueHBydikge1xuICAgIHRocm93IG5ldyBFcnJvcigneHBydiBwcm92aWRlZCB3YXMgbm90IGEgcHJpdmF0ZSBrZXkgKGZvdW5kIHhwdWIgaW5zdGVhZCknKTtcbiAgfVxuXG4gIGNvbnN0IHdhbGxldFhwdWJzID0gXy5tYXAoc2VsZi5rZXljaGFpbnMsICd4cHViJyk7XG4gIGlmICghXy5pbmNsdWRlcyh3YWxsZXRYcHVicywgeHB1YikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3hwcnYgcHJvdmlkZWQgd2FzIG5vdCBhIGtleWNoYWluIG9uIHRoaXMgd2FsbGV0IScpO1xuICB9XG5cbiAgLy8gZ2V0IHRoZSBrZXljaGFpbiBvYmplY3QgZnJvbSBiaXRnbyB0byBmaW5kIHRoZSBwYXRoIGFuZCAocG90ZW50aWFsKSB3YWxsZXQgc3RydWN0dXJlXG4gIHJldHVybiBzZWxmLmJpdGdvXG4gICAgLmtleWNoYWlucygpXG4gICAgLmdldCh7IHhwdWI6IHhwdWIgfSlcbiAgICAudGhlbihmdW5jdGlvbiAoa2V5Y2hhaW4pIHtcbiAgICAgIGtleWNoYWluLnhwcnYgPSBwYXJhbXMueHBydjtcbiAgICAgIHJldHVybiBrZXljaGFpbjtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogVGFrZXMgYSB3YWxsZXQncyB1bnNwZW50cyBhbmQgZmFucyB0aGVtIG91dCBpbnRvIGEgbGFyZ2VyIG51bWJlciBvZiBlcXVhbGx5IHNpemVkIHVuc3BlbnRzXG4gKiBAcGFyYW0gcGFyYW1zXG4gKiAgdGFyZ2V0OiBzZXQgaG93IG1hbnkgdW5zcGVudHMgeW91IHdhbnQgdG8gaGF2ZSBpbiB0aGUgZW5kXG4gKiAgbWluQ29uZmlybXM6IG1pbmltdW0gbnVtYmVyIG9mIGNvbmZpcm1zIHRoZSB1bnNwZW50cyBtdXN0IGhhdmVcbiAqICB4cHJ2OiBwcml2YXRlIGtleSB0byBzaWduIHRyYW5zYWN0aW9uXG4gKiAgd2FsbGV0UGFzc3BocmFzZTogd2FsbGV0IHBhc3NwaHJhc2UgdG8gZGVjcnlwdCB0aGUgd2FsbGV0J3MgcHJpdmF0ZSBrZXlcbiAqIEBwYXJhbSBjYWxsYmFja1xuICogQHJldHVybnMgeyp9XG4gKi9cbldhbGxldC5wcm90b3R5cGUuZmFuT3V0VW5zcGVudHMgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBjb25zdCBzZWxmID0gdGhpcztcbiAgcmV0dXJuIEJsdWViaXJkLmNvcm91dGluZShmdW5jdGlvbiogKCkge1xuICAgIC8vIG1heGltdW0gbnVtYmVyIG9mIGlucHV0cyBmb3IgZmFub3V0IHRyYW5zYWN0aW9uXG4gICAgLy8gKHdoZW4gZmFubmluZyBvdXQsIHdlIHRha2UgYWxsIHRoZSB1bnNwZW50cyBhbmQgbWFrZSBhIGJpZ2dlciBudW1iZXIgb2Ygb3V0cHV0cylcbiAgICBjb25zdCBNQVhfRkFOT1VUX0lOUFVUX0NPVU5UID0gODA7XG4gICAgLy8gbWF4aW11bSBudW1iZXIgb2Ygb3V0cHV0cyBmb3IgZmFub3V0IHRyYW5zYWN0aW9uXG4gICAgY29uc3QgTUFYX0ZBTk9VVF9PVVRQVVRfQ09VTlQgPSAzMDA7XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbJ3dhbGxldFBhc3NwaHJhc2UnLCAneHBydiddLCBjYWxsYmFjayk7XG4gICAgY29uc3QgdmFsaWRhdGUgPSBwYXJhbXMudmFsaWRhdGUgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBwYXJhbXMudmFsaWRhdGU7XG5cbiAgICBjb25zdCB0YXJnZXQgPSBwYXJhbXMudGFyZ2V0O1xuICAgIC8vIHRoZSB0YXJnZXQgbXVzdCBiZSBkZWZpbmVkLCBiZSBhIG51bWJlciwgYmUgYXQgbGVhc3QgdHdvLCBhbmQgYmUgYSBuYXR1cmFsIG51bWJlclxuICAgIGlmICghXy5pc051bWJlcih0YXJnZXQpIHx8IHRhcmdldCA8IDIgfHwgdGFyZ2V0ICUgMSAhPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUYXJnZXQgbmVlZHMgdG8gYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXQgPiBNQVhfRkFOT1VUX09VVFBVVF9DT1VOVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYW4gb3V0IHRhcmdldCB0b28gaGlnaCcpO1xuICAgIH1cblxuICAgIGxldCBtaW5Db25maXJtcyA9IHBhcmFtcy5taW5Db25maXJtcztcbiAgICBpZiAobWluQ29uZmlybXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbWluQ29uZmlybXMgPSAxO1xuICAgIH1cbiAgICBpZiAoIV8uaXNOdW1iZXIobWluQ29uZmlybXMpIHx8IG1pbkNvbmZpcm1zIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaW5Db25maXJtcyBuZWVkcyB0byBiZSBhbiBpbnRlZ2VyID49IDAnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTcGxpdCBhIG5hdHVyYWwgbnVtYmVyIE4gaW50byBuIGFsbW9zdCBlcXVhbGx5IHNpemVkICjCsTEpIG5hdHVyYWwgbnVtYmVycy5cbiAgICAgKiBJbiBvcmRlciB0byBjYWxjdWxhdGUgdGhlIHNpemVzIG9mIHRoZSBwYXJ0cywgd2UgY2FsY3VsYXRlIGZsb29yKE4vbiksIGFuZCB0aHVzIGhhdmUgdGhlIGJhc2Ugc2l6ZSBvZiBhbGwgcGFydHMuXG4gICAgICogSWYgTiAlIG4gIT09IDAsIHRoaXMgbGVhdmVzIHVzIHdpdGggYSByZW1haW5kZXIgciB3aGVyZSByIDwgbi4gV2UgZGlzdHJpYnV0ZSByIGVxdWFsbHkgYW1vbmcgdGhlIG4gcGFydHMgYnlcbiAgICAgKiBhZGRpbmcgMSB0byB0aGUgZmlyc3QgciBwYXJ0cy5cbiAgICAgKiBAcGFyYW0gdG90YWxcbiAgICAgKiBAcGFyYW0gcGFydENvdW50XG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIGNvbnN0IHNwbGl0TnVtYmVySW50b0Nsb3NlTmF0dXJhbE51bWJlcnMgPSBmdW5jdGlvbiAodG90YWwsIHBhcnRDb3VudCkge1xuICAgICAgY29uc3QgcGFydFNpemUgPSBNYXRoLmZsb29yKHRvdGFsIC8gcGFydENvdW50KTtcbiAgICAgIGNvbnN0IHJlbWFpbmRlciA9IHRvdGFsIC0gcGFydFNpemUgKiBwYXJ0Q291bnQ7XG4gICAgICAvLyBpbml0aWFsaXplIHBsYWNlaG9sZGVyIGFycmF5XG4gICAgICBjb25zdCBhbG1vc3RFcXVhbFBhcnRzID0gbmV3IEFycmF5KHBhcnRDb3VudCk7XG4gICAgICAvLyBmaWxsIHRoZSBmaXJzdCByZW1haW5kZXIgcGFydHMgd2l0aCB0aGUgdmFsdWUgcGFydFNpemUrMVxuICAgICAgXy5maWxsKGFsbW9zdEVxdWFsUGFydHMsIHBhcnRTaXplICsgMSwgMCwgcmVtYWluZGVyKTtcbiAgICAgIC8vIGZpbGwgdGhlIHJlbWFpbmluZyBwYXJ0cyB3aXRoIHRoZSB2YWx1ZSBwYXJ0U2l6ZVxuICAgICAgXy5maWxsKGFsbW9zdEVxdWFsUGFydHMsIHBhcnRTaXplLCByZW1haW5kZXIpO1xuICAgICAgLy8gYXNzZXJ0IHRoZSBjb3JyZWN0bmVzcyBvZiB0aGUgYWxtb3N0IGVxdWFsIHBhcnRzXG4gICAgICAvLyBUT0RPOiBhZGQgY2hlY2sgZm9yIHRoZSBiaWdnZXN0IGRldmlhdGlvbiBiZXR3ZWVuIGFueSB0d28gcGFydHMgYW5kIG1ha2Ugc3VyZSBpdCdzIDw9IDFcbiAgICAgIGlmIChfKGFsbW9zdEVxdWFsUGFydHMpLnN1bSgpICE9PSB0b3RhbCB8fCBfKGFsbW9zdEVxdWFsUGFydHMpLnNpemUoKSAhPT0gcGFydENvdW50KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncGFydCBzdW0gb3IgcGFydCBjb3VudCBtaXNtYXRjaCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFsbW9zdEVxdWFsUGFydHM7XG4gICAgfTtcblxuICAgIC8vIGZpcnN0LCBsZXQncyB0YWtlIGFsbCB0aGUgd2FsbGV0J3MgdW5zcGVudHMgKHdpdGggbWluIGNvbmZpcm1zIGlmIG5lY2Vzc2FyeSlcbiAgICBjb25zdCBhbGxVbnNwZW50cyA9ICh5aWVsZCBzZWxmLnVuc3BlbnRzKHsgbWluQ29uZmlybXM6IG1pbkNvbmZpcm1zIH0pKSBhcyBhbnk7XG4gICAgaWYgKGFsbFVuc3BlbnRzLmxlbmd0aCA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gdW5zcGVudHMgdG8gYnJhbmNoIG91dCcpO1xuICAgIH1cblxuICAgIC8vIHRoaXMgY29uc29saWRhdGlvbiBpcyBlc3NlbnRpYWxseSBqdXN0IGEgd2FzdGUgb2YgbW9uZXlcbiAgICBpZiAoYWxsVW5zcGVudHMubGVuZ3RoID49IHRhcmdldCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYW4gb3V0IHRhcmdldCBoYXMgdG8gYmUgYmlnZ2VyIHRoYW4gY3VycmVudCBudW1iZXIgb2YgdW5zcGVudHMnKTtcbiAgICB9XG5cbiAgICAvLyB3ZSBoYXZlIGF0IHRoZSB2ZXJ5IG1pbmltdW0gODEgaW5wdXRzLCBhbmQgODEgb3V0cHV0cy4gVGhhdCB0cmFuc2FjdGlvbiB3aWxsIGJlIGJpZ1xuICAgIC8vIGluIHRoZSBtZWRpdW0gcnVuLCB0aGlzIGFsZ29yaXRobSBjb3VsZCBiZSByZXdvcmtlZCB0byBvbmx5IHdvcmsgd2l0aCBhIHN1YnNldCBvZiB0aGUgdHJhbnNhY3Rpb25zXG4gICAgaWYgKGFsbFVuc3BlbnRzLmxlbmd0aCA+IE1BWF9GQU5PVVRfSU5QVVRfQ09VTlQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVG9vIG1hbnkgdW5zcGVudHMnKTtcbiAgICB9XG5cbiAgICAvLyB0aGlzIGlzIGFsbCB0aGUgbW9uZXkgdGhhdCBpcyBjdXJyZW50bHkgaW4gdGhlIHdhbGxldFxuICAgIGNvbnN0IGdyb3NzQW1vdW50ID0gXyhhbGxVbnNwZW50cykubWFwKCd2YWx1ZScpLnN1bSgpO1xuXG4gICAgLy8gaW4gb3JkZXIgdG8gbm90IG1vZGlmeSB0aGUgcGFyYW1zIG9iamVjdCwgd2UgY3JlYXRlIGEgY29weVxuICAgIGNvbnN0IHR4UGFyYW1zID0gXy5leHRlbmQoe30sIHBhcmFtcyk7XG4gICAgdHhQYXJhbXMudW5zcGVudHMgPSBhbGxVbnNwZW50cztcbiAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0ge307XG5cbiAgICAvLyBjcmVhdGUgdGFyZ2V0IGFtb3VudCBvZiBuZXcgYWRkcmVzc2VzIGZvciB0aGlzIHdhbGxldFxuICAgIGNvbnN0IG5ld0FkZHJlc3NQcm9taXNlcyA9IF8ucmFuZ2UodGFyZ2V0KS5tYXAoKCkgPT5cbiAgICAgIHNlbGYuY3JlYXRlQWRkcmVzcyh7IGNoYWluOiBzZWxmLmdldENoYW5nZUNoYWluKHBhcmFtcyksIHZhbGlkYXRlOiB2YWxpZGF0ZSB9KVxuICAgICk7XG4gICAgY29uc3QgbmV3QWRkcmVzc2VzID0geWllbGQgQmx1ZWJpcmQuYWxsKG5ld0FkZHJlc3NQcm9taXNlcyk7XG4gICAgLy8gbGV0J3MgZmluZCBhIG5pY2UsIGVxdWFsIGRpc3RyaWJ1dGlvbiBvZiBvdXIgU2F0b3NoaXMgYW1vbmcgdGhlIG5ldyBhZGRyZXNzZXNcbiAgICBjb25zdCBzcGxpdEFtb3VudHMgPSBzcGxpdE51bWJlckludG9DbG9zZU5hdHVyYWxOdW1iZXJzKGdyb3NzQW1vdW50LCB0YXJnZXQpO1xuICAgIC8vIG1hcCB0aGUgbmV3bHkgY3JlYXRlZCBhZGRyZXNzZXMgdG8gdGhlIGFsbW9zdCBjb21wb25lbnRzIGFtb3VudHMgd2UganVzdCBjYWxjdWxhdGVkXG4gICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IF8uemlwT2JqZWN0KF8ubWFwKG5ld0FkZHJlc3NlcywgJ2FkZHJlc3MnKSwgc3BsaXRBbW91bnRzKTtcbiAgICB0eFBhcmFtcy5ub1NwbGl0Q2hhbmdlID0gdHJ1ZTtcbiAgICAvLyBhdHRlbXB0IHRvIGNyZWF0ZSBhIHRyYW5zYWN0aW9uLiBBcyBpdCBpcyBhIHdhbGxldC1zd2VlcGluZyB0cmFuc2FjdGlvbiB3aXRoIG5vIGZlZSwgd2UgZXhwZWN0IGl0IHRvIGZhaWxcbiAgICB0cnkge1xuICAgICAgeWllbGQgc2VsZi5zZW5kTWFueSh0eFBhcmFtcyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIGFzIGV4cGVjdGVkLCB0aGUgdHJhbnNhY3Rpb24gY3JlYXRpb24gZGlkIGluZGVlZCBmYWlsIGR1ZSB0byBpbnN1ZmZpY2llbnQgZmVlc1xuICAgICAgLy8gdGhlIGVycm9yIHN1Z2dlc3RzIGEgZmVlIHZhbHVlIHdoaWNoIHdlIHRoZW4gdXNlIGZvciB0aGUgdHJhbnNhY3Rpb25cbiAgICAgIC8vIGhvd2V2ZXIsIGxldCdzIG1ha2Ugc3VyZSBpdCB3YXNuJ3Qgc29tZXRoaW5nIGVsc2VcbiAgICAgIGlmICghZXJyb3IuZmVlICYmICghZXJyb3IucmVzdWx0IHx8ICFlcnJvci5yZXN1bHQuZmVlKSkge1xuICAgICAgICAvLyBpZiB0aGUgZXJyb3IgZG9lcyBub3QgY29udGFpbiBhIGZlZSBwcm9wZXJ0eSwgaXQgaXMgc29tZXRoaW5nIGVsc2UgdGhhdCBoYXMgZ29uZSBhd3J5LCBhbmQgd2UgdGhyb3cgaXRcbiAgICAgICAgY29uc3QgZGVidWdQYXJhbXMgPSBfLm9taXQodHhQYXJhbXMsIFsnd2FsbGV0UGFzc3BocmFzZScsICd4cHJ2J10pO1xuICAgICAgICBlcnJvci5tZXNzYWdlICs9IGBcXG5cXG5UWCBQQVJBTVM6XFxuICR7SlNPTi5zdHJpbmdpZnkoZGVidWdQYXJhbXMsIG51bGwsIDQpfWA7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuICAgICAgY29uc3QgYmFzZUZlZSA9IGVycm9yLmZlZSB8fCBlcnJvci5yZXN1bHQuZmVlO1xuICAgICAgbGV0IHRvdGFsRmVlID0gYmFzZUZlZTtcbiAgICAgIGlmIChlcnJvci5yZXN1bHQuYml0Z29GZWUgJiYgZXJyb3IucmVzdWx0LmJpdGdvRmVlLmFtb3VudCkge1xuICAgICAgICB0b3RhbEZlZSArPSBlcnJvci5yZXN1bHQuYml0Z29GZWUuYW1vdW50O1xuICAgICAgICB0eFBhcmFtcy5iaXRnb0ZlZSA9IGVycm9yLnJlc3VsdC5iaXRnb0ZlZTtcbiAgICAgIH1cblxuICAgICAgLy8gTmVlZCB0byBjbGVhciB0aGVzZSBvdXQgc2luY2Ugb25seSAxIG1heSBiZSBzZXRcbiAgICAgIGRlbGV0ZSB0eFBhcmFtcy5mZWU7XG4gICAgICB0eFBhcmFtcy5vcmlnaW5hbEZlZVJhdGUgPSB0eFBhcmFtcy5mZWVSYXRlO1xuICAgICAgZGVsZXRlIHR4UGFyYW1zLmZlZVJhdGU7XG4gICAgICBkZWxldGUgdHhQYXJhbXMuZmVlVHhDb25maXJtVGFyZ2V0O1xuICAgICAgdHhQYXJhbXMuZmVlID0gYmFzZUZlZTtcbiAgICAgIC8vIGluIG9yZGVyIHRvIG1haW50YWluIHRoZSBlcXVhbCBkaXN0cmlidXRpb24sIHdlIG5lZWQgdG8gc3VidHJhY3QgdGhlIGZlZSBmcm9tIHRoZSBjdW11bGF0aXZlIGZ1bmRzXG4gICAgICAvLyBpbiBjYXNlIHNvbWUgdW5zcGVudHMgZ290IHBydW5lZCwgd2UgbmVlZCB0byB1c2UgZXJyb3IucmVzdWx0LmF2YWlsYWJsZVxuICAgICAgY29uc3QgbmV0QW1vdW50ID0gZXJyb3IucmVzdWx0LmF2YWlsYWJsZSAtIHRvdGFsRmVlOyAvLyBhZnRlciBmZWVzXG4gICAgICAvLyB0aGF0IG1lYW5zIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBoYXMgdG8gYmUgcmVjYWxjdWxhdGVkXG4gICAgICBjb25zdCByZW1haW5pbmdTcGxpdEFtb3VudHMgPSBzcGxpdE51bWJlckludG9DbG9zZU5hdHVyYWxOdW1iZXJzKG5ldEFtb3VudCwgdGFyZ2V0KTtcbiAgICAgIC8vIGFuZCB0aGUgZGlzdHJpYnV0aW9uIGFnYWluIG1hcHBlZCB0byB0aGUgbmV3IGFkZHJlc3Nlc1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IF8uemlwT2JqZWN0KF8ubWFwKG5ld0FkZHJlc3NlcywgJ2FkZHJlc3MnKSwgcmVtYWluaW5nU3BsaXRBbW91bnRzKTtcbiAgICB9XG5cbiAgICAvLyB0aGlzIHRpbWUsIHRoZSB0cmFuc2FjdGlvbiBjcmVhdGlvbiBzaG91bGQgd29ya1xuICAgIGxldCBmYW5vdXRUeDtcbiAgICB0cnkge1xuICAgICAgZmFub3V0VHggPSB5aWVsZCBzZWxmLnNlbmRNYW55KHR4UGFyYW1zKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCBkZWJ1Z1BhcmFtcyA9IF8ub21pdCh0eFBhcmFtcywgWyd3YWxsZXRQYXNzcGhyYXNlJywgJ3hwcnYnXSk7XG4gICAgICBlLm1lc3NhZ2UgKz0gYFxcblxcblRYIFBBUkFNUzpcXG4gJHtKU09OLnN0cmluZ2lmeShkZWJ1Z1BhcmFtcywgbnVsbCwgNCl9YDtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUoZmFub3V0VHgpLmFzQ2FsbGJhY2soY2FsbGJhY2spO1xuICB9KSgpLmFzQ2FsbGJhY2soY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciB0byBmYW4gb3V0IG9yIGNvYWxlc2NlIGEgd2FsbGV0J3MgdW5zcGVudHNcbiAqIEBwYXJhbSBwYXJhbXNcbiAqIEBwYXJhbSBjYWxsYmFja1xuICogQHJldHVybnMge1JlcXVlc3R8UHJvbWlzZS48VD58Kn1cbiAqL1xuV2FsbGV0LnByb3RvdHlwZS5yZWdyb3VwVW5zcGVudHMgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbnN0IHRhcmdldCA9IHBhcmFtcy50YXJnZXQ7XG4gIGlmICghXy5pc051bWJlcih0YXJnZXQpIHx8IHRhcmdldCA8IDEgfHwgdGFyZ2V0ICUgMSAhPT0gMCkge1xuICAgIC8vIHRoZSB0YXJnZXQgbXVzdCBiZSBkZWZpbmVkLCBiZSBhIG51bWJlciwgYmUgYXQgbGVhc3Qgb25lLCBhbmQgYmUgYSBuYXR1cmFsIG51bWJlclxuICAgIHRocm93IG5ldyBFcnJvcignVGFyZ2V0IG5lZWRzIHRvIGJlIGEgcG9zaXRpdmUgaW50ZWdlcicpO1xuICB9XG5cbiAgbGV0IG1pbkNvbmZpcm1zID0gcGFyYW1zLm1pbkNvbmZpcm1zO1xuICBpZiAobWluQ29uZmlybXMgPT09IHVuZGVmaW5lZCkge1xuICAgIG1pbkNvbmZpcm1zID0gMTtcbiAgfVxuICBpZiAoIV8uaXNOdW1iZXIobWluQ29uZmlybXMpIHx8IG1pbkNvbmZpcm1zIDwgMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWluQ29uZmlybXMgbmVlZHMgdG8gYmUgYW4gaW50ZWdlciBlcXVhbCB0byBvciBiaWdnZXIgdGhhbiAwJyk7XG4gIH1cblxuICBjb25zdCBzZWxmID0gdGhpcztcbiAgcmV0dXJuIHNlbGYudW5zcGVudHMoeyBtaW5Db25maXJtczogbWluQ29uZmlybXMgfSkudGhlbihmdW5jdGlvbiAodW5zcGVudHMpIHtcbiAgICBpZiAodW5zcGVudHMubGVuZ3RoID09PSB0YXJnZXQpIHtcbiAgICAgIHJldHVybiB1bnNwZW50cztcbiAgICB9IGVsc2UgaWYgKHVuc3BlbnRzLmxlbmd0aCA+IHRhcmdldCkge1xuICAgICAgcmV0dXJuIHNlbGYuY29uc29saWRhdGVVbnNwZW50cyhwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICB9IGVsc2UgaWYgKHVuc3BlbnRzLmxlbmd0aCA8IHRhcmdldCkge1xuICAgICAgcmV0dXJuIHNlbGYuZmFuT3V0VW5zcGVudHMocGFyYW1zLCBjYWxsYmFjayk7XG4gICAgfVxuICB9KTtcbn07XG5cbi8qKlxuICogQ29uc29saWRhdGUgYSB3YWxsZXQncyB1bnNwZW50cyBpbnRvIGZld2VyIHVuc3BlbnRzXG4gKiBAcGFyYW0gcGFyYW1zXG4gKiAgdGFyZ2V0OiBzZXQgaG93IG1hbnkgdW5zcGVudHMgeW91IHdhbnQgdG8gaGF2ZSBpbiB0aGUgZW5kXG4gKiAgbWF4SW5wdXRDb3VudFBlckNvbnNvbGlkYXRpb246IHNldCBob3cgbWFueSBtYXhpbXVtIGlucHV0cyBhcmUgdG8gYmUgcGVybWl0dGVkIHBlciBjb25zb2xpZGF0aW9uIGJhdGNoXG4gKiAgeHBydjogcHJpdmF0ZSBrZXkgdG8gc2lnbiB0cmFuc2FjdGlvblxuICogIHdhbGxldFBhc3NwaHJhc2U6IHdhbGxldCBwYXNzcGhyYXNlIHRvIGRlY3J5cHQgdGhlIHdhbGxldCdzIHByaXZhdGUga2V5XG4gKiAgbWF4SXRlcmF0aW9uQ291bnQ6IG1heGltdW0gbnVtYmVyIG9mIGl0ZXJhdGlvbnMgdG8gYmUgcGVyZm9ybWVkIHVudGlsIGZ1bmN0aW9uIHN0b3BzXG4gKiAgcHJvZ3Jlc3NDYWxsYmFjazogbWV0aG9kIHRvIGJlIGNhbGxlZCB3aXRoIG9iamVjdCBvdXRsaW5pbmcgY3VycmVudCBwcm9ncmVzcyBkZXRhaWxzXG4gKiBAcGFyYW0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHsqfVxuICovXG5XYWxsZXQucHJvdG90eXBlLmNvbnNvbGlkYXRlVW5zcGVudHMgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbJ3dhbGxldFBhc3NwaHJhc2UnLCAneHBydiddLCBjYWxsYmFjayk7XG4gIGNvbnN0IHZhbGlkYXRlID0gcGFyYW1zLnZhbGlkYXRlID09PSB1bmRlZmluZWQgPyB0cnVlIDogcGFyYW1zLnZhbGlkYXRlO1xuXG4gIGxldCB0YXJnZXQgPSBwYXJhbXMudGFyZ2V0O1xuICBpZiAodGFyZ2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0YXJnZXQgPSAxO1xuICB9IGVsc2UgaWYgKCFfLmlzTnVtYmVyKHRhcmdldCkgfHwgdGFyZ2V0IDwgMSB8fCB0YXJnZXQgJSAxICE9PSAwKSB7XG4gICAgLy8gdGhlIHRhcmdldCBtdXN0IGJlIGRlZmluZWQsIGJlIGEgbnVtYmVyLCBiZSBhdCBsZWFzdCBvbmUsIGFuZCBiZSBhIG5hdHVyYWwgbnVtYmVyXG4gICAgdGhyb3cgbmV3IEVycm9yKCdUYXJnZXQgbmVlZHMgdG8gYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyJyk7XG4gIH1cblxuICBpZiAocGFyYW1zLm1heFNpemUgJiYgIV8uaXNOdW1iZXIocGFyYW1zLm1heFNpemUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdtYXhTaXplIHNob3VsZCBiZSBhIG51bWJlcicpO1xuICB9XG5cbiAgaWYgKHBhcmFtcy5taW5TaXplICYmICFfLmlzTnVtYmVyKHBhcmFtcy5taW5TaXplKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWluU2l6ZSBzaG91bGQgYmUgYSBudW1iZXInKTtcbiAgfVxuXG4gIC8vIG1heGltdW0gbnVtYmVyIG9mIGlucHV0cyBwZXIgdHJhbnNhY3Rpb24gZm9yIGNvbnNvbGlkYXRpb25cbiAgY29uc3QgTUFYX0lOUFVUX0NPVU5UID0gMjAwO1xuICBsZXQgbWF4SW5wdXRDb3VudCA9IHBhcmFtcy5tYXhJbnB1dENvdW50UGVyQ29uc29saWRhdGlvbjtcbiAgaWYgKG1heElucHV0Q291bnQgPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIG51bGwgb3IgdW5pZGVudGlmaWVkLCBiZWNhdXNlIGVxdWFsaXR5IHRvIHplcm8gcmV0dXJucyB0cnVlIGluIGlmKCEgY2xhdXNlXG4gICAgbWF4SW5wdXRDb3VudCA9IE1BWF9JTlBVVF9DT1VOVDtcbiAgfVxuICBpZiAodHlwZW9mIG1heElucHV0Q291bnQgIT09ICdudW1iZXInIHx8IG1heElucHV0Q291bnQgPCAyIHx8IG1heElucHV0Q291bnQgJSAxICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNYXhpbXVtIGNvbnNvbGlkYXRpb24gaW5wdXQgY291bnQgbmVlZHMgdG8gYmUgYW4gaW50ZWdlciBlcXVhbCB0byBvciBiaWdnZXIgdGhhbiAyJyk7XG4gIH0gZWxzZSBpZiAobWF4SW5wdXRDb3VudCA+IE1BWF9JTlBVVF9DT1VOVCkge1xuICAgIHRocm93IG5ldyBFcnJvcignTWF4aW11bSBjb25zb2xpZGF0aW9uIGlucHV0IGNvdW50IGNhbm5vdCBiZSBiaWdnZXIgdGhhbiAnICsgTUFYX0lOUFVUX0NPVU5UKTtcbiAgfVxuXG4gIGNvbnN0IG1heEl0ZXJhdGlvbkNvdW50ID0gcGFyYW1zLm1heEl0ZXJhdGlvbkNvdW50IHx8IC0xO1xuICBpZiAoXG4gICAgKHBhcmFtcy5tYXhJdGVyYXRpb25Db3VudCAmJiAoIV8uaXNOdW1iZXIobWF4SXRlcmF0aW9uQ291bnQpIHx8IG1heEl0ZXJhdGlvbkNvdW50IDwgMSkpIHx8XG4gICAgbWF4SXRlcmF0aW9uQ291bnQgJSAxICE9PSAwXG4gICkge1xuICAgIHRocm93IG5ldyBFcnJvcignTWF4aW11bSBpdGVyYXRpb24gY291bnQgbmVlZHMgdG8gYmUgYW4gaW50ZWdlciBlcXVhbCB0byBvciBiaWdnZXIgdGhhbiAxJyk7XG4gIH1cblxuICBsZXQgbWluQ29uZmlybXMgPSBwYXJhbXMubWluQ29uZmlybXM7XG4gIGlmIChtaW5Db25maXJtcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbWluQ29uZmlybXMgPSAxO1xuICB9XG4gIGlmICghXy5pc051bWJlcihtaW5Db25maXJtcykgfHwgbWluQ29uZmlybXMgPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdtaW5Db25maXJtcyBuZWVkcyB0byBiZSBhbiBpbnRlZ2VyIGVxdWFsIHRvIG9yIGJpZ2dlciB0aGFuIDAnKTtcbiAgfVxuXG4gIGxldCBtaW5TaXplID0gcGFyYW1zLm1pblNpemUgfHwgMDtcbiAgaWYgKHBhcmFtcy5mZWVSYXRlKSB7XG4gICAgLy8gZmVlIHJhdGUgaXMgaW4gc2F0b3NoaXMgcGVyIGtCLCBpbnB1dCBzaXplIGluIGJ5dGVzXG4gICAgY29uc3QgZmVlQmFzZWRNaW5TaXplID0gTWF0aC5jZWlsKChWaXJ0dWFsU2l6ZXMudHhQMnNoSW5wdXRTaXplICogcGFyYW1zLmZlZVJhdGUpIC8gMTAwMCk7XG4gICAgaWYgKHBhcmFtcy5taW5TaXplICYmIG1pblNpemUgPCBmZWVCYXNlZE1pblNpemUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncHJvdmlkZWQgbWluU2l6ZSB0b28gbG93IGR1ZSB0byB0b28gaGlnaCBmZWUgcmF0ZScpO1xuICAgIH1cbiAgICBtaW5TaXplID0gTWF0aC5tYXgoZmVlQmFzZWRNaW5TaXplLCBtaW5TaXplKTtcblxuICAgIGlmICghcGFyYW1zLm1pblNpemUpIHtcbiAgICAgIC8vIGZlZSByYXRlLWJhc2VkIG1pbiBzaXplIG5lZWRzIG5vIGxvZ2dpbmcgaWYgaXQgd2FzIHNldCBleHBsaWNpdGx5XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgJ09ubHkgY29uc29saWRhdGluZyB1bnNwZW50cyBsYXJnZXIgdGhhbiAnICtcbiAgICAgICAgICBtaW5TaXplICtcbiAgICAgICAgICAnIHNhdG9zaGlzIHRvIGF2b2lkIHdhc3RpbmcgbW9uZXkgb24gZmVlcy4gVG8gY29uc29saWRhdGUgc21hbGxlciB1bnNwZW50cywgdXNlIGEgbG93ZXIgZmVlIHJhdGUuJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBsZXQgaXRlcmF0aW9uQ291bnQgPSAwO1xuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICBsZXQgY29uc29saWRhdGlvbkluZGV4ID0gMDtcblxuICAvKipcbiAgICogQ29uc29saWRhdGUgb25lIGJhdGNoIG9mIHVwIHRvIE1BWF9JTlBVVF9DT1VOVCB1bnNwZW50cy5cbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBjb25zdCBydW5OZXh0Q29uc29saWRhdGlvbiA9IGNvKGZ1bmN0aW9uKiAoKSB7XG4gICAgY29uc3QgY29uc29saWRhdGlvblRyYW5zYWN0aW9uczogYW55W10gPSBbXTtcbiAgICBsZXQgaXNGaW5hbENvbnNvbGlkYXRpb24gPSBmYWxzZTtcbiAgICBpdGVyYXRpb25Db3VudCsrO1xuICAgIC8qXG4gICAgIFdlIHRha2UgYSBtYXhpbXVtIG9mIHVuc3BlbnRCdWxrU2l6ZUxpbWl0IHVuc3BlbnRzIGZyb20gdGhlIHdhbGxldC4gV2Ugd2FudCB0byBtYWtlIHN1cmUgdGhhdCB3ZSBzd2lwZSB0aGUgd2FsbGV0XG4gICAgIGNsZWFuIG9mIGFsbCBleGNlc3NpdmUgdW5zcGVudHMsIHNvIHdlIGFkZCAxIHRvIHRoZSB0YXJnZXQgdW5zcGVudCBjb3VudCB0byBtYWtlIHN1cmUgd2UgaGF2ZW4ndCBtaXNzZWQgYW55dGhpbmcuXG4gICAgIEluIGNhc2UgdGhlcmUgYXJlIGV2ZW4gbW9yZSB1bnNwZW50cyB0aGFuIHRoYXQsIHRvIG1ha2UgdGhlIGNvbnNvbGlkYXRpb24gYXMgZmFzdCBhcyBwb3NzaWJsZSwgd2UgZXhwYW5kIG91clxuICAgICBzZWxlY3Rpb24gdG8gaW5jbHVkZSBhcyBtYW55IGFzIHRoZSBtYXhpbXVtIHBlcm1pc3NpYmxlIG51bWJlciBvZiBpbnB1dHMgcGVyIGNvbnNvbGlkYXRpb24gYmF0Y2guXG4gICAgIFNob3VsZCB0aGUgdGFyZ2V0IG51bWJlciBvZiB1bnNwZW50cyBiZSBoaWdoZXIgdGhhbiB0aGUgbWF4aW11bSBudW1iZXIgaWYgaW5wdXRzIHBlciBjb25zb2xpZGF0aW9uLFxuICAgICB3ZSBzdGlsbCB3YW50IHRvIGZldGNoIHRoZW0gYWxsIHNpbXBseSB0byBiZSBhYmxlIHRvIGRldGVybWluZSB3aGV0aGVyIG9yIG5vdCBhIGNvbnNvbGlkYXRpb24gY2FuIGJlIHBlcmZvcm1lZFxuICAgICBhdCBhbGwsIHdoaWNoIGlzIGRlcGVuZGVudCBvbiB0aGUgbnVtYmVyIG9mIGFsbCB1bnNwZW50cyBiZWluZyBoaWdoZXIgdGhhbiB0aGUgdGFyZ2V0LlxuICAgICBJbiB0aGUgbmV4dCB2ZXJzaW9uIG9mIHRoZSB1bnNwZW50cyB2ZXJzaW9uIFNESywgd2Ugd2lsbCBrbm93IHRoZSB0b3RhbCBudW1iZXIgb2YgdW5zcGVudHMgd2l0aG91dCBoYXZpbmcgdG8gZmV0Y2hcbiAgICAgdGhlbSwgYW5kIHRoZXJlZm9yZSB3aWxsIGJlIGFibGUgdG8gc2ltcGxpZnkgdGhpcyBtZXRob2QuXG4gICAgICovXG5cbiAgICBjb25zdCBxdWVyeVBhcmFtczogYW55ID0ge1xuICAgICAgbGltaXQ6IHRhcmdldCArIG1heElucHV0Q291bnQsXG4gICAgICBtaW5Db25maXJtczogbWluQ29uZmlybXMsXG4gICAgICBtaW5TaXplOiBtaW5TaXplLFxuICAgIH07XG4gICAgaWYgKHBhcmFtcy5tYXhTaXplKSB7XG4gICAgICBxdWVyeVBhcmFtcy5tYXhTaXplID0gcGFyYW1zLm1heFNpemU7XG4gICAgfVxuICAgIGNvbnN0IGFsbFVuc3BlbnRzID0gKHlpZWxkIHNlbGYudW5zcGVudHMocXVlcnlQYXJhbXMpKSBhcyBhbnk7XG4gICAgLy8gdGhpcyBjb25zb2xpZGF0aW9uIGlzIGVzc2VudGlhbGx5IGp1c3QgYSB3YXN0ZSBvZiBtb25leVxuICAgIGlmIChhbGxVbnNwZW50cy5sZW5ndGggPD0gdGFyZ2V0KSB7XG4gICAgICBpZiAoaXRlcmF0aW9uQ291bnQgPD0gMSkge1xuICAgICAgICAvLyB0aGlzIGlzIHRoZSBmaXJzdCBpdGVyYXRpb24sIHNvIHRoZSBtZXRob2QgaXMgaW5jb3JyZWN0XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmV3ZXIgdW5zcGVudHMgdGhhbiBjb25zb2xpZGF0aW9uIHRhcmdldC4gVXNlIGZhbk91dFVuc3BlbnRzIGluc3RlYWQuJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBpdCdzIGEgbGF0ZXIgaXRlcmF0aW9uLCBzbyB0aGUgdGFyZ2V0IG1heSBoYXZlIGJlZW4gc3VycGFzc2VkIChkdWUgdG8gY29uZmlybWF0aW9ucyBpbiB0aGUgYmFja2dyb3VuZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEb25lJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYWxsVW5zcGVudHNDb3VudCA9IGFsbFVuc3BlbnRzLmxlbmd0aDtcblxuICAgIC8vIGhvdyBtYW55IG9mIHRoZSB1bnNwZW50cyBkbyB3ZSB3YW50IHRvIGNvbnNvbGlkYXRlP1xuICAgIC8vIHRoZSArMSBpcyBiZWNhdXNlIHRoZSBjb25zb2xpZGF0ZWQgYmxvY2sgYmVjb21lcyBhIG5ldyB1bnNwZW50IGxhdGVyXG4gICAgbGV0IHRhcmdldElucHV0Q291bnQgPSBhbGxVbnNwZW50c0NvdW50IC0gdGFyZ2V0ICsgMTtcbiAgICB0YXJnZXRJbnB1dENvdW50ID0gTWF0aC5taW4odGFyZ2V0SW5wdXRDb3VudCwgYWxsVW5zcGVudHMubGVuZ3RoKTtcblxuICAgIC8vIGlmIHRoZSB0YXJnZXRJbnB1dENvdW50IHJlcXVpcmVzIG1vcmUgaW5wdXRzIHRoYW4gd2UgYWxsb3cgcGVyIGJhdGNoLCB3ZSByZWR1Y2UgdGhlIG51bWJlclxuICAgIGNvbnN0IGlucHV0Q291bnQgPSBNYXRoLm1pbih0YXJnZXRJbnB1dENvdW50LCBtYXhJbnB1dENvdW50KTtcblxuICAgIC8vIGlmIGVpdGhlciB0aGUgbnVtYmVyIG9mIGlucHV0cyBsZWZ0IHRvIGNvYWxlc2NlIGVxdWFscyB0aGUgbnVtYmVyIHdlIHdpbGwgY29hbGVzY2UgaW4gdGhpcyBpdGVyYXRpb25cbiAgICAvLyBvciBpZiB0aGUgbnVtYmVyIG9mIGl0ZXJhdGlvbnMgbWF0Y2hlcyB0aGUgbWF4aW11bSBwZXJtaXR0ZWQgbnVtYmVyXG4gICAgaXNGaW5hbENvbnNvbGlkYXRpb24gPSBpbnB1dENvdW50ID09PSB0YXJnZXRJbnB1dENvdW50IHx8IGl0ZXJhdGlvbkNvdW50ID09PSBtYXhJdGVyYXRpb25Db3VudDtcblxuICAgIGNvbnN0IGN1cnJlbnRDaHVuayA9IGFsbFVuc3BlbnRzLnNwbGljZSgwLCBpbnB1dENvdW50KTtcbiAgICBjb25zdCBjaGFuZ2VDaGFpbiA9IHNlbGYuZ2V0Q2hhbmdlQ2hhaW4ocGFyYW1zKTtcbiAgICBjb25zdCBuZXdBZGRyZXNzID0gKHlpZWxkIHNlbGYuY3JlYXRlQWRkcmVzcyh7IGNoYWluOiBjaGFuZ2VDaGFpbiwgdmFsaWRhdGU6IHZhbGlkYXRlIH0pKSBhcyBhbnk7XG4gICAgY29uc3QgdHhQYXJhbXMgPSBfLmV4dGVuZCh7fSwgcGFyYW1zKTtcbiAgICBjb25zdCBjdXJyZW50QWRkcmVzcyA9IG5ld0FkZHJlc3M7XG4gICAgLy8gdGhlIHRvdGFsIGFtb3VudCB0aGF0IHdlIGFyZSBjb25zb2xpZGF0aW5nIHdpdGhpbiB0aGlzIGJhdGNoXG4gICAgY29uc3QgZ3Jvc3NBbW91bnQgPSBfKGN1cnJlbnRDaHVuaykubWFwKCd2YWx1ZScpLnN1bSgpOyAvLyBiZWZvcmUgZmVlc1xuXG4gICAgdHhQYXJhbXMudW5zcGVudHMgPSBjdXJyZW50Q2h1bms7XG4gICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IHt9O1xuICAgIHR4UGFyYW1zLnJlY2lwaWVudHNbbmV3QWRkcmVzcy5hZGRyZXNzXSA9IGdyb3NzQW1vdW50O1xuICAgIHR4UGFyYW1zLm5vU3BsaXRDaGFuZ2UgPSB0cnVlO1xuXG4gICAgaWYgKHR4UGFyYW1zLnVuc3BlbnRzLmxlbmd0aCA8PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RvbmUnKTtcbiAgICB9XG5cbiAgICAvLyBsZXQncyBhdHRlbXB0IHRvIGNyZWF0ZSB0aGlzIHRyYW5zYWN0aW9uLiBXZSBleHBlY3QgaXQgdG8gZmFpbCBiZWNhdXNlIG5vIGZlZSBpcyBzZXQuXG4gICAgdHJ5IHtcbiAgICAgIHlpZWxkIHNlbGYuc2VuZE1hbnkodHhQYXJhbXMpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyB0aGlzIGVycm9yIHNob3VsZCBvY2N1ciBkdWUgdG8gaW5zdWZmaWNpZW50IGZ1bmRzXG4gICAgICAvLyBob3dldmVyLCBsZXQncyBtYWtlIHN1cmUgaXQgd2Fzbid0IHNvbWV0aGluZyBlbHNlXG4gICAgICBpZiAoIWVycm9yLmZlZSAmJiAoIWVycm9yLnJlc3VsdCB8fCAhZXJyb3IucmVzdWx0LmZlZSkpIHtcbiAgICAgICAgLy8gaWYgdGhlIGVycm9yIGRvZXMgbm90IGNvbnRhaW4gYSBmZWUgcHJvcGVydHksIGl0IGlzIHNvbWV0aGluZyBlbHNlIHRoYXQgaGFzIGdvbmUgYXdyeSwgYW5kIHdlIHRocm93IGl0XG4gICAgICAgIGNvbnN0IGRlYnVnUGFyYW1zID0gXy5vbWl0KHR4UGFyYW1zLCBbJ3dhbGxldFBhc3NwaHJhc2UnLCAneHBydiddKTtcbiAgICAgICAgZXJyb3IubWVzc2FnZSArPSBgXFxuXFxuVFggUEFSQU1TOlxcbiAke0pTT04uc3RyaW5naWZ5KGRlYnVnUGFyYW1zLCBudWxsLCA0KX1gO1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJhc2VGZWUgPSBlcnJvci5mZWUgfHwgZXJyb3IucmVzdWx0LmZlZTtcbiAgICAgIGxldCBiaXRnb0ZlZSA9IDA7XG4gICAgICBsZXQgdG90YWxGZWUgPSBiYXNlRmVlO1xuICAgICAgaWYgKGVycm9yLnJlc3VsdC5iaXRnb0ZlZSAmJiBlcnJvci5yZXN1bHQuYml0Z29GZWUuYW1vdW50KSB7XG4gICAgICAgIGJpdGdvRmVlID0gZXJyb3IucmVzdWx0LmJpdGdvRmVlLmFtb3VudDtcbiAgICAgICAgdG90YWxGZWUgKz0gYml0Z29GZWU7XG4gICAgICAgIHR4UGFyYW1zLmJpdGdvRmVlID0gZXJyb3IucmVzdWx0LmJpdGdvRmVlO1xuICAgICAgfVxuXG4gICAgICAvLyBpZiB0aGUgbmV0IGFtb3VudCBpcyBuZWdhdGl2ZSwgaXQgc2hvdWxkIGJlIHJlcGxhY2VkIHdpdGggdGhlIG1pbmltdW0gb3V0cHV0IHNpemVcbiAgICAgIGNvbnN0IG5ldEFtb3VudCA9IE1hdGgubWF4KGVycm9yLnJlc3VsdC5hdmFpbGFibGUgLSB0b3RhbEZlZSwgc2VsZi5iaXRnby5nZXRDb25zdGFudHMoKS5taW5PdXRwdXRTaXplKTtcbiAgICAgIC8vIE5lZWQgdG8gY2xlYXIgdGhlc2Ugb3V0IHNpbmNlIG9ubHkgMSBtYXkgYmUgc2V0XG4gICAgICBkZWxldGUgdHhQYXJhbXMuZmVlO1xuICAgICAgdHhQYXJhbXMub3JpZ2luYWxGZWVSYXRlID0gdHhQYXJhbXMuZmVlUmF0ZTtcbiAgICAgIGRlbGV0ZSB0eFBhcmFtcy5mZWVSYXRlO1xuICAgICAgZGVsZXRlIHR4UGFyYW1zLmZlZVR4Q29uZmlybVRhcmdldDtcblxuICAgICAgLy8gd2Ugc2V0IHRoZSBmZWUgZXhwbGljaXRseVxuICAgICAgdHhQYXJhbXMuZmVlID0gZXJyb3IucmVzdWx0LmF2YWlsYWJsZSAtIG5ldEFtb3VudCAtIGJpdGdvRmVlO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50c1tuZXdBZGRyZXNzLmFkZHJlc3NdID0gbmV0QW1vdW50O1xuICAgIH1cbiAgICAvLyB0aGlzIHRyYW5zYWN0aW9uLCBvbiB0aGUgb3RoZXIgaGFuZCwgc2hvdWxkIGJlIGNyZWF0ZWQgd2l0aCBubyBpc3N1ZXMsIGJlY2F1c2UgYW4gYXBwcm9wcmlhdGUgZmVlIGlzIHNldFxuICAgIGxldCBzZW50VHg7XG4gICAgdHJ5IHtcbiAgICAgIHNlbnRUeCA9IHlpZWxkIHNlbGYuc2VuZE1hbnkodHhQYXJhbXMpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnN0IGRlYnVnUGFyYW1zID0gXy5vbWl0KHR4UGFyYW1zLCBbJ3dhbGxldFBhc3NwaHJhc2UnLCAneHBydiddKTtcbiAgICAgIGUubWVzc2FnZSArPSBgXFxuXFxuVFggUEFSQU1TOlxcbiAke0pTT04uc3RyaW5naWZ5KGRlYnVnUGFyYW1zLCBudWxsLCA0KX1gO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5wdXNoKHNlbnRUeCk7XG4gICAgaWYgKF8uaXNGdW5jdGlvbihwYXJhbXMucHJvZ3Jlc3NDYWxsYmFjaykpIHtcbiAgICAgIHBhcmFtcy5wcm9ncmVzc0NhbGxiYWNrKHtcbiAgICAgICAgdHhpZDogc2VudFR4Lmhhc2gsXG4gICAgICAgIGRlc3RpbmF0aW9uOiBjdXJyZW50QWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiBncm9zc0Ftb3VudCxcbiAgICAgICAgZmVlOiBzZW50VHguZmVlLFxuICAgICAgICBpbnB1dENvdW50OiBpbnB1dENvdW50LFxuICAgICAgICBpbmRleDogY29uc29saWRhdGlvbkluZGV4LFxuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnNvbGlkYXRpb25JbmRleCsrO1xuICAgIGlmICghaXNGaW5hbENvbnNvbGlkYXRpb24pIHtcbiAgICAgIC8vIHRoaXMgbGFzdCBjb25zb2xpZGF0aW9uIGhhcyBub3QgeWV0IGJyb3VnaHQgdGhlIHVuc3BlbnRzIGNvdW50IGRvd24gdG8gdGhlIHRhcmdldCB1bnNwZW50IGNvdW50XG4gICAgICAvLyB0aGVyZWZvcmUsIHdlIHByb2NlZWQgYnkgY29uc29saWRhdGluZyB5ZXQgYW5vdGhlciBiYXRjaFxuICAgICAgLy8gYmVmb3JlIHdlIGRvIHRoYXQsIHdlIHdhaXQgMSBzZWNvbmQgc28gdGhhdCB0aGUgbmV3bHkgY3JlYXRlZCB1bnNwZW50IHdpbGwgYmUgZmV0Y2hlZCBpbiB0aGUgbmV4dCBiYXRjaFxuICAgICAgeWllbGQgQmx1ZWJpcmQuZGVsYXkoMTAwMCk7XG4gICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLnB1c2goLi4uKCh5aWVsZCBydW5OZXh0Q29uc29saWRhdGlvbigpKSBhcyBhbnkpKTtcbiAgICB9XG4gICAgLy8gdGhpcyBpcyB0aGUgZmluYWwgY29uc29saWRhdGlvbiB0cmFuc2FjdGlvbi4gV2UgcmV0dXJuIGFsbCB0aGUgb25lcyB3ZSd2ZSBoYWQgc28gZmFyXG4gICAgcmV0dXJuIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnM7XG4gIH0pO1xuXG4gIHJldHVybiBydW5OZXh0Q29uc29saWRhdGlvbih0aGlzLCB0YXJnZXQpXG4gICAgLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGlmIChlcnIubWVzc2FnZSA9PT0gJ0RvbmUnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9KVxuICAgIC5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbldhbGxldC5wcm90b3R5cGUuc2hhcmVXYWxsZXQgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnZW1haWwnLCAncGVybWlzc2lvbnMnXSwgWyd3YWxsZXRQYXNzcGhyYXNlJywgJ21lc3NhZ2UnXSwgY2FsbGJhY2spO1xuXG4gIGlmIChwYXJhbXMucmVzaGFyZSAhPT0gdW5kZWZpbmVkICYmICFfLmlzQm9vbGVhbihwYXJhbXMucmVzaGFyZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIHJlc2hhcmUgdG8gYmUgYSBib29sZWFuLicpO1xuICB9XG5cbiAgaWYgKHBhcmFtcy5za2lwS2V5Y2hhaW4gIT09IHVuZGVmaW5lZCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLnNraXBLZXljaGFpbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIHNraXBLZXljaGFpbiB0byBiZSBhIGJvb2xlYW4uICcpO1xuICB9XG4gIGNvbnN0IG5lZWRzS2V5Y2hhaW4gPSAhcGFyYW1zLnNraXBLZXljaGFpbiAmJiBwYXJhbXMucGVybWlzc2lvbnMuaW5kZXhPZignc3BlbmQnKSAhPT0gLTE7XG5cbiAgaWYgKHBhcmFtcy5kaXNhYmxlRW1haWwgIT09IHVuZGVmaW5lZCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmRpc2FibGVFbWFpbCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIGRpc2FibGVFbWFpbCB0byBiZSBhIGJvb2xlYW4uJyk7XG4gIH1cblxuICBjb25zdCBzZWxmID0gdGhpcztcbiAgbGV0IHNoYXJpbmc7XG4gIGxldCBzaGFyZWRLZXljaGFpbjtcbiAgcmV0dXJuIHRoaXMuYml0Z29cbiAgICAuZ2V0U2hhcmluZ0tleSh7IGVtYWlsOiBwYXJhbXMuZW1haWwudG9Mb3dlckNhc2UoKSB9KVxuICAgIC50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgIHNoYXJpbmcgPSByZXN1bHQ7XG5cbiAgICAgIGlmIChuZWVkc0tleWNoYWluKSB7XG4gICAgICAgIHJldHVybiBzZWxmLmdldEVuY3J5cHRlZFVzZXJLZXljaGFpbih7fSkudGhlbihmdW5jdGlvbiAoa2V5Y2hhaW4pIHtcbiAgICAgICAgICAvLyBEZWNyeXB0IHRoZSB1c2VyIGtleSB3aXRoIGEgcGFzc3BocmFzZVxuICAgICAgICAgIGlmIChrZXljaGFpbi5lbmNyeXB0ZWRYcHJ2KSB7XG4gICAgICAgICAgICBpZiAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyB3YWxsZXRQYXNzcGhyYXNlIGFyZ3VtZW50Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBrZXljaGFpbi54cHJ2ID0gc2VsZi5iaXRnby5kZWNyeXB0KHsgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLCBpbnB1dDoga2V5Y2hhaW4uZW5jcnlwdGVkWHBydiB9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZGVjcnlwdCB1c2VyIGtleWNoYWluJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGVja2V5ID0gbWFrZVJhbmRvbUtleSgpO1xuICAgICAgICAgICAgY29uc3Qgc2VjcmV0ID0gZ2V0U2hhcmVkU2VjcmV0KGVja2V5LCBCdWZmZXIuZnJvbShzaGFyaW5nLnB1YmtleSwgJ2hleCcpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICAgICAgICBjb25zdCBuZXdFbmNyeXB0ZWRYcHJ2ID0gc2VsZi5iaXRnby5lbmNyeXB0KHsgcGFzc3dvcmQ6IHNlY3JldCwgaW5wdXQ6IGtleWNoYWluLnhwcnYgfSk7XG5cbiAgICAgICAgICAgIHNoYXJlZEtleWNoYWluID0ge1xuICAgICAgICAgICAgICB4cHViOiBrZXljaGFpbi54cHViLFxuICAgICAgICAgICAgICBlbmNyeXB0ZWRYcHJ2OiBuZXdFbmNyeXB0ZWRYcHJ2LFxuICAgICAgICAgICAgICBmcm9tUHViS2V5OiBlY2tleS5wdWJsaWNLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgICAgICB0b1B1YktleTogc2hhcmluZy5wdWJrZXksXG4gICAgICAgICAgICAgIHBhdGg6IHNoYXJpbmcucGF0aCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIGludGVyZmFjZSBPcHRpb25zIHtcbiAgICAgICAgdXNlcjogYW55O1xuICAgICAgICBwZXJtaXNzaW9uczogc3RyaW5nO1xuICAgICAgICByZXNoYXJlOiBib29sZWFuO1xuICAgICAgICBtZXNzYWdlOiBzdHJpbmc7XG4gICAgICAgIGRpc2FibGVFbWFpbDogYW55O1xuICAgICAgICBrZXljaGFpbj86IGFueTtcbiAgICAgICAgc2tpcEtleWNoYWluPzogYm9vbGVhbjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3B0aW9uczogT3B0aW9ucyA9IHtcbiAgICAgICAgdXNlcjogc2hhcmluZy51c2VySWQsXG4gICAgICAgIHBlcm1pc3Npb25zOiBwYXJhbXMucGVybWlzc2lvbnMsXG4gICAgICAgIHJlc2hhcmU6IHBhcmFtcy5yZXNoYXJlLFxuICAgICAgICBtZXNzYWdlOiBwYXJhbXMubWVzc2FnZSxcbiAgICAgICAgZGlzYWJsZUVtYWlsOiBwYXJhbXMuZGlzYWJsZUVtYWlsLFxuICAgICAgfTtcbiAgICAgIGlmIChzaGFyZWRLZXljaGFpbikge1xuICAgICAgICBvcHRpb25zLmtleWNoYWluID0gc2hhcmVkS2V5Y2hhaW47XG4gICAgICB9IGVsc2UgaWYgKHBhcmFtcy5za2lwS2V5Y2hhaW4pIHtcbiAgICAgICAgb3B0aW9ucy5rZXljaGFpbiA9IHt9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VsZi5jcmVhdGVTaGFyZShvcHRpb25zKTtcbiAgICB9KVxuICAgIC5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbldhbGxldC5wcm90b3R5cGUucmVtb3ZlVXNlciA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd1c2VyJ10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUoXG4gICAgdGhpcy5iaXRnb1xuICAgICAgLmRlbCh0aGlzLnVybCgnL3VzZXIvJyArIHBhcmFtcy51c2VyKSlcbiAgICAgIC5zZW5kKClcbiAgICAgIC5yZXN1bHQoKVxuICApLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuV2FsbGV0LnByb3RvdHlwZS5nZXRQb2xpY3kgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZ2V0KHRoaXMudXJsKCcvcG9saWN5JykpLnNlbmQoKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG5XYWxsZXQucHJvdG90eXBlLmdldFBvbGljeVN0YXR1cyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5nZXQodGhpcy51cmwoJy9wb2xpY3kvc3RhdHVzJykpLnNlbmQoKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG5XYWxsZXQucHJvdG90eXBlLnNldFBvbGljeVJ1bGUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnaWQnLCAndHlwZSddLCBbJ21lc3NhZ2UnXSwgY2FsbGJhY2spO1xuXG4gIGlmICghXy5pc09iamVjdChwYXJhbXMuY29uZGl0aW9uKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBwYXJhbWV0ZXI6IGNvbmRpdGlvbnMgb2JqZWN0Jyk7XG4gIH1cblxuICBpZiAoIV8uaXNPYmplY3QocGFyYW1zLmFjdGlvbikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcGFyYW1ldGVyOiBhY3Rpb24gb2JqZWN0Jyk7XG4gIH1cblxuICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZSh0aGlzLmJpdGdvLnB1dCh0aGlzLnVybCgnL3BvbGljeS9ydWxlJykpLnNlbmQocGFyYW1zKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG5XYWxsZXQucHJvdG90eXBlLnJlbW92ZVBvbGljeVJ1bGUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnaWQnXSwgWydtZXNzYWdlJ10sIGNhbGxiYWNrKTtcblxuICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZSh0aGlzLmJpdGdvLmRlbCh0aGlzLnVybCgnL3BvbGljeS9ydWxlJykpLnNlbmQocGFyYW1zKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG5XYWxsZXQucHJvdG90eXBlLmxpc3RXZWJob29rcyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUodGhpcy5iaXRnby5nZXQodGhpcy51cmwoJy93ZWJob29rcycpKS5zZW5kKCkucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBTaW11bGF0ZSB3YWxsZXQgd2ViaG9vaywgY3VycmVudGx5IGZvciB3ZWJob29rcyBvZiB0eXBlIHRyYW5zYWN0aW9uIGFuZCBwZW5kaW5nIGFwcHJvdmFsXG4gKiBAcGFyYW0gcGFyYW1zXG4gKiAtIHdlYmhvb2tJZCAocmVxdWlyZWQpOiBpZCBvZiB0aGUgd2ViaG9vayB0byBiZSBzaW11bGF0ZWRcbiAqIC0gdHhIYXNoIChvcHRpb25hbCBidXQgcmVxdWlyZWQgZm9yIHRyYW5zYWN0aW9uIHdlYmhvb2tzKSBoYXNoIG9mIHRoZSBzaW11bGF0ZWQgdHJhbnNhY3Rpb25cbiAqIC0gcGVuZGluZ0FwcHJvdmFsSWQgKG9wdGlvbmFsIGJ1dCByZXF1aXJlZCBmb3IgcGVuZGluZyBhcHByb3ZhbCB3ZWJob29rcykgaWQgb2YgdGhlIHNpbXVsYXRlZCBwZW5kaW5nIGFwcHJvdmFsXG4gKiBAcGFyYW0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHsqfVxuICovXG5XYWxsZXQucHJvdG90eXBlLnNpbXVsYXRlV2ViaG9vayA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd3ZWJob29rSWQnXSwgWyd0eEhhc2gnLCAncGVuZGluZ0FwcHJvdmFsSWQnXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IGhhc1R4SGFzaCA9ICEhcGFyYW1zLnR4SGFzaDtcbiAgY29uc3QgaGFzUGVuZGluZ0FwcHJvdmFsSWQgPSAhIXBhcmFtcy5wZW5kaW5nQXBwcm92YWxJZDtcblxuICBpZiAoKGhhc1R4SGFzaCAmJiBoYXNQZW5kaW5nQXBwcm92YWxJZCkgfHwgKCFoYXNUeEhhc2ggJiYgIWhhc1BlbmRpbmdBcHByb3ZhbElkKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignbXVzdCBzdXBwbHkgZWl0aGVyIHR4SGFzaCBvciBwZW5kaW5nQXBwcm92YWxJZCwgYnV0IG5vdCBib3RoJyk7XG4gIH1cblxuICAvLyBkZXBlbmRpbmcgb24gdGhlIGNvaW4gdHlwZSBvZiB0aGUgd2FsbGV0LCB0aGUgdHhIYXNoIGhhcyB0byBhZGhlcmUgdG8gaXRzIHJlc3BlY3RpdmUgZm9ybWF0XG4gIC8vIGJ1dCB0aGUgc2VydmVyIHRha2VzIGNhcmUgb2YgdGhhdFxuXG4gIC8vIG9ubHkgdGFrZSB0aGUgdHhIYXNoIGFuZCBwZW5kaW5nQXBwcm92YWxJZCBwcm9wZXJ0aWVzXG4gIGNvbnN0IGZpbHRlcmVkUGFyYW1zID0gXy5waWNrKHBhcmFtcywgWyd0eEhhc2gnLCAncGVuZGluZ0FwcHJvdmFsSWQnXSk7XG5cbiAgY29uc3Qgd2ViaG9va0lkID0gcGFyYW1zLndlYmhvb2tJZDtcbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUoXG4gICAgdGhpcy5iaXRnb1xuICAgICAgLnBvc3QodGhpcy51cmwoJy93ZWJob29rcy8nICsgd2ViaG9va0lkICsgJy9zaW11bGF0ZScpKVxuICAgICAgLnNlbmQoZmlsdGVyZWRQYXJhbXMpXG4gICAgICAucmVzdWx0KClcbiAgKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbldhbGxldC5wcm90b3R5cGUuYWRkV2ViaG9vayA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd1cmwnLCAndHlwZSddLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28ucG9zdCh0aGlzLnVybCgnL3dlYmhvb2tzJykpLnNlbmQocGFyYW1zKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG5XYWxsZXQucHJvdG90eXBlLnJlbW92ZVdlYmhvb2sgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsndXJsJywgJ3R5cGUnXSwgW10sIGNhbGxiYWNrKTtcblxuICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZSh0aGlzLmJpdGdvLmRlbCh0aGlzLnVybCgnL3dlYmhvb2tzJykpLnNlbmQocGFyYW1zKS5yZXN1bHQoKSkubm9kZWlmeShjYWxsYmFjayk7XG59O1xuXG5XYWxsZXQucHJvdG90eXBlLmVzdGltYXRlRmVlID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgaWYgKHBhcmFtcy5hbW91bnQgJiYgcGFyYW1zLnJlY2lwaWVudHMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBzcGVjaWZ5IGJvdGggYW1vdW50IGFzIHdlbGwgYXMgcmVjaXBpZW50cycpO1xuICB9XG4gIGlmIChwYXJhbXMucmVjaXBpZW50cyAmJiAhXy5pc09iamVjdChwYXJhbXMucmVjaXBpZW50cykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlY2lwaWVudHMgbXVzdCBiZSBhcnJheSBvZiB7IGFkZHJlc3M6IGFiYywgYW1vdW50OiAxMDAwMDAgfSBvYmplY3RzJyk7XG4gIH1cbiAgaWYgKHBhcmFtcy5hbW91bnQgJiYgIV8uaXNOdW1iZXIocGFyYW1zLmFtb3VudCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYW1vdW50IGFyZ3VtZW50LCBleHBlY3RpbmcgbnVtYmVyJyk7XG4gIH1cblxuICBjb25zdCByZWNpcGllbnRzID0gcGFyYW1zLnJlY2lwaWVudHMgfHwgW107XG5cbiAgaWYgKHBhcmFtcy5hbW91bnQpIHtcbiAgICAvLyBvbmx5IHRoZSBhbW91bnQgd2FzIHBhc3NlZCBpbiwgc28gd2UgbmVlZCB0byBtYWtlIGEgZmFsc2UgcmVjaXBpZW50IHRvIHJ1biBjcmVhdGVUcmFuc2FjdGlvbiB3aXRoXG4gICAgcmVjaXBpZW50cy5wdXNoKHtcbiAgICAgIGFkZHJlc3M6IGNvbW1vbi5FbnZpcm9ubWVudHNbdGhpcy5iaXRnby5lbnZdLnNpZ25pbmdBZGRyZXNzLCAvLyBhbnkgYWRkcmVzcyB3aWxsIGRvXG4gICAgICBhbW91bnQ6IHBhcmFtcy5hbW91bnQsXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCB0cmFuc2FjdGlvblBhcmFtcyA9IF8uZXh0ZW5kKHt9LCBwYXJhbXMpO1xuICB0cmFuc2FjdGlvblBhcmFtcy5hbW91bnQgPSB1bmRlZmluZWQ7XG4gIHRyYW5zYWN0aW9uUGFyYW1zLnJlY2lwaWVudHMgPSByZWNpcGllbnRzO1xuXG4gIHJldHVybiB0aGlzLmNyZWF0ZVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uUGFyYW1zKS50aGVuKGZ1bmN0aW9uICh0eCkge1xuICAgIHJldHVybiB7XG4gICAgICBlc3RpbWF0ZWRTaXplOiB0eC5lc3RpbWF0ZWRTaXplLFxuICAgICAgZmVlOiB0eC5mZWUsXG4gICAgICBmZWVSYXRlOiB0eC5mZWVSYXRlLFxuICAgIH07XG4gIH0pO1xufTtcblxuLy8gTm90IGZ1bGx5IGltcGxlbWVudGVkIC8gcmVsZWFzZWQgb24gU0RLLiBUZXN0aW5nIGZvciBub3cuXG5XYWxsZXQucHJvdG90eXBlLnVwZGF0ZVBvbGljeVJ1bGUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnaWQnLCAndHlwZSddLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28ucHV0KHRoaXMudXJsKCcvcG9saWN5L3J1bGUnKSkuc2VuZChwYXJhbXMpLnJlc3VsdCgpKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbldhbGxldC5wcm90b3R5cGUuZGVsZXRlUG9saWN5UnVsZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWydpZCddLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBCbHVlYmlyZC5yZXNvbHZlKHRoaXMuYml0Z28uZGVsKHRoaXMudXJsKCcvcG9saWN5L3J1bGUnKSkuc2VuZChwYXJhbXMpLnJlc3VsdCgpKS5ub2RlaWZ5KGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBnZXRCaXRHb0ZlZVxuLy8gR2V0IHRoZSByZXF1aXJlZCBvbi10cmFuc2FjdGlvbiBCaXRHbyBmZWVcbi8vXG5XYWxsZXQucHJvdG90eXBlLmdldEJpdEdvRmVlID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgW10sIGNhbGxiYWNrKTtcbiAgaWYgKCFfLmlzTnVtYmVyKHBhcmFtcy5hbW91bnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFtb3VudCBhcmd1bWVudCcpO1xuICB9XG4gIGlmIChwYXJhbXMuaW5zdGFudCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmluc3RhbnQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGluc3RhbnQgYXJndW1lbnQnKTtcbiAgfVxuICByZXR1cm4gQmx1ZWJpcmQucmVzb2x2ZSh0aGlzLmJpdGdvLmdldCh0aGlzLnVybCgnL2JpbGxpbmcvZmVlJykpLnF1ZXJ5KHBhcmFtcykucmVzdWx0KCkpLm5vZGVpZnkoY2FsbGJhY2spO1xufTtcblxuZXhwb3J0ID0gV2FsbGV0O1xuIl19