@bitgo-beta/sdk-coin-trx 1.2.3-alpha.397 → 1.2.3-alpha.399

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 (80) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +7 -7
  3. package/dist/src/index.d.ts +0 -6
  4. package/dist/src/index.d.ts.map +0 -1
  5. package/dist/src/index.js +0 -22
  6. package/dist/src/lib/address.d.ts +0 -11
  7. package/dist/src/lib/address.d.ts.map +0 -1
  8. package/dist/src/lib/address.js +0 -13
  9. package/dist/src/lib/builder.d.ts +0 -3
  10. package/dist/src/lib/builder.d.ts.map +0 -1
  11. package/dist/src/lib/builder.js +0 -10
  12. package/dist/src/lib/constants.d.ts +0 -3
  13. package/dist/src/lib/constants.d.ts.map +0 -1
  14. package/dist/src/lib/constants.js +0 -6
  15. package/dist/src/lib/contractCallBuilder.d.ts +0 -62
  16. package/dist/src/lib/contractCallBuilder.d.ts.map +0 -1
  17. package/dist/src/lib/contractCallBuilder.js +0 -218
  18. package/dist/src/lib/delegateResourceTxBuilder.d.ts +0 -27
  19. package/dist/src/lib/delegateResourceTxBuilder.d.ts.map +0 -1
  20. package/dist/src/lib/delegateResourceTxBuilder.js +0 -98
  21. package/dist/src/lib/enum.d.ts +0 -58
  22. package/dist/src/lib/enum.d.ts.map +0 -1
  23. package/dist/src/lib/enum.js +0 -64
  24. package/dist/src/lib/freezeBalanceTxBuilder.d.ts +0 -71
  25. package/dist/src/lib/freezeBalanceTxBuilder.d.ts.map +0 -1
  26. package/dist/src/lib/freezeBalanceTxBuilder.js +0 -211
  27. package/dist/src/lib/iface.d.ts +0 -321
  28. package/dist/src/lib/iface.d.ts.map +0 -1
  29. package/dist/src/lib/iface.js +0 -3
  30. package/dist/src/lib/index.d.ts +0 -12
  31. package/dist/src/lib/index.d.ts.map +0 -1
  32. package/dist/src/lib/index.js +0 -53
  33. package/dist/src/lib/keyPair.d.ts +0 -43
  34. package/dist/src/lib/keyPair.d.ts.map +0 -1
  35. package/dist/src/lib/keyPair.js +0 -134
  36. package/dist/src/lib/resourceManagementTxBuilder.d.ts +0 -72
  37. package/dist/src/lib/resourceManagementTxBuilder.d.ts.map +0 -1
  38. package/dist/src/lib/resourceManagementTxBuilder.js +0 -150
  39. package/dist/src/lib/tokenTransferBuilder.d.ts +0 -23
  40. package/dist/src/lib/tokenTransferBuilder.d.ts.map +0 -1
  41. package/dist/src/lib/tokenTransferBuilder.js +0 -42
  42. package/dist/src/lib/transaction.d.ts +0 -74
  43. package/dist/src/lib/transaction.d.ts.map +0 -1
  44. package/dist/src/lib/transaction.js +0 -312
  45. package/dist/src/lib/transactionBuilder.d.ts +0 -110
  46. package/dist/src/lib/transactionBuilder.d.ts.map +0 -1
  47. package/dist/src/lib/transactionBuilder.js +0 -304
  48. package/dist/src/lib/undelegateResourceTxBuilder.d.ts +0 -27
  49. package/dist/src/lib/undelegateResourceTxBuilder.d.ts.map +0 -1
  50. package/dist/src/lib/undelegateResourceTxBuilder.js +0 -98
  51. package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts +0 -65
  52. package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts.map +0 -1
  53. package/dist/src/lib/unfreezeBalanceTxBuilder.js +0 -204
  54. package/dist/src/lib/utils.d.ts +0 -197
  55. package/dist/src/lib/utils.d.ts.map +0 -1
  56. package/dist/src/lib/utils.js +0 -745
  57. package/dist/src/lib/voteWitnessTxBuilder.d.ts +0 -62
  58. package/dist/src/lib/voteWitnessTxBuilder.d.ts.map +0 -1
  59. package/dist/src/lib/voteWitnessTxBuilder.js +0 -219
  60. package/dist/src/lib/withdrawBuilder.d.ts +0 -49
  61. package/dist/src/lib/withdrawBuilder.d.ts.map +0 -1
  62. package/dist/src/lib/withdrawBuilder.js +0 -167
  63. package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts +0 -49
  64. package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts.map +0 -1
  65. package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.js +0 -167
  66. package/dist/src/lib/wrappedBuilder.d.ts +0 -110
  67. package/dist/src/lib/wrappedBuilder.d.ts.map +0 -1
  68. package/dist/src/lib/wrappedBuilder.js +0 -192
  69. package/dist/src/register.d.ts +0 -3
  70. package/dist/src/register.d.ts.map +0 -1
  71. package/dist/src/register.js +0 -15
  72. package/dist/src/trx.d.ts +0 -262
  73. package/dist/src/trx.d.ts.map +0 -1
  74. package/dist/src/trx.js +0 -737
  75. package/dist/src/trxToken.d.ts +0 -38
  76. package/dist/src/trxToken.d.ts.map +0 -1
  77. package/dist/src/trxToken.js +0 -91
  78. package/dist/src/ttrx.d.ts +0 -13
  79. package/dist/src/ttrx.d.ts.map +0 -1
  80. package/dist/src/ttrx.js +0 -14
package/dist/src/trx.js DELETED
@@ -1,737 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.Trx = exports.NodeTypes = exports.DEFAULT_SCAN_FACTOR = exports.RECOVER_TRANSACTION_EXPIRY = exports.SAFE_TRON_TOKEN_TRANSACTION_FEE = exports.SAFE_TRON_TRANSACTION_FEE = exports.MINIMUM_TRON_MSIG_TRANSACTION_FEE = void 0;
37
- /**
38
- * @prettier
39
- */
40
- const secp256k1 = __importStar(require("secp256k1"));
41
- const crypto_1 = require("crypto");
42
- const secp256k1_1 = require("@bitgo-beta/secp256k1");
43
- const request = __importStar(require("superagent"));
44
- const sdk_core_1 = require("@bitgo-beta/sdk-core");
45
- const lib_1 = require("./lib");
46
- const builder_1 = require("./lib/builder");
47
- const lodash_1 = require("lodash");
48
- exports.MINIMUM_TRON_MSIG_TRANSACTION_FEE = 1e6;
49
- exports.SAFE_TRON_TRANSACTION_FEE = 2.1 * 1e6; // TRON foundation recommends 2.1 TRX as fees for guaranteed transaction
50
- exports.SAFE_TRON_TOKEN_TRANSACTION_FEE = 100 * 1e6; // TRON foundation recommends 100 TRX as fees for guaranteed transaction
51
- exports.RECOVER_TRANSACTION_EXPIRY = 86400000; // 24 hour
52
- exports.DEFAULT_SCAN_FACTOR = 20; // default number of receive addresses to scan for funds
53
- var NodeTypes;
54
- (function (NodeTypes) {
55
- NodeTypes[NodeTypes["Full"] = 0] = "Full";
56
- NodeTypes[NodeTypes["Solidity"] = 1] = "Solidity";
57
- })(NodeTypes || (exports.NodeTypes = NodeTypes = {}));
58
- class Trx extends sdk_core_1.BaseCoin {
59
- constructor(bitgo, staticsCoin) {
60
- super(bitgo);
61
- if (!staticsCoin) {
62
- throw new Error('missing required constructor parameter staticsCoin');
63
- }
64
- this._staticsCoin = staticsCoin;
65
- }
66
- getChain() {
67
- return this._staticsCoin.name;
68
- }
69
- getFamily() {
70
- return this._staticsCoin.family;
71
- }
72
- getFullName() {
73
- return this._staticsCoin.fullName;
74
- }
75
- getBaseFactor() {
76
- return Math.pow(10, this._staticsCoin.decimalPlaces);
77
- }
78
- /** @inheritdoc */
79
- transactionDataAllowed() {
80
- return true;
81
- }
82
- /** inherited doc */
83
- getDefaultMultisigType() {
84
- return sdk_core_1.multisigTypes.onchain;
85
- }
86
- static createInstance(bitgo, staticsCoin) {
87
- return new Trx(bitgo, staticsCoin);
88
- }
89
- /**
90
- * Flag for sending value of 0
91
- * @returns {boolean} True if okay to send 0 value, false otherwise
92
- */
93
- valuelessTransferAllowed() {
94
- return true;
95
- }
96
- /** @inheritDoc */
97
- allowsAccountConsolidations() {
98
- return true;
99
- }
100
- /**
101
- * Checks if this is a valid base58
102
- * @param address
103
- */
104
- isValidAddress(address) {
105
- if (!address) {
106
- return false;
107
- }
108
- return lib_1.Utils.isBase58Address(address);
109
- }
110
- /**
111
- * Checks if this is a valid hex address
112
- * @param address hex address
113
- */
114
- isValidHexAddress(address) {
115
- return /^41[0-9a-f]{40}$/i.test(address);
116
- }
117
- /**
118
- * Generate ed25519 key pair
119
- *
120
- * @param seed
121
- * @returns {Object} object with generated pub, prv
122
- */
123
- generateKeyPair(seed) {
124
- // TODO: move this and address creation logic to account-lib
125
- if (!seed) {
126
- // An extended private key has both a normal 256 bit private key and a 256 bit chain code, both of which must be
127
- // random. 512 bits is therefore the maximum entropy and gives us maximum security against cracking.
128
- seed = (0, crypto_1.randomBytes)(512 / 8);
129
- }
130
- const hd = secp256k1_1.bip32.fromSeed(seed);
131
- return {
132
- pub: hd.neutered().toBase58(),
133
- prv: hd.toBase58(),
134
- };
135
- }
136
- isValidXpub(xpub) {
137
- try {
138
- return secp256k1_1.bip32.fromBase58(xpub).isNeutered();
139
- }
140
- catch (e) {
141
- return false;
142
- }
143
- }
144
- isValidPub(pub) {
145
- if (this.isValidXpub(pub)) {
146
- // xpubs can be converted into regular pubs, so technically it is a valid pub
147
- return true;
148
- }
149
- return new RegExp('^04[a-zA-Z0-9]{128}$').test(pub);
150
- }
151
- async parseTransaction(params) {
152
- return {};
153
- }
154
- async isWalletAddress(params) {
155
- throw new sdk_core_1.MethodNotImplementedError();
156
- }
157
- async verifyTransaction(params) {
158
- return true;
159
- }
160
- /**
161
- * Derive a user key using the chain path of the address
162
- * @param key
163
- * @param path
164
- * @returns {string} derived private key
165
- */
166
- deriveKeyWithPath({ key, path }) {
167
- const keychain = secp256k1_1.bip32.fromBase58(key);
168
- const derivedKeyNode = keychain.derivePath(path);
169
- return derivedKeyNode.toBase58();
170
- }
171
- /**
172
- * Assemble keychain and half-sign prebuilt transaction
173
- *
174
- * @param params
175
- * @param params.txPrebuild {Object} prebuild object returned by platform
176
- * @param params.prv {String} user prv
177
- * @returns Bluebird<SignedTransaction>
178
- */
179
- async signTransaction(params) {
180
- const txBuilder = (0, builder_1.getBuilder)(this.getChain()).from(params.txPrebuild.txHex);
181
- let key;
182
- const { chain, index } = params.txPrebuild?.addressInfo ?? { chain: 0, index: 0 };
183
- if (chain === 0 && index === 0) {
184
- key = params.prv;
185
- }
186
- else {
187
- const derivationPath = `0/0/${chain}/${index}`;
188
- key = this.deriveKeyWithPath({ key: params.prv, path: derivationPath });
189
- }
190
- txBuilder.sign({ key });
191
- const transaction = await txBuilder.build();
192
- const response = {
193
- txHex: JSON.stringify(transaction.toJson()),
194
- };
195
- if (transaction.toJson().signature.length >= 2) {
196
- return response;
197
- }
198
- // Half signed transaction
199
- return {
200
- halfSigned: response,
201
- };
202
- }
203
- /**
204
- * Return boolean indicating whether input is valid seed for the coin
205
- *
206
- * @param prv - the prv to be checked
207
- */
208
- isValidXprv(prv) {
209
- try {
210
- return !secp256k1_1.bip32.fromBase58(prv).isNeutered();
211
- }
212
- catch {
213
- return false;
214
- }
215
- }
216
- /**
217
- * Convert a message to string in hexadecimal format.
218
- *
219
- * @param message {Buffer|String} message to sign
220
- * @return the message as a hexadecimal string
221
- */
222
- toHexString(message) {
223
- if (typeof message === 'string') {
224
- return Buffer.from(message).toString('hex');
225
- }
226
- else if (Buffer.isBuffer(message)) {
227
- return message.toString('hex');
228
- }
229
- else {
230
- throw new Error('Invalid messaged passed to signMessage');
231
- }
232
- }
233
- /**
234
- * Sign message with private key
235
- *
236
- * @param key
237
- * @param message
238
- */
239
- async signMessage(key, message) {
240
- const toSign = this.toHexString(message);
241
- let prv = key.prv;
242
- if (this.isValidXprv(prv)) {
243
- prv = secp256k1_1.bip32.fromBase58(prv).privateKey?.toString('hex');
244
- }
245
- if (!prv) {
246
- throw new Error('no privateKey');
247
- }
248
- let sig = lib_1.Utils.signString(toSign, prv, true);
249
- // remove the preceding 0x
250
- sig = sig.replace(/^0x/, '');
251
- return Buffer.from(sig, 'hex');
252
- }
253
- /**
254
- * Converts an xpub to a uncompressed pub
255
- * @param xpub
256
- */
257
- xpubToUncompressedPub(xpub) {
258
- if (!this.isValidXpub(xpub)) {
259
- throw new Error('invalid xpub');
260
- }
261
- const publicKey = secp256k1_1.bip32.fromBase58(xpub).publicKey;
262
- return Buffer.from(secp256k1.publicKeyConvert(publicKey, false /* compressed */)).toString('hex');
263
- }
264
- /**
265
- * Modify prebuild before sending it to the server.
266
- * @param buildParams The whitelisted parameters for this prebuild
267
- */
268
- async getExtraPrebuildParams(buildParams) {
269
- if (buildParams.recipients[0].data && buildParams.feeLimit) {
270
- buildParams.recipients[0].feeLimit = buildParams.feeLimit;
271
- }
272
- }
273
- pubToHexAddress(pub) {
274
- const byteArrayAddr = lib_1.Utils.getByteArrayFromHexAddress(pub);
275
- const rawAddress = lib_1.Utils.getRawAddressFromPubKey(byteArrayAddr);
276
- return lib_1.Utils.getHexAddressFromByteArray(rawAddress);
277
- }
278
- xprvToCompressedPrv(xprv) {
279
- if (!this.isValidXprv(xprv)) {
280
- throw new Error('invalid xprv');
281
- }
282
- const hdNode = secp256k1_1.bip32.fromBase58(xprv);
283
- if (!hdNode.privateKey) {
284
- throw new Error('no privateKey');
285
- }
286
- return hdNode.privateKey.toString('hex');
287
- }
288
- getNodeUrl(node) {
289
- switch (node) {
290
- case NodeTypes.Full:
291
- return sdk_core_1.common.Environments[this.bitgo.getEnv()].tronNodes.full;
292
- case NodeTypes.Solidity:
293
- return sdk_core_1.common.Environments[this.bitgo.getEnv()].tronNodes.solidity;
294
- default:
295
- throw new Error('node type not found');
296
- }
297
- }
298
- /**
299
- * Make a query to Trongrid for information such as balance, token balance, solidity calls
300
- * @param query {Object} key-value pairs of parameters to append after /api
301
- * @returns {Object} response from Trongrid
302
- */
303
- async recoveryPost(query) {
304
- const nodeUri = this.getNodeUrl(query.node);
305
- const response = await request
306
- .post(nodeUri + query.path)
307
- .type('json')
308
- .send(query.jsonObj);
309
- if (!response.ok) {
310
- throw new Error('could not reach Tron node');
311
- }
312
- // unfortunately, it doesn't look like most TRON nodes return valid json as body
313
- return JSON.parse(response.text);
314
- }
315
- /**
316
- * Make a query to Trongrid for information such as balance, token balance, solidity calls
317
- * @param query {Object} key-value pairs of parameters to append after /api
318
- * @returns {Object} response from Trongrid
319
- */
320
- async recoveryGet(query) {
321
- const nodeUri = this.getNodeUrl(query.node);
322
- const response = await request
323
- .get(nodeUri + query.path)
324
- .type('json')
325
- .send(query.jsonObj);
326
- if (!response.ok) {
327
- throw new Error('could not reach Tron node');
328
- }
329
- // unfortunately, it doesn't look like most TRON nodes return valid json as body
330
- return JSON.parse(response.text);
331
- }
332
- /**
333
- * Query our explorer for the balance of an address
334
- * @param address {String} the address encoded in hex
335
- * @returns {BigNumber} address balance
336
- */
337
- async getAccountBalancesFromNode(address) {
338
- return await this.recoveryGet({
339
- path: '/v1/accounts/' + address,
340
- jsonObj: {},
341
- node: NodeTypes.Full,
342
- });
343
- }
344
- /**
345
- * Retrieves our build transaction from a node.
346
- * @param toAddr hex-encoded address
347
- * @param fromAddr hex-encoded address
348
- * @param amount
349
- */
350
- async getBuildTransaction(toAddr, fromAddr, amount) {
351
- // our addresses should be base58, we'll have to encode to hex
352
- return await this.recoveryPost({
353
- path: '/wallet/createtransaction',
354
- jsonObj: {
355
- to_address: toAddr,
356
- owner_address: fromAddr,
357
- amount,
358
- },
359
- node: NodeTypes.Full,
360
- });
361
- }
362
- /**
363
- * Retrieves our build transaction from a node.
364
- * @param toAddr hex-encoded address
365
- * @param fromAddr hex-encoded address
366
- * @param amount
367
- */
368
- async getTriggerSmartContractTransaction(toAddr, fromAddr, amount, contractAddr) {
369
- const functionSelector = 'transfer(address,uint256)';
370
- const types = ['address', 'uint256'];
371
- const values = [toAddr, amount];
372
- const parameter = lib_1.Utils.encodeDataParams(types, values, '');
373
- return await this.recoveryPost({
374
- path: '/wallet/triggersmartcontract',
375
- jsonObj: {
376
- owner_address: fromAddr,
377
- contract_address: contractAddr,
378
- function_selector: functionSelector,
379
- parameter: parameter,
380
- fee_limit: 100000000,
381
- },
382
- node: NodeTypes.Full,
383
- });
384
- }
385
- /**
386
- * Throws an error if any keys in the ownerKeys collection don't match the keys array we pass
387
- * @param ownerKeys
388
- * @param keys
389
- */
390
- checkPermissions(ownerKeys, keys) {
391
- keys = keys.map((k) => k.toUpperCase());
392
- ownerKeys.map((key) => {
393
- const hexKey = key.address.toUpperCase();
394
- if (!keys.includes(hexKey)) {
395
- throw new Error(`pub address ${hexKey} not found in account`);
396
- }
397
- if (key.weight !== 1) {
398
- throw new Error('owner permission is invalid for this structure');
399
- }
400
- });
401
- }
402
- /**
403
- * Format for offline vault signing
404
- * @param {BaseTransaction} tx
405
- * @param {number} fee
406
- * @param {number} recoveryAmount
407
- * @returns {RecoveryTransaction}
408
- */
409
- formatForOfflineVault(tx, fee, recoveryAmount, addressInfo) {
410
- const txJSON = tx.toJson();
411
- const format = {
412
- txHex: JSON.stringify(txJSON),
413
- recoveryAmount,
414
- feeInfo: {
415
- fee: `${fee}`,
416
- },
417
- tx: txJSON, // Leaving it as txJSON for backwards compatibility
418
- coin: this.getChain(),
419
- };
420
- return addressInfo ? { ...format, addressInfo } : format;
421
- }
422
- /**
423
- * Builds a funds recovery transaction without BitGo.
424
- * We need to do three queries during this:
425
- * 1) Node query - how much money is in the account
426
- * 2) Build transaction - build our transaction for the amount
427
- * 3) Send signed build - send our signed build to a public node
428
- *
429
- * Note 1: for base address recoveries, fund will be recovered to recovery destination if base address balance is
430
- * more than 2.1 TRX for native TRX recovery and 100 TRX for token recover. For receive addresses, fund will be
431
- * recovered to base address first then swept to base address(decided as the universal pattern in team meeting).
432
- *
433
- * Note 2: the function supports token sweep from base address.
434
- * TODO: support token sweep from receive address.
435
- *
436
- * @param params
437
- */
438
- async recover(params) {
439
- const isKrsRecovery = (0, sdk_core_1.getIsKrsRecovery)(params);
440
- const isUnsignedSweep = (0, sdk_core_1.getIsUnsignedSweep)(params);
441
- if (!this.isValidAddress(params.recoveryDestination)) {
442
- throw new Error('Invalid destination address!');
443
- }
444
- let startIdx = params.startingScanIndex;
445
- if ((0, lodash_1.isUndefined)(startIdx)) {
446
- startIdx = 1;
447
- }
448
- else if (!(0, lodash_1.isInteger)(startIdx) || startIdx < 0) {
449
- throw new Error('Invalid starting index to scan for addresses');
450
- }
451
- let numIteration = params.scan;
452
- if ((0, lodash_1.isUndefined)(numIteration)) {
453
- numIteration = 20;
454
- }
455
- else if (typeof numIteration === 'string') {
456
- numIteration = parseInt(numIteration, 10);
457
- }
458
- if (!(0, lodash_1.isInteger)(numIteration) || numIteration <= 0) {
459
- throw new Error('Invalid scanning factor');
460
- }
461
- // get our user, backup keys
462
- const keys = (0, sdk_core_1.getBip32Keys)(this.bitgo, params, { requireBitGoXpub: false });
463
- // we need to decode our bitgoKey to a base58 address
464
- const bitgoHexAddr = this.pubToHexAddress(this.xpubToUncompressedPub(params.bitgoKey));
465
- let recoveryFromAddrHex = bitgoHexAddr;
466
- let recoveryToAddressHex = lib_1.Utils.getHexAddressFromBase58Address(params.recoveryDestination);
467
- // call the node to get our account balance for base address
468
- let account = await this.getAccountBalancesFromNode(lib_1.Utils.getBase58AddressFromHex(recoveryFromAddrHex));
469
- let recoveryAmount = account.data[0].balance;
470
- let userXPrv = keys[0].toBase58();
471
- let isReceiveAddress = false;
472
- let addressInfo;
473
- const tokenContractAddr = params.tokenContractAddress;
474
- // check for possible token recovery, recover the token provide by user
475
- if (tokenContractAddr) {
476
- let rawTokenTxn;
477
- for (const token of account.data[0].trc20) {
478
- if (token[tokenContractAddr]) {
479
- const amount = token[tokenContractAddr];
480
- const tokenContractAddrHex = lib_1.Utils.getHexAddressFromBase58Address(tokenContractAddr);
481
- rawTokenTxn = (await this.getTriggerSmartContractTransaction(recoveryToAddressHex, recoveryFromAddrHex, amount, tokenContractAddrHex)).transaction;
482
- recoveryAmount = parseInt(amount, 10);
483
- break;
484
- }
485
- }
486
- // build and sign token txns
487
- if (rawTokenTxn) {
488
- // Check there is sufficient of the native asset to cover fees
489
- const trxBalance = account.data[0].balance;
490
- if (trxBalance < exports.SAFE_TRON_TOKEN_TRANSACTION_FEE) {
491
- throw new Error(`Amount of funds to recover ${trxBalance} is less than ${exports.SAFE_TRON_TOKEN_TRANSACTION_FEE} and wouldn't be able to fund a trc20 send`);
492
- }
493
- const txBuilder = (0, builder_1.getBuilder)(this.getChain()).from(rawTokenTxn);
494
- // Default expiry is 1 minute which is too short for recovery purposes
495
- // extend the expiry to 1 day
496
- txBuilder.extendValidTo(exports.RECOVER_TRANSACTION_EXPIRY);
497
- // this tx should be enough to drop into a node
498
- if (isUnsignedSweep) {
499
- return this.formatForOfflineVault(await txBuilder.build(), exports.SAFE_TRON_TOKEN_TRANSACTION_FEE, recoveryAmount);
500
- }
501
- const userPrv = this.xprvToCompressedPrv(userXPrv);
502
- txBuilder.sign({ key: userPrv });
503
- // krs recoveries don't get signed
504
- if (!isKrsRecovery && !isReceiveAddress) {
505
- const backupXPrv = keys[1].toBase58();
506
- const backupPrv = this.xprvToCompressedPrv(backupXPrv);
507
- txBuilder.sign({ key: backupPrv });
508
- }
509
- return this.formatForOfflineVault(await txBuilder.build(), exports.SAFE_TRON_TOKEN_TRANSACTION_FEE, recoveryAmount);
510
- }
511
- else {
512
- throw Error('Not found token to recover, please check token balance');
513
- }
514
- }
515
- // let us recover the native Tron
516
- if (recoveryAmount > exports.SAFE_TRON_TRANSACTION_FEE) {
517
- const userXPub = keys[0].neutered().toBase58();
518
- const backupXPub = keys[1].neutered().toBase58();
519
- // check multisig permissions
520
- const keyHexAddresses = [
521
- this.pubToHexAddress(this.xpubToUncompressedPub(userXPub)),
522
- this.pubToHexAddress(this.xpubToUncompressedPub(backupXPub)),
523
- bitgoHexAddr,
524
- ];
525
- // run checks to ensure this is a valid tx - permissions match our signer keys
526
- const ownerKeys = [];
527
- for (const key of account.data[0].owner_permission.keys) {
528
- const address = lib_1.Utils.getHexAddressFromBase58Address(key.address);
529
- const weight = key.weight;
530
- ownerKeys.push({ address, weight });
531
- }
532
- const activePermissionKeys = [];
533
- for (const key of account.data[0].active_permission[0].keys) {
534
- const address = lib_1.Utils.getHexAddressFromBase58Address(key.address);
535
- const weight = key.weight;
536
- activePermissionKeys.push({ address, weight });
537
- }
538
- this.checkPermissions(ownerKeys, keyHexAddresses);
539
- this.checkPermissions(activePermissionKeys, keyHexAddresses);
540
- }
541
- else {
542
- // Check receive addresses for funds
543
- // Check for first derived wallet with funds
544
- // Receive addresses are derived from the user key
545
- for (let i = startIdx; i < numIteration + startIdx; i++) {
546
- const derivationPath = `0/0/0/${i}`;
547
- const userKey = keys[0].derivePath(derivationPath);
548
- const xpub = userKey.neutered();
549
- const receiveAddress = this.pubToHexAddress(this.xpubToUncompressedPub(xpub.toBase58()));
550
- const address = lib_1.Utils.getBase58AddressFromHex(receiveAddress);
551
- // call the node to get our account balance
552
- const accountInfo = await this.getAccountBalancesFromNode(address);
553
- if (accountInfo.data[0] && accountInfo.data[0].balance > exports.SAFE_TRON_TRANSACTION_FEE) {
554
- account = accountInfo;
555
- recoveryAmount = accountInfo.data[0].balance;
556
- userXPrv = userKey.toBase58(); // assign derived userXPrx
557
- isReceiveAddress = true;
558
- recoveryFromAddrHex = receiveAddress;
559
- recoveryToAddressHex = bitgoHexAddr;
560
- addressInfo = {
561
- address,
562
- chain: 0,
563
- index: i,
564
- };
565
- break;
566
- }
567
- }
568
- }
569
- // a sweep potentially needs to pay for multi-sig transfer, destination account activation and bandwidth
570
- // TRON foundation recommends 2.1 TRX for guaranteed confirmation
571
- if (!recoveryAmount || exports.SAFE_TRON_TRANSACTION_FEE >= recoveryAmount) {
572
- throw new Error(`Amount of funds to recover ${recoveryAmount} is less than ${exports.SAFE_TRON_TRANSACTION_FEE} and wouldn't be able to fund a send`);
573
- }
574
- const recoveryAmountMinusFees = recoveryAmount - exports.SAFE_TRON_TRANSACTION_FEE;
575
- const buildTx = await this.getBuildTransaction(recoveryToAddressHex, recoveryFromAddrHex, recoveryAmountMinusFees);
576
- // construct our tx
577
- const txBuilder = (0, builder_1.getBuilder)(this.getChain()).from(buildTx);
578
- // Default expiry is 1 minute which is too short for recovery purposes
579
- // extend the expiry to 1 day
580
- txBuilder.extendValidTo(exports.RECOVER_TRANSACTION_EXPIRY);
581
- const tx = await txBuilder.build();
582
- // this tx should be enough to drop into a node
583
- if (isUnsignedSweep) {
584
- return this.formatForOfflineVault(tx, exports.SAFE_TRON_TRANSACTION_FEE, recoveryAmountMinusFees, addressInfo);
585
- }
586
- const userPrv = this.xprvToCompressedPrv(userXPrv);
587
- txBuilder.sign({ key: userPrv });
588
- // krs recoveries don't get signed
589
- if (!isKrsRecovery && !isReceiveAddress) {
590
- const backupXPrv = keys[1].toBase58();
591
- const backupPrv = this.xprvToCompressedPrv(backupXPrv);
592
- txBuilder.sign({ key: backupPrv });
593
- }
594
- const txSigned = await txBuilder.build();
595
- return this.formatForOfflineVault(txSigned, exports.SAFE_TRON_TRANSACTION_FEE, recoveryAmountMinusFees, addressInfo);
596
- }
597
- /**
598
- * Builds native TRX recoveries of receive addresses in batch without BitGo.
599
- * Funds will be recovered to base address first. You need to initiate another sweep txn after that.
600
- * Note: there will be another recoverTokenConsolidations function to support token recover from receive addresses.
601
- *
602
- * @param {ConsolidationRecoveryOptions} params - options for consolidation recovery.
603
- * @param {string} [params.startingScanIndex] - receive address index to start scanning from. default to 1 (inclusive).
604
- * @param {string} [params.endingScanIndex] - receive address index to end scanning at. default to startingScanIndex + 20 (exclusive).
605
- */
606
- async recoverConsolidations(params) {
607
- const isUnsignedConsolidations = (0, sdk_core_1.getIsUnsignedSweep)(params);
608
- const startIdx = params.startingScanIndex || 1;
609
- const endIdx = params.endingScanIndex || startIdx + exports.DEFAULT_SCAN_FACTOR;
610
- if (startIdx < 1 || endIdx <= startIdx || endIdx - startIdx > 10 * exports.DEFAULT_SCAN_FACTOR) {
611
- throw new Error(`Invalid starting or ending index to scan for addresses. startingScanIndex: ${startIdx}, endingScanIndex: ${endIdx}.`);
612
- }
613
- const keys = (0, sdk_core_1.getBip32Keys)(this.bitgo, params, { requireBitGoXpub: false });
614
- const baseAddrHex = this.pubToHexAddress(this.xpubToUncompressedPub(params.bitgoKey));
615
- const txnsBatch = [];
616
- for (let i = startIdx; i < endIdx; i++) {
617
- const derivationPath = `0/0/0/${i}`;
618
- const userKey = keys[0].derivePath(derivationPath);
619
- const userKeyXPub = userKey.neutered();
620
- const receiveAddressHex = this.pubToHexAddress(this.xpubToUncompressedPub(userKeyXPub.toBase58()));
621
- const receiveAddress = lib_1.Utils.getBase58AddressFromHex(receiveAddressHex);
622
- // call the node to get our account balance
623
- const accountInfo = await this.getAccountBalancesFromNode(receiveAddress);
624
- if (accountInfo.data[0] && accountInfo.data[0].balance > exports.SAFE_TRON_TRANSACTION_FEE) {
625
- let recoveryAmount = 0;
626
- // Tokens must be consolidate before the native asset. First construct token txns
627
- let rawTokenTxn;
628
- // check for possible token recovery, recover the token provide by user
629
- if (params.tokenContractAddress) {
630
- if (accountInfo.data[0].balance > exports.SAFE_TRON_TOKEN_TRANSACTION_FEE && accountInfo.data[0].trc20[0]) {
631
- const tokenDataArray = accountInfo.data[0].trc20;
632
- for (const tokenData of tokenDataArray) {
633
- const contractAddress = Object.keys(tokenData);
634
- if (params.tokenContractAddress === contractAddress[0]) {
635
- const amount = tokenData[contractAddress[0]];
636
- const tokenContractAddrHex = lib_1.Utils.getHexAddressFromBase58Address(contractAddress[0]);
637
- rawTokenTxn = (await this.getTriggerSmartContractTransaction(baseAddrHex, receiveAddressHex, amount, tokenContractAddrHex)).transaction;
638
- recoveryAmount = parseInt(amount, 10);
639
- break;
640
- }
641
- }
642
- }
643
- // build and sign token txns
644
- if (rawTokenTxn) {
645
- const addressInfo = {
646
- address: receiveAddress,
647
- chain: 0,
648
- index: i,
649
- };
650
- const txBuilder = (0, builder_1.getBuilder)(this.getChain()).from(rawTokenTxn);
651
- // Default expiry is 1 minute which is too short for recovery purposes
652
- // extend the expiry to 1 day
653
- txBuilder.extendValidTo(exports.RECOVER_TRANSACTION_EXPIRY);
654
- // this tx should be enough to drop into a node
655
- if (!isUnsignedConsolidations) {
656
- const userPrv = this.xprvToCompressedPrv(userKey.toBase58());
657
- // receive address only needs to be signed by user key
658
- txBuilder.sign({ key: userPrv });
659
- }
660
- const tx = await txBuilder.build();
661
- txnsBatch.push(this.formatForOfflineVault(tx, exports.SAFE_TRON_TOKEN_TRANSACTION_FEE, recoveryAmount, addressInfo));
662
- }
663
- }
664
- else {
665
- const addressBalance = accountInfo.data[0].balance;
666
- const addressInfo = {
667
- address: receiveAddress,
668
- chain: 0,
669
- index: i,
670
- };
671
- const recoveryAmount = addressBalance - exports.SAFE_TRON_TRANSACTION_FEE;
672
- const buildTx = await this.getBuildTransaction(baseAddrHex, receiveAddressHex, recoveryAmount);
673
- // construct our tx
674
- const txBuilder = (0, builder_1.getBuilder)(this.getChain()).from(buildTx);
675
- // Default expiry is 1 minute which is too short for recovery purposes
676
- // extend the expiry to 1 day
677
- txBuilder.extendValidTo(exports.RECOVER_TRANSACTION_EXPIRY);
678
- if (!isUnsignedConsolidations) {
679
- const userPrv = this.xprvToCompressedPrv(userKey.toBase58());
680
- // receive address only needs to be signed by user key
681
- txBuilder.sign({ key: userPrv });
682
- }
683
- const tx = await txBuilder.build();
684
- txnsBatch.push(this.formatForOfflineVault(tx, exports.SAFE_TRON_TRANSACTION_FEE, recoveryAmount, addressInfo));
685
- }
686
- }
687
- }
688
- return {
689
- transactions: txnsBatch,
690
- };
691
- }
692
- /**
693
- * Explain a Tron transaction from txHex
694
- * @param params
695
- */
696
- async explainTransaction(params) {
697
- const txHex = params.txHex || (params.halfSigned && params.halfSigned.txHex);
698
- if (!txHex || !params.feeInfo) {
699
- throw new Error('missing explain tx parameters');
700
- }
701
- const txBuilder = (0, builder_1.getBuilder)(this.getChain()).from(txHex);
702
- const tx = await txBuilder.build();
703
- const outputs = [
704
- {
705
- amount: tx.outputs[0].value.toString(),
706
- address: tx.outputs[0].address, // Should turn it into a readable format, aka base58
707
- },
708
- ];
709
- const displayOrder = [
710
- 'id',
711
- 'outputAmount',
712
- 'changeAmount',
713
- 'outputs',
714
- 'changeOutputs',
715
- 'fee',
716
- 'timestamp',
717
- 'expiration',
718
- ];
719
- return {
720
- displayOrder,
721
- id: tx.id,
722
- outputs,
723
- outputAmount: outputs[0].amount,
724
- changeOutputs: [], // account based does not use change outputs
725
- changeAmount: '0', // account base does not make change
726
- fee: params.feeInfo,
727
- timestamp: tx.validFrom,
728
- expiration: tx.validTo,
729
- };
730
- }
731
- /** @inheritDoc */
732
- auditDecryptedKey(params) {
733
- throw new sdk_core_1.MethodNotImplementedError();
734
- }
735
- }
736
- exports.Trx = Trx;
737
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJ4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RyeC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7R0FFRztBQUNILHFEQUF1QztBQUN2QyxtQ0FBcUM7QUFFckMscURBQThDO0FBQzlDLG9EQUFzQztBQUN0QyxtREF1QjhCO0FBQzlCLCtCQUF5RDtBQUN6RCwyQ0FBMkM7QUFFM0MsbUNBQWdEO0FBRW5DLFFBQUEsaUNBQWlDLEdBQUcsR0FBRyxDQUFDO0FBQ3hDLFFBQUEseUJBQXlCLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLHdFQUF3RTtBQUMvRyxRQUFBLCtCQUErQixHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQyx3RUFBd0U7QUFDckgsUUFBQSwwQkFBMEIsR0FBRyxRQUFRLENBQUMsQ0FBQyxVQUFVO0FBQ2pELFFBQUEsbUJBQW1CLEdBQUcsRUFBRSxDQUFDLENBQUMsd0RBQXdEO0FBOEUvRixJQUFZLFNBR1g7QUFIRCxXQUFZLFNBQVM7SUFDbkIseUNBQUksQ0FBQTtJQUNKLGlEQUFRLENBQUE7QUFDVixDQUFDLEVBSFcsU0FBUyx5QkFBVCxTQUFTLFFBR3BCO0FBU0QsTUFBYSxHQUFJLFNBQVEsbUJBQVE7SUFHL0IsWUFBWSxLQUFnQixFQUFFLFdBQXVDO1FBQ25FLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUViLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDeEUsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUFDO0lBQ2xDLENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQsU0FBUztRQUNQLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxN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QUs7WUFDTCxXQUFXO1lBQ1gsWUFBWTtTQUNiLENBQUM7UUFFRixPQUFPO1lBQ0wsWUFBWTtZQUNaLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRTtZQUNULE9BQU87WUFDUCxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07WUFDL0IsYUFBYSxFQUFFLEVBQUUsRUFBRSw0Q0FBNEM7WUFDL0QsWUFBWSxFQUFFLEdBQUcsRUFBRSxvQ0FBb0M7WUFDdkQsR0FBRyxFQUFFLE1BQU0sQ0FBQyxPQUFPO1lBQ25CLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUztZQUN2QixVQUFVLEVBQUUsRUFBRSxDQUFDLE9BQU87U0FDdkIsQ0FBQztJQUNKLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsaUJBQWlCLENBQUMsTUFBK0I7UUFDL0MsTUFBTSxJQUFJLG9DQUF5QixFQUFFLENBQUM7SUFDeEMsQ0FBQztDQUNGO0FBMXhCRCxrQkEweEJDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0ICogYXMgc2VjcDI1NmsxIGZyb20gJ3NlY3AyNTZrMSc7XG5pbXBvcnQgeyByYW5kb21CeXRlcyB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBDb2luRmFtaWx5LCBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4gfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvLWJldGEvc2VjcDI1NmsxJztcbmltcG9ydCAqIGFzIHJlcXVlc3QgZnJvbSAnc3VwZXJhZ2VudCc7XG5pbXBvcnQge1xuICBCYXNlQ29pbixcbiAgQml0R29CYXNlLFxuICBjb21tb24sXG4gIGdldEJpcDMyS2V5cyxcbiAgZ2V0SXNLcnNSZWNvdmVyeSxcbiAgZ2V0SXNVbnNpZ25lZFN3ZWVwLFxuICBLZXlQYWlyLFxuICBNZXRob2ROb3RJbXBsZW1lbnRlZEVycm9yLFxuICBQYXJzZWRUcmFuc2FjdGlvbixcbiAgUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFNpZ25lZFRyYW5zYWN0aW9uLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLFxuICBUcmFuc2FjdGlvbkZlZSxcbiAgVHJhbnNhY3Rpb25QcmVidWlsZCBhcyBCYXNlVHJhbnNhY3Rpb25QcmVidWlsZCxcbiAgVHJhbnNhY3Rpb25SZWNpcGllbnQgYXMgUmVjaXBpZW50LFxuICBWZXJpZnlBZGRyZXNzT3B0aW9ucyxcbiAgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zLFxuICBCYXNlVHJhbnNhY3Rpb24sXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IEludGVyZmFjZSwgVXRpbHMsIFdyYXBwZWRCdWlsZGVyIH0gZnJvbSAnLi9saWInO1xuaW1wb3J0IHsgZ2V0QnVpbGRlciB9IGZyb20gJy4vbGliL2J1aWxkZXInO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25SZWNlaXB0IH0gZnJvbSAnLi9saWIvaWZhY2UnO1xuaW1wb3J0IHsgaXNJbnRlZ2VyLCBpc1VuZGVmaW5lZCB9IGZyb20gJ2xvZGFzaCc7XG5cbmV4cG9ydCBjb25zdCBNSU5JTVVNX1RST05fTVNJR19UUkFOU0FDVElPTl9GRUUgPSAxZTY7XG5leHBvcnQgY29uc3QgU0FGRV9UUk9OX1RSQU5TQUNUSU9OX0ZFRSA9IDIuMSAqIDFlNjsgLy8gVFJPTiBmb3VuZGF0aW9uIHJlY29tbWVuZHMgMi4xIFRSWCBhcyBmZWVzIGZvciBndWFyYW50ZWVkIHRyYW5zYWN0aW9uXG5leHBvcnQgY29uc3QgU0FGRV9UUk9OX1RPS0VOX1RSQU5TQUNUSU9OX0ZFRSA9IDEwMCAqIDFlNjsgLy8gVFJPTiBmb3VuZGF0aW9uIHJlY29tbWVuZHMgMTAwIFRSWCBhcyBmZWVzIGZvciBndWFyYW50ZWVkIHRyYW5zYWN0aW9uXG5leHBvcnQgY29uc3QgUkVDT1ZFUl9UUkFOU0FDVElPTl9FWFBJUlkgPSA4NjQwMDAwMDsgLy8gMjQgaG91clxuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0NBTl9GQUNUT1IgPSAyMDsgLy8gZGVmYXVsdCBudW1iZXIgb2YgcmVjZWl2ZSBhZGRyZXNzZXMgdG8gc2NhbiBmb3IgZnVuZHNcblxuZXhwb3J0IGludGVyZmFjZSBUcm9uU2lnblRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eFByZWJ1aWxkOiBUcmFuc2FjdGlvblByZWJ1aWxkO1xuICBwcnY6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUeEluZm8ge1xuICByZWNpcGllbnRzOiBSZWNpcGllbnRbXTtcbiAgZnJvbTogc3RyaW5nO1xuICB0eGlkOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQWRkcmVzc0luZm8ge1xuICBhZGRyZXNzOiBzdHJpbmc7XG4gIGNoYWluOiBudW1iZXI7XG4gIGluZGV4OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJvblRyYW5zYWN0aW9uRXhwbGFuYXRpb24gZXh0ZW5kcyBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgZXhwaXJhdGlvbjogbnVtYmVyO1xuICB0aW1lc3RhbXA6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2FjdGlvblByZWJ1aWxkIGV4dGVuZHMgQmFzZVRyYW5zYWN0aW9uUHJlYnVpbGQge1xuICB0eEhleDogc3RyaW5nO1xuICB0eEluZm86IFR4SW5mbztcbiAgYWRkcmVzc0luZm8/OiBBZGRyZXNzSW5mbztcbiAgZmVlSW5mbzogVHJhbnNhY3Rpb25GZWU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyB7XG4gIHR4SGV4Pzogc3RyaW5nOyAvLyB0eEhleCBpcyBwb29ybHkgbmFtZWQgaGVyZTsgaXQgaXMganVzdCBhIHdyYXBwZWQgSlNPTiBvYmplY3RcbiAgaGFsZlNpZ25lZD86IHtcbiAgICB0eEhleDogc3RyaW5nOyAvLyB0eEhleCBpcyBwb29ybHkgbmFtZWQgaGVyZTsgaXQgaXMganVzdCBhIHdyYXBwZWQgSlNPTiBvYmplY3RcbiAgfTtcbiAgZmVlSW5mbzogVHJhbnNhY3Rpb25GZWU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVjb3ZlcnlPcHRpb25zIHtcbiAgdXNlcktleTogc3RyaW5nOyAvLyBCb3ggQVxuICBiYWNrdXBLZXk6IHN0cmluZzsgLy8gQm94IEJcbiAgYml0Z29LZXk6IHN0cmluZzsgLy8gQm94IEMgLSB0aGlzIGlzIGJpdGdvJ3MgeHB1YiBhbmQgd2lsbCBiZSB1c2VkIHRvIGRlcml2ZSB0aGVpciByb290IGFkZHJlc3NcbiAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogc3RyaW5nOyAvLyBiYXNlNTggYWRkcmVzc1xuICBrcnNQcm92aWRlcj86IHN0cmluZztcbiAgdG9rZW5Db250cmFjdEFkZHJlc3M/OiBzdHJpbmc7XG4gIHdhbGxldFBhc3NwaHJhc2U/OiBzdHJpbmc7XG4gIHN0YXJ0aW5nU2NhbkluZGV4PzogbnVtYmVyO1xuICBzY2FuPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnNvbGlkYXRpb25SZWNvdmVyeU9wdGlvbnMge1xuICB1c2VyS2V5OiBzdHJpbmc7XG4gIGJhY2t1cEtleTogc3RyaW5nO1xuICBiaXRnb0tleTogc3RyaW5nO1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzcz86IHN0cmluZztcbiAgc3RhcnRpbmdTY2FuSW5kZXg/OiBudW1iZXI7IC8vIGRlZmF1bHQgdG8gMSAoaW5jbHVzaXZlKVxuICBlbmRpbmdTY2FuSW5kZXg/OiBudW1iZXI7IC8vIGRlZmF1bHQgdG8gc3RhcnRpbmdTY2FuSW5kZXggKyAyMCAoZXhjbHVzaXZlKVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnNvbGlkYXRpb25SZWNvdmVyeUJhdGNoIHtcbiAgdHJhbnNhY3Rpb25zOiBSZWNvdmVyeVRyYW5zYWN0aW9uW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmVlSW5mbyB7XG4gIGZlZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY292ZXJ5VHJhbnNhY3Rpb24ge1xuICB0eEhleD86IHN0cmluZztcbiAgZmVlSW5mbz86IEZlZUluZm87XG4gIGNvaW4/OiBzdHJpbmc7XG4gIHR4PzogVHJhbnNhY3Rpb25QcmVidWlsZDtcbiAgcmVjb3ZlcnlBbW91bnQ/OiBudW1iZXI7XG4gIHRva2VuVHhzPzogVHJhbnNhY3Rpb25SZWNlaXB0W107XG4gIGFkZHJlc3NJbmZvPzogQWRkcmVzc0luZm87XG59XG5cbmV4cG9ydCBlbnVtIE5vZGVUeXBlcyB7XG4gIEZ1bGwsXG4gIFNvbGlkaXR5LFxufVxuXG4vKipcbiAqIFRoaXMgc3RydWN0dXJlIGlzIG5vdCBhIGNvbXBsZXRlIG1vZGVsIG9mIHRoZSBBY2NvdW50UmVzcG9uc2UgZnJvbSBhIG5vZGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWNjb3VudFJlc3BvbnNlIHtcbiAgZGF0YTogW0ludGVyZmFjZS5BY2NvdW50SW5mb107XG59XG5cbmV4cG9ydCBjbGFzcyBUcnggZXh0ZW5kcyBCYXNlQ29pbiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBfc3RhdGljc0NvaW46IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj47XG5cbiAgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBnZXRDaGFpbigpIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4ubmFtZTtcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBDb2luRmFtaWx5IHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZmFtaWx5O1xuICB9XG5cbiAgZ2V0RnVsbE5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRpY3NDb2luLmZ1bGxOYW1lO1xuICB9XG5cbiAgZ2V0QmFzZUZhY3RvcigpIHtcbiAgICByZXR1cm4gTWF0aC5wb3coMTAsIHRoaXMuX3N0YXRpY3NDb2luLmRlY2ltYWxQbGFjZXMpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHRyYW5zYWN0aW9uRGF0YUFsbG93ZWQoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogaW5oZXJpdGVkIGRvYyAqL1xuICBnZXREZWZhdWx0TXVsdGlzaWdUeXBlKCk6IE11bHRpc2lnVHlwZSB7XG4gICAgcmV0dXJuIG11bHRpc2lnVHlwZXMub25jaGFpbjtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVJbnN0YW5jZShiaXRnbzogQml0R29CYXNlLCBzdGF0aWNzQ29pbj86IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj4pOiBCYXNlQ29pbiB7XG4gICAgcmV0dXJuIG5ldyBUcngoYml0Z28sIHN0YXRpY3NDb2luKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFnIGZvciBzZW5kaW5nIHZhbHVlIG9mIDBcbiAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgb2theSB0byBzZW5kIDAgdmFsdWUsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgdmFsdWVsZXNzVHJhbnNmZXJBbGxvd2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGFsbG93c0FjY291bnRDb25zb2xpZGF0aW9ucygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhpcyBpcyBhIHZhbGlkIGJhc2U1OFxuICAgKiBAcGFyYW0gYWRkcmVzc1xuICAgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKCFhZGRyZXNzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIFV0aWxzLmlzQmFzZTU4QWRkcmVzcyhhZGRyZXNzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhpcyBpcyBhIHZhbGlkIGhleCBhZGRyZXNzXG4gICAqIEBwYXJhbSBhZGRyZXNzIGhleCBhZGRyZXNzXG4gICAqL1xuICBpc1ZhbGlkSGV4QWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gL140MVswLTlhLWZdezQwfSQvaS50ZXN0KGFkZHJlc3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGVkMjU1MTkga2V5IHBhaXJcbiAgICpcbiAgICogQHBhcmFtIHNlZWRcbiAgICogQHJldHVybnMge09iamVjdH0gb2JqZWN0IHdpdGggZ2VuZXJhdGVkIHB1YiwgcHJ2XG4gICAqL1xuICBnZW5lcmF0ZUtleVBhaXIoc2VlZD86IEJ1ZmZlcik6IEtleVBhaXIge1xuICAgIC8vIFRPRE86IG1vdmUgdGhpcyBhbmQgYWRkcmVzcyBjcmVhdGlvbiBsb2dpYyB0byBhY2NvdW50LWxpYlxuICAgIGlmICghc2VlZCkge1xuICAgICAgLy8gQW4gZXh0ZW5kZWQgcHJpdmF0ZSBrZXkgaGFzIGJvdGggYSBub3JtYWwgMjU2IGJpdCBwcml2YXRlIGtleSBhbmQgYSAyNTYgYml0IGNoYWluIGNvZGUsIGJvdGggb2Ygd2hpY2ggbXVzdCBiZVxuICAgICAgLy8gcmFuZG9tLiA1MTIgYml0cyBpcyB0aGVyZWZvcmUgdGhlIG1heGltdW0gZW50cm9weSBhbmQgZ2l2ZXMgdXMgbWF4aW11bSBzZWN1cml0eSBhZ2FpbnN0IGNyYWNraW5nLlxuICAgICAgc2VlZCA9IHJhbmRvbUJ5dGVzKDUxMiAvIDgpO1xuICAgIH1cbiAgICBjb25zdCBoZCA9IGJpcDMyLmZyb21TZWVkKHNlZWQpO1xuICAgIHJldHVybiB7XG4gICAgICBwdWI6IGhkLm5ldXRlcmVkKCkudG9CYXNlNTgoKSxcbiAgICAgIHBydjogaGQudG9CYXNlNTgoKSxcbiAgICB9O1xuICB9XG5cbiAgaXNWYWxpZFhwdWIoeHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBiaXAzMi5mcm9tQmFzZTU4KHhwdWIpLmlzTmV1dGVyZWQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgaXNWYWxpZFB1YihwdWI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlzVmFsaWRYcHViKHB1YikpIHtcbiAgICAgIC8vIHhwdWJzIGNhbiBiZSBjb252ZXJ0ZWQgaW50byByZWd1bGFyIHB1YnMsIHNvIHRlY2huaWNhbGx5IGl0IGlzIGEgdmFsaWQgcHViXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoJ14wNFthLXpBLVowLTldezEyOH0kJykudGVzdChwdWIpO1xuICB9XG5cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIGFzeW5jIGlzV2FsbGV0QWRkcmVzcyhwYXJhbXM6IFZlcmlmeUFkZHJlc3NPcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdGhyb3cgbmV3IE1ldGhvZE5vdEltcGxlbWVudGVkRXJyb3IoKTtcbiAgfVxuXG4gIGFzeW5jIHZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtczogVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRGVyaXZlIGEgdXNlciBrZXkgdXNpbmcgdGhlIGNoYWluIHBhdGggb2YgdGhlIGFkZHJlc3NcbiAgICogQHBhcmFtIGtleVxuICAgKiBAcGFyYW0gcGF0aFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBkZXJpdmVkIHByaXZhdGUga2V5XG4gICAqL1xuICBkZXJpdmVLZXlXaXRoUGF0aCh7IGtleSwgcGF0aCB9OiB7IGtleTogc3RyaW5nOyBwYXRoOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gICAgY29uc3Qga2V5Y2hhaW4gPSBiaXAzMi5mcm9tQmFzZTU4KGtleSk7XG4gICAgY29uc3QgZGVyaXZlZEtleU5vZGUgPSBrZXljaGFpbi5kZXJpdmVQYXRoKHBhdGgpO1xuICAgIHJldHVybiBkZXJpdmVkS2V5Tm9kZS50b0Jhc2U1OCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2VtYmxlIGtleWNoYWluIGFuZCBoYWxmLXNpZ24gcHJlYnVpbHQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcGFyYW0gcGFyYW1zLnR4UHJlYnVpbGQge09iamVjdH0gcHJlYnVpbGQgb2JqZWN0IHJldHVybmVkIGJ5IHBsYXRmb3JtXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2IHtTdHJpbmd9IHVzZXIgcHJ2XG4gICAqIEByZXR1cm5zIEJsdWViaXJkPFNpZ25lZFRyYW5zYWN0aW9uPlxuICAgKi9cbiAgYXN5bmMgc2lnblRyYW5zYWN0aW9uKHBhcmFtczogVHJvblNpZ25UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPiB7XG4gICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcih0aGlzLmdldENoYWluKCkpLmZyb20ocGFyYW1zLnR4UHJlYnVpbGQudHhIZXgpO1xuXG4gICAgbGV0IGtleTtcbiAgICBjb25zdCB7IGNoYWluLCBpbmRleCB9ID0gcGFyYW1zLnR4UHJlYnVpbGQ/LmFkZHJlc3NJbmZvID8/IHsgY2hhaW46IDAsIGluZGV4OiAwIH07XG4gICAgaWYgKGNoYWluID09PSAwICYmIGluZGV4ID09PSAwKSB7XG4gICAgICBrZXkgPSBwYXJhbXMucHJ2O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9IGAwLzAvJHtjaGFpbn0vJHtpbmRleH1gO1xuICAgICAga2V5ID0gdGhpcy5kZXJpdmVLZXlXaXRoUGF0aCh7IGtleTogcGFyYW1zLnBydiwgcGF0aDogZGVyaXZhdGlvblBhdGggfSk7XG4gICAgfVxuICAgIHR4QnVpbGRlci5zaWduKHsga2V5IH0pO1xuXG4gICAgY29uc3QgdHJhbnNhY3Rpb24gPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICBjb25zdCByZXNwb25zZSA9IHtcbiAgICAgIHR4SGV4OiBKU09OLnN0cmluZ2lmeSh0cmFuc2FjdGlvbi50b0pzb24oKSksXG4gICAgfTtcbiAgICBpZiAodHJhbnNhY3Rpb24udG9Kc29uKCkuc2lnbmF0dXJlLmxlbmd0aCA+PSAyKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfVxuICAgIC8vIEhhbGYgc2lnbmVkIHRyYW5zYWN0aW9uXG4gICAgcmV0dXJuIHtcbiAgICAgIGhhbGZTaWduZWQ6IHJlc3BvbnNlLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIGlucHV0IGlzIHZhbGlkIHNlZWQgZm9yIHRoZSBjb2luXG4gICAqXG4gICAqIEBwYXJhbSBwcnYgLSB0aGUgcHJ2IHRvIGJlIGNoZWNrZWRcbiAgICovXG4gIGlzVmFsaWRYcHJ2KHBydjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAhYmlwMzIuZnJvbUJhc2U1OChwcnYpLmlzTmV1dGVyZWQoKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBhIG1lc3NhZ2UgdG8gc3RyaW5nIGluIGhleGFkZWNpbWFsIGZvcm1hdC5cbiAgICpcbiAgICogQHBhcmFtIG1lc3NhZ2Uge0J1ZmZlcnxTdHJpbmd9IG1lc3NhZ2UgdG8gc2lnblxuICAgKiBAcmV0dXJuIHRoZSBtZXNzYWdlIGFzIGEgaGV4YWRlY2ltYWwgc3RyaW5nXG4gICAqL1xuICB0b0hleFN0cmluZyhtZXNzYWdlOiBzdHJpbmcgfCBCdWZmZXIpOiBzdHJpbmcge1xuICAgIGlmICh0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBCdWZmZXIuZnJvbShtZXNzYWdlKS50b1N0cmluZygnaGV4Jyk7XG4gICAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIobWVzc2FnZSkpIHtcbiAgICAgIHJldHVybiBtZXNzYWdlLnRvU3RyaW5nKCdoZXgnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1lc3NhZ2VkIHBhc3NlZCB0byBzaWduTWVzc2FnZScpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIG1lc3NhZ2Ugd2l0aCBwcml2YXRlIGtleVxuICAgKlxuICAgKiBAcGFyYW0ga2V5XG4gICAqIEBwYXJhbSBtZXNzYWdlXG4gICAqL1xuICBhc3luYyBzaWduTWVzc2FnZShrZXk6IEtleVBhaXIsIG1lc3NhZ2U6IHN0cmluZyB8IEJ1ZmZlcik6IFByb21pc2U8QnVmZmVyPiB7XG4gICAgY29uc3QgdG9TaWduID0gdGhpcy50b0hleFN0cmluZyhtZXNzYWdlKTtcblxuICAgIGxldCBwcnY6IHN0cmluZyB8IHVuZGVmaW5lZCA9IGtleS5wcnY7XG4gICAgaWYgKHRoaXMuaXNWYWxpZFhwcnYocHJ2KSkge1xuICAgICAgcHJ2ID0gYmlwMzIuZnJvbUJhc2U1OChwcnYpLnByaXZhdGVLZXk/LnRvU3RyaW5nKCdoZXgnKTtcbiAgICB9XG5cbiAgICBpZiAoIXBydikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlS2V5Jyk7XG4gICAgfVxuICAgIGxldCBzaWcgPSBVdGlscy5zaWduU3RyaW5nKHRvU2lnbiwgcHJ2LCB0cnVlKTtcblxuICAgIC8vIHJlbW92ZSB0aGUgcHJlY2VkaW5nIDB4XG4gICAgc2lnID0gc2lnLnJlcGxhY2UoL14weC8sICcnKTtcblxuICAgIHJldHVybiBCdWZmZXIuZnJvbShzaWcsICdoZXgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhbiB4cHViIHRvIGEgdW5jb21wcmVzc2VkIHB1YlxuICAgKiBAcGFyYW0geHB1YlxuICAgKi9cbiAgeHB1YlRvVW5jb21wcmVzc2VkUHViKHhwdWI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRYcHViKHhwdWIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgeHB1YicpO1xuICAgIH1cblxuICAgIGNvbnN0IHB1YmxpY0tleSA9IGJpcDMyLmZyb21CYXNlNTgoeHB1YikucHVibGljS2V5O1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShzZWNwMjU2azEucHVibGljS2V5Q29udmVydChwdWJsaWNLZXksIGZhbHNlIC8qIGNvbXByZXNzZWQgKi8pKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogTW9kaWZ5IHByZWJ1aWxkIGJlZm9yZSBzZW5kaW5nIGl0IHRvIHRoZSBzZXJ2ZXIuXG4gICAqIEBwYXJhbSBidWlsZFBhcmFtcyBUaGUgd2hpdGVsaXN0ZWQgcGFyYW1ldGVycyBmb3IgdGhpcyBwcmVidWlsZFxuICAgKi9cbiAgYXN5bmMgZ2V0RXh0cmFQcmVidWlsZFBhcmFtcyhidWlsZFBhcmFtczogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICBpZiAoYnVpbGRQYXJhbXMucmVjaXBpZW50c1swXS5kYXRhICYmIGJ1aWxkUGFyYW1zLmZlZUxpbWl0KSB7XG4gICAgICBidWlsZFBhcmFtcy5yZWNpcGllbnRzWzBdLmZlZUxpbWl0ID0gYnVpbGRQYXJhbXMuZmVlTGltaXQ7XG4gICAgfVxuICB9XG5cbiAgcHViVG9IZXhBZGRyZXNzKHB1Yjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBieXRlQXJyYXlBZGRyID0gVXRpbHMuZ2V0Qnl0ZUFycmF5RnJvbUhleEFkZHJlc3MocHViKTtcbiAgICBjb25zdCByYXdBZGRyZXNzID0gVXRpbHMuZ2V0UmF3QWRkcmVzc0Zyb21QdWJLZXkoYnl0ZUFycmF5QWRkcik7XG4gICAgcmV0dXJuIFV0aWxzLmdldEhleEFkZHJlc3NGcm9tQnl0ZUFycmF5KHJhd0FkZHJlc3MpO1xuICB9XG5cbiAgeHBydlRvQ29tcHJlc3NlZFBydih4cHJ2OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkWHBydih4cHJ2KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHhwcnYnKTtcbiAgICB9XG5cbiAgICBjb25zdCBoZE5vZGUgPSBiaXAzMi5mcm9tQmFzZTU4KHhwcnYpO1xuICAgIGlmICghaGROb2RlLnByaXZhdGVLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbm8gcHJpdmF0ZUtleScpO1xuICAgIH1cbiAgICByZXR1cm4gaGROb2RlLnByaXZhdGVLZXkudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXROb2RlVXJsKG5vZGU6IE5vZGVUeXBlcyk6IHN0cmluZyB7XG4gICAgc3dpdGNoIChub2RlKSB7XG4gICAgICBjYXNlIE5vZGVUeXBlcy5GdWxsOlxuICAgICAgICByZXR1cm4gY29tbW9uLkVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS50cm9uTm9kZXMuZnVsbDtcbiAgICAgIGNhc2UgTm9kZVR5cGVzLlNvbGlkaXR5OlxuICAgICAgICByZXR1cm4gY29tbW9uLkVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS50cm9uTm9kZXMuc29saWRpdHk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vZGUgdHlwZSBub3QgZm91bmQnKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIE1ha2UgYSBxdWVyeSB0byBUcm9uZ3JpZCBmb3IgaW5mb3JtYXRpb24gc3VjaCBhcyBiYWxhbmNlLCB0b2tlbiBiYWxhbmNlLCBzb2xpZGl0eSBjYWxsc1xuICAgKiBAcGFyYW0gcXVlcnkge09iamVjdH0ga2V5LXZhbHVlIHBhaXJzIG9mIHBhcmFtZXRlcnMgdG8gYXBwZW5kIGFmdGVyIC9hcGlcbiAgICogQHJldHVybnMge09iamVjdH0gcmVzcG9uc2UgZnJvbSBUcm9uZ3JpZFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZWNvdmVyeVBvc3QocXVlcnk6IHsgcGF0aDogc3RyaW5nOyBqc29uT2JqOiBhbnk7IG5vZGU6IE5vZGVUeXBlcyB9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBub2RlVXJpID0gdGhpcy5nZXROb2RlVXJsKHF1ZXJ5Lm5vZGUpO1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0XG4gICAgICAucG9zdChub2RlVXJpICsgcXVlcnkucGF0aClcbiAgICAgIC50eXBlKCdqc29uJylcbiAgICAgIC5zZW5kKHF1ZXJ5Lmpzb25PYmopO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgcmVhY2ggVHJvbiBub2RlJyk7XG4gICAgfVxuXG4gICAgLy8gdW5mb3J0dW5hdGVseSwgaXQgZG9lc24ndCBsb29rIGxpa2UgbW9zdCBUUk9OIG5vZGVzIHJldHVybiB2YWxpZCBqc29uIGFzIGJvZHlcbiAgICByZXR1cm4gSlNPTi5wYXJzZShyZXNwb25zZS50ZXh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlIGEgcXVlcnkgdG8gVHJvbmdyaWQgZm9yIGluZm9ybWF0aW9uIHN1Y2ggYXMgYmFsYW5jZSwgdG9rZW4gYmFsYW5jZSwgc29saWRpdHkgY2FsbHNcbiAgICogQHBhcmFtIHF1ZXJ5IHtPYmplY3R9IGtleS12YWx1ZSBwYWlycyBvZiBwYXJhbWV0ZXJzIHRvIGFwcGVuZCBhZnRlciAvYXBpXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IHJlc3BvbnNlIGZyb20gVHJvbmdyaWRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVjb3ZlcnlHZXQocXVlcnk6IHsgcGF0aDogc3RyaW5nOyBqc29uT2JqOiBhbnk7IG5vZGU6IE5vZGVUeXBlcyB9KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBub2RlVXJpID0gdGhpcy5nZXROb2RlVXJsKHF1ZXJ5Lm5vZGUpO1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0XG4gICAgICAuZ2V0KG5vZGVVcmkgKyBxdWVyeS5wYXRoKVxuICAgICAgLnR5cGUoJ2pzb24nKVxuICAgICAgLnNlbmQocXVlcnkuanNvbk9iaik7XG5cbiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCByZWFjaCBUcm9uIG5vZGUnKTtcbiAgICB9XG5cbiAgICAvLyB1bmZvcnR1bmF0ZWx5LCBpdCBkb2Vzbid0IGxvb2sgbGlrZSBtb3N0IFRST04gbm9kZXMgcmV0dXJuIHZhbGlkIGpzb24gYXMgYm9keVxuICAgIHJldHVybiBKU09OLnBhcnNlKHJlc3BvbnNlLnRleHQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFF1ZXJ5IG91ciBleHBsb3JlciBmb3IgdGhlIGJhbGFuY2Ugb2YgYW4gYWRkcmVzc1xuICAgKiBAcGFyYW0gYWRkcmVzcyB7U3RyaW5nfSB0aGUgYWRkcmVzcyBlbmNvZGVkIGluIGhleFxuICAgKiBAcmV0dXJucyB7QmlnTnVtYmVyfSBhZGRyZXNzIGJhbGFuY2VcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUoYWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxBY2NvdW50UmVzcG9uc2U+IHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5yZWNvdmVyeUdldCh7XG4gICAgICBwYXRoOiAnL3YxL2FjY291bnRzLycgKyBhZGRyZXNzLFxuICAgICAganNvbk9iajoge30sXG4gICAgICBub2RlOiBOb2RlVHlwZXMuRnVsbCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgb3VyIGJ1aWxkIHRyYW5zYWN0aW9uIGZyb20gYSBub2RlLlxuICAgKiBAcGFyYW0gdG9BZGRyIGhleC1lbmNvZGVkIGFkZHJlc3NcbiAgICogQHBhcmFtIGZyb21BZGRyIGhleC1lbmNvZGVkIGFkZHJlc3NcbiAgICogQHBhcmFtIGFtb3VudFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRCdWlsZFRyYW5zYWN0aW9uKFxuICAgIHRvQWRkcjogc3RyaW5nLFxuICAgIGZyb21BZGRyOiBzdHJpbmcsXG4gICAgYW1vdW50OiBudW1iZXJcbiAgKTogUHJvbWlzZTxJbnRlcmZhY2UuVHJhbnNhY3Rpb25SZWNlaXB0PiB7XG4gICAgLy8gb3VyIGFkZHJlc3NlcyBzaG91bGQgYmUgYmFzZTU4LCB3ZSdsbCBoYXZlIHRvIGVuY29kZSB0byBoZXhcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5yZWNvdmVyeVBvc3Qoe1xuICAgICAgcGF0aDogJy93YWxsZXQvY3JlYXRldHJhbnNhY3Rpb24nLFxuICAgICAganNvbk9iajoge1xuICAgICAgICB0b19hZGRyZXNzOiB0b0FkZHIsXG4gICAgICAgIG93bmVyX2FkZHJlc3M6IGZyb21BZGRyLFxuICAgICAgICBhbW91bnQsXG4gICAgICB9LFxuICAgICAgbm9kZTogTm9kZVR5cGVzLkZ1bGwsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIG91ciBidWlsZCB0cmFuc2FjdGlvbiBmcm9tIGEgbm9kZS5cbiAgICogQHBhcmFtIHRvQWRkciBoZXgtZW5jb2RlZCBhZGRyZXNzXG4gICAqIEBwYXJhbSBmcm9tQWRkciBoZXgtZW5jb2RlZCBhZGRyZXNzXG4gICAqIEBwYXJhbSBhbW91bnRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0VHJpZ2dlclNtYXJ0Q29udHJhY3RUcmFuc2FjdGlvbihcbiAgICB0b0FkZHI6IHN0cmluZyxcbiAgICBmcm9tQWRkcjogc3RyaW5nLFxuICAgIGFtb3VudDogc3RyaW5nLFxuICAgIGNvbnRyYWN0QWRkcjogc3RyaW5nXG4gICk6IFByb21pc2U8eyB0cmFuc2FjdGlvbjogSW50ZXJmYWNlLlRyYW5zYWN0aW9uUmVjZWlwdCB9PiB7XG4gICAgY29uc3QgZnVuY3Rpb25TZWxlY3RvciA9ICd0cmFuc2ZlcihhZGRyZXNzLHVpbnQyNTYpJztcbiAgICBjb25zdCB0eXBlcyA9IFsnYWRkcmVzcycsICd1aW50MjU2J107XG4gICAgY29uc3QgdmFsdWVzID0gW3RvQWRkciwgYW1vdW50XTtcbiAgICBjb25zdCBwYXJhbWV0ZXIgPSBVdGlscy5lbmNvZGVEYXRhUGFyYW1zKHR5cGVzLCB2YWx1ZXMsICcnKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5yZWNvdmVyeVBvc3Qoe1xuICAgICAgcGF0aDogJy93YWxsZXQvdHJpZ2dlcnNtYXJ0Y29udHJhY3QnLFxuICAgICAganNvbk9iajoge1xuICAgICAgICBvd25lcl9hZGRyZXNzOiBmcm9tQWRkcixcbiAgICAgICAgY29udHJhY3RfYWRkcmVzczogY29udHJhY3RBZGRyLFxuICAgICAgICBmdW5jdGlvbl9zZWxlY3RvcjogZnVuY3Rpb25TZWxlY3RvcixcbiAgICAgICAgcGFyYW1ldGVyOiBwYXJhbWV0ZXIsXG4gICAgICAgIGZlZV9saW1pdDogMTAwMDAwMDAwLFxuICAgICAgfSxcbiAgICAgIG5vZGU6IE5vZGVUeXBlcy5GdWxsLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiBhbnkga2V5cyBpbiB0aGUgb3duZXJLZXlzIGNvbGxlY3Rpb24gZG9uJ3QgbWF0Y2ggdGhlIGtleXMgYXJyYXkgd2UgcGFzc1xuICAgKiBAcGFyYW0gb3duZXJLZXlzXG4gICAqIEBwYXJhbSBrZXlzXG4gICAqL1xuICBjaGVja1Blcm1pc3Npb25zKG93bmVyS2V5czogeyBhZGRyZXNzOiBzdHJpbmc7IHdlaWdodDogbnVtYmVyIH1bXSwga2V5czogc3RyaW5nW10pIHtcbiAgICBrZXlzID0ga2V5cy5tYXAoKGspID0+IGsudG9VcHBlckNhc2UoKSk7XG5cbiAgICBvd25lcktleXMubWFwKChrZXkpID0+IHtcbiAgICAgIGNvbnN0IGhleEtleSA9IGtleS5hZGRyZXNzLnRvVXBwZXJDYXNlKCk7XG4gICAgICBpZiAoIWtleXMuaW5jbHVkZXMoaGV4S2V5KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHB1YiBhZGRyZXNzICR7aGV4S2V5fSBub3QgZm91bmQgaW4gYWNjb3VudGApO1xuICAgICAgfVxuXG4gICAgICBpZiAoa2V5LndlaWdodCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ293bmVyIHBlcm1pc3Npb24gaXMgaW52YWxpZCBmb3IgdGhpcyBzdHJ1Y3R1cmUnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXQgZm9yIG9mZmxpbmUgdmF1bHQgc2lnbmluZ1xuICAgKiBAcGFyYW0ge0Jhc2VUcmFuc2FjdGlvbn0gdHhcbiAgICogQHBhcmFtIHtudW1iZXJ9IGZlZVxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVjb3ZlcnlBbW91bnRcbiAgICogQHJldHVybnMge1JlY292ZXJ5VHJhbnNhY3Rpb259XG4gICAqL1xuICBmb3JtYXRGb3JPZmZsaW5lVmF1bHQoXG4gICAgdHg6IEJhc2VUcmFuc2FjdGlvbixcbiAgICBmZWU6IG51bWJlcixcbiAgICByZWNvdmVyeUFtb3VudDogbnVtYmVyLFxuICAgIGFkZHJlc3NJbmZvPzogQWRkcmVzc0luZm9cbiAgKTogUmVjb3ZlcnlUcmFuc2FjdGlvbiB7XG4gICAgY29uc3QgdHhKU09OID0gdHgudG9Kc29uKCk7XG4gICAgY29uc3QgZm9ybWF0ID0ge1xuICAgICAgdHhIZXg6IEpTT04uc3RyaW5naWZ5KHR4SlNPTiksXG4gICAgICByZWNvdmVyeUFtb3VudCxcbiAgICAgIGZlZUluZm86IHtcbiAgICAgICAgZmVlOiBgJHtmZWV9YCxcbiAgICAgIH0sXG4gICAgICB0eDogdHhKU09OLCAvLyBMZWF2aW5nIGl0IGFzIHR4SlNPTiBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgICAgIGNvaW46IHRoaXMuZ2V0Q2hhaW4oKSxcbiAgICB9O1xuICAgIHJldHVybiBhZGRyZXNzSW5mbyA/IHsgLi4uZm9ybWF0LCBhZGRyZXNzSW5mbyB9IDogZm9ybWF0O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGZ1bmRzIHJlY292ZXJ5IHRyYW5zYWN0aW9uIHdpdGhvdXQgQml0R28uXG4gICAqIFdlIG5lZWQgdG8gZG8gdGhyZWUgcXVlcmllcyBkdXJpbmcgdGhpczpcbiAgICogMSkgTm9kZSBxdWVyeSAtIGhvdyBtdWNoIG1vbmV5IGlzIGluIHRoZSBhY2NvdW50XG4gICAqIDIpIEJ1aWxkIHRyYW5zYWN0aW9uIC0gYnVpbGQgb3VyIHRyYW5zYWN0aW9uIGZvciB0aGUgYW1vdW50XG4gICAqIDMpIFNlbmQgc2lnbmVkIGJ1aWxkIC0gc2VuZCBvdXIgc2lnbmVkIGJ1aWxkIHRvIGEgcHVibGljIG5vZGVcbiAgICpcbiAgICogTm90ZSAxOiBmb3IgYmFzZSBhZGRyZXNzIHJlY292ZXJpZXMsIGZ1bmQgd2lsbCBiZSByZWNvdmVyZWQgdG8gcmVjb3ZlcnkgZGVzdGluYXRpb24gaWYgYmFzZSBhZGRyZXNzIGJhbGFuY2UgaXNcbiAgICogbW9yZSB0aGFuIDIuMSBUUlggZm9yIG5hdGl2ZSBUUlggcmVjb3ZlcnkgYW5kIDEwMCBUUlggZm9yIHRva2VuIHJlY292ZXIuIEZvciByZWNlaXZlIGFkZHJlc3NlcywgZnVuZCB3aWxsIGJlXG4gICAqIHJlY292ZXJlZCB0byBiYXNlIGFkZHJlc3MgZmlyc3QgdGhlbiBzd2VwdCB0byBiYXNlIGFkZHJlc3MoZGVjaWRlZCBhcyB0aGUgdW5pdmVyc2FsIHBhdHRlcm4gaW4gdGVhbSBtZWV0aW5nKS5cbiAgICpcbiAgICogTm90ZSAyOiB0aGUgZnVuY3Rpb24gc3VwcG9ydHMgdG9rZW4gc3dlZXAgZnJvbSBiYXNlIGFkZHJlc3MuXG4gICAqIFRPRE86IHN1cHBvcnQgdG9rZW4gc3dlZXAgZnJvbSByZWNlaXZlIGFkZHJlc3MuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIGFzeW5jIHJlY292ZXIocGFyYW1zOiBSZWNvdmVyeU9wdGlvbnMpOiBQcm9taXNlPFJlY292ZXJ5VHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCBpc0tyc1JlY292ZXJ5ID0gZ2V0SXNLcnNSZWNvdmVyeShwYXJhbXMpO1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9IGdldElzVW5zaWduZWRTd2VlcChwYXJhbXMpO1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRlc3RpbmF0aW9uIGFkZHJlc3MhJyk7XG4gICAgfVxuXG4gICAgbGV0IHN0YXJ0SWR4ID0gcGFyYW1zLnN0YXJ0aW5nU2NhbkluZGV4O1xuICAgIGlmIChpc1VuZGVmaW5lZChzdGFydElkeCkpIHtcbiAgICAgIHN0YXJ0SWR4ID0gMTtcbiAgICB9IGVsc2UgaWYgKCFpc0ludGVnZXIoc3RhcnRJZHgpIHx8IHN0YXJ0SWR4IDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0YXJ0aW5nIGluZGV4IHRvIHNjYW4gZm9yIGFkZHJlc3NlcycpO1xuICAgIH1cblxuICAgIGxldCBudW1JdGVyYXRpb24gPSBwYXJhbXMuc2NhbjtcbiAgICBpZiAoaXNVbmRlZmluZWQobnVtSXRlcmF0aW9uKSkge1xuICAgICAgbnVtSXRlcmF0aW9uID0gMjA7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbnVtSXRlcmF0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgbnVtSXRlcmF0aW9uID0gcGFyc2VJbnQobnVtSXRlcmF0aW9uLCAxMCk7XG4gICAgfVxuXG4gICAgaWYgKCFpc0ludGVnZXIobnVtSXRlcmF0aW9uKSB8fCBudW1JdGVyYXRpb24gPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNjYW5uaW5nIGZhY3RvcicpO1xuICAgIH1cblxuICAgIC8vIGdldCBvdXIgdXNlciwgYmFja3VwIGtleXNcbiAgICBjb25zdCBrZXlzID0gZ2V0QmlwMzJLZXlzKHRoaXMuYml0Z28sIHBhcmFtcywgeyByZXF1aXJlQml0R29YcHViOiBmYWxzZSB9KTtcblxuICAgIC8vIHdlIG5lZWQgdG8gZGVjb2RlIG91ciBiaXRnb0tleSB0byBhIGJhc2U1OCBhZGRyZXNzXG4gICAgY29uc3QgYml0Z29IZXhBZGRyID0gdGhpcy5wdWJUb0hleEFkZHJlc3ModGhpcy54cHViVG9VbmNvbXByZXNzZWRQdWIocGFyYW1zLmJpdGdvS2V5KSk7XG4gICAgbGV0IHJlY292ZXJ5RnJvbUFkZHJIZXggPSBiaXRnb0hleEFkZHI7XG4gICAgbGV0IHJlY292ZXJ5VG9BZGRyZXNzSGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKTtcblxuICAgIC8vIGNhbGwgdGhlIG5vZGUgdG8gZ2V0IG91ciBhY2NvdW50IGJhbGFuY2UgZm9yIGJhc2UgYWRkcmVzc1xuICAgIGxldCBhY2NvdW50ID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50QmFsYW5jZXNGcm9tTm9kZShVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleChyZWNvdmVyeUZyb21BZGRySGV4KSk7XG4gICAgbGV0IHJlY292ZXJ5QW1vdW50ID0gYWNjb3VudC5kYXRhWzBdLmJhbGFuY2U7XG5cbiAgICBsZXQgdXNlclhQcnYgPSBrZXlzWzBdLnRvQmFzZTU4KCk7XG4gICAgbGV0IGlzUmVjZWl2ZUFkZHJlc3MgPSBmYWxzZTtcbiAgICBsZXQgYWRkcmVzc0luZm86IEFkZHJlc3NJbmZvIHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRva2VuQ29udHJhY3RBZGRyID0gcGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzO1xuICAgIC8vIGNoZWNrIGZvciBwb3NzaWJsZSB0b2tlbiByZWNvdmVyeSwgcmVjb3ZlciB0aGUgdG9rZW4gcHJvdmlkZSBieSB1c2VyXG4gICAgaWYgKHRva2VuQ29udHJhY3RBZGRyKSB7XG4gICAgICBsZXQgcmF3VG9rZW5UeG46IGFueSB8IHVuZGVmaW5lZDtcbiAgICAgIGZvciAoY29uc3QgdG9rZW4gb2YgYWNjb3VudC5kYXRhWzBdLnRyYzIwKSB7XG4gICAgICAgIGlmICh0b2tlblt0b2tlbkNvbnRyYWN0QWRkcl0pIHtcbiAgICAgICAgICBjb25zdCBhbW91bnQgPSB0b2tlblt0b2tlbkNvbnRyYWN0QWRkcl07XG4gICAgICAgICAgY29uc3QgdG9rZW5Db250cmFjdEFkZHJIZXggPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3ModG9rZW5Db250cmFjdEFkZHIpO1xuICAgICAgICAgIHJhd1Rva2VuVHhuID0gKFxuICAgICAgICAgICAgYXdhaXQgdGhpcy5nZXRUcmlnZ2VyU21hcnRDb250cmFjdFRyYW5zYWN0aW9uKFxuICAgICAgICAgICAgICByZWNvdmVyeVRvQWRkcmVzc0hleCxcbiAgICAgICAgICAgICAgcmVjb3ZlcnlGcm9tQWRkckhleCxcbiAgICAgICAgICAgICAgYW1vdW50LFxuICAgICAgICAgICAgICB0b2tlbkNvbnRyYWN0QWRkckhleFxuICAgICAgICAgICAgKVxuICAgICAgICAgICkudHJhbnNhY3Rpb247XG4gICAgICAgICAgcmVjb3ZlcnlBbW91bnQgPSBwYXJzZUludChhbW91bnQsIDEwKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBidWlsZCBhbmQgc2lnbiB0b2tlbiB0eG5zXG4gICAgICBpZiAocmF3VG9rZW5UeG4pIHtcbiAgICAgICAgLy8gQ2hlY2sgdGhlcmUgaXMgc3VmZmljaWVudCBvZiB0aGUgbmF0aXZlIGFzc2V0IHRvIGNvdmVyIGZlZXNcbiAgICAgICAgY29uc3QgdHJ4QmFsYW5jZSA9IGFjY291bnQuZGF0YVswXS5iYWxhbmNlO1xuICAgICAgICBpZiAodHJ4QmFsYW5jZSA8IFNBRkVfVFJPTl9UT0tFTl9UUkFOU0FDVElPTl9GRUUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgQW1vdW50IG9mIGZ1bmRzIHRvIHJlY292ZXIgJHt0cnhCYWxhbmNlfSBpcyBsZXNzIHRoYW4gJHtTQUZFX1RST05fVE9LRU5fVFJBTlNBQ1RJT05fRkVFfSBhbmQgd291bGRuJ3QgYmUgYWJsZSB0byBmdW5kIGEgdHJjMjAgc2VuZGBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcih0aGlzLmdldENoYWluKCkpLmZyb20ocmF3VG9rZW5UeG4pO1xuICAgICAgICAvLyBEZWZhdWx0IGV4cGlyeSBpcyAxIG1pbnV0ZSB3aGljaCBpcyB0b28gc2hvcnQgZm9yIHJlY292ZXJ5IHB1cnBvc2VzXG4gICAgICAgIC8vIGV4dGVuZCB0aGUgZXhwaXJ5IHRvIDEgZGF5XG4gICAgICAgIHR4QnVpbGRlci5leHRlbmRWYWxpZFRvKFJFQ09WRVJfVFJBTlNBQ1RJT05fRVhQSVJZKTtcbiAgICAgICAgLy8gdGhpcyB0eCBzaG91bGQgYmUgZW5vdWdoIHRvIGRyb3AgaW50byBhIG5vZGVcbiAgICAgICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLmZvcm1hdEZvck9mZmxpbmVWYXVsdChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSwgU0FGRV9UUk9OX1RPS0VOX1RSQU5TQUNUSU9OX0ZFRSwgcmVjb3ZlcnlBbW91bnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdXNlclBydiA9IHRoaXMueHBydlRvQ29tcHJlc3NlZFBydih1c2VyWFBydik7XG5cbiAgICAgICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHVzZXJQcnYgfSk7XG5cbiAgICAgICAgLy8ga3JzIHJlY292ZXJpZXMgZG9uJ3QgZ2V0IHNpZ25lZFxuICAgICAgICBpZiAoIWlzS3JzUmVjb3ZlcnkgJiYgIWlzUmVjZWl2ZUFkZHJlc3MpIHtcbiAgICAgICAgICBjb25zdCBiYWNrdXBYUHJ2ID0ga2V5c1sxXS50b0Jhc2U1OCgpO1xuICAgICAgICAgIGNvbnN0IGJhY2t1cFBydiA9IHRoaXMueHBydlRvQ29tcHJlc3NlZFBydihiYWNrdXBYUHJ2KTtcblxuICAgICAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBiYWNrdXBQcnYgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KGF3YWl0IHR4QnVpbGRlci5idWlsZCgpLCBTQUZFX1RST05fVE9LRU5fVFJBTlNBQ1RJT05fRkVFLCByZWNvdmVyeUFtb3VudCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBFcnJvcignTm90IGZvdW5kIHRva2VuIHRvIHJlY292ZXIsIHBsZWFzZSBjaGVjayB0b2tlbiBiYWxhbmNlJyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIGxldCB1cyByZWNvdmVyIHRoZSBuYXRpdmUgVHJvblxuICAgIGlmIChyZWNvdmVyeUFtb3VudCA+IFNBRkVfVFJPTl9UUkFOU0FDVElPTl9GRUUpIHtcbiAgICAgIGNvbnN0IHVzZXJYUHViID0ga2V5c1swXS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCk7XG4gICAgICBjb25zdCBiYWNrdXBYUHViID0ga2V5c1sxXS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCk7XG5cbiAgICAgIC8vIGNoZWNrIG11bHRpc2lnIHBlcm1pc3Npb25zXG4gICAgICBjb25zdCBrZXlIZXhBZGRyZXNzZXMgPSBbXG4gICAgICAgIHRoaXMucHViVG9IZXhBZGRyZXNzKHRoaXMueHB1YlRvVW5jb21wcmVzc2VkUHViKHVzZXJYUHViKSksXG4gICAgICAgIHRoaXMucHViVG9IZXhBZGRyZXNzKHRoaXMueHB1YlRvVW5jb21wcmVzc2VkUHViKGJhY2t1cFhQdWIpKSxcbiAgICAgICAgYml0Z29IZXhBZGRyLFxuICAgICAgXTtcbiAgICAgIC8vIHJ1biBjaGVja3MgdG8gZW5zdXJlIHRoaXMgaXMgYSB2YWxpZCB0eCAtIHBlcm1pc3Npb25zIG1hdGNoIG91ciBzaWduZXIga2V5c1xuICAgICAgY29uc3Qgb3duZXJLZXlzOiB7IGFkZHJlc3M6IHN0cmluZzsgd2VpZ2h0OiBudW1iZXIgfVtdID0gW107XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBhY2NvdW50LmRhdGFbMF0ub3duZXJfcGVybWlzc2lvbi5rZXlzKSB7XG4gICAgICAgIGNvbnN0IGFkZHJlc3MgPSBVdGlscy5nZXRIZXhBZGRyZXNzRnJvbUJhc2U1OEFkZHJlc3Moa2V5LmFkZHJlc3MpO1xuICAgICAgICBjb25zdCB3ZWlnaHQgPSBrZXkud2VpZ2h0O1xuICAgICAgICBvd25lcktleXMucHVzaCh7IGFkZHJlc3MsIHdlaWdodCB9KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdGl2ZVBlcm1pc3Npb25LZXlzOiB7IGFkZHJlc3M6IHN0cmluZzsgd2VpZ2h0OiBudW1iZXIgfVtdID0gW107XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBhY2NvdW50LmRhdGFbMF0uYWN0aXZlX3Blcm1pc3Npb25bMF0ua2V5cykge1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKGtleS5hZGRyZXNzKTtcbiAgICAgICAgY29uc3Qgd2VpZ2h0ID0ga2V5LndlaWdodDtcbiAgICAgICAgYWN0aXZlUGVybWlzc2lvbktleXMucHVzaCh7IGFkZHJlc3MsIHdlaWdodCB9KTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2hlY2tQZXJtaXNzaW9ucyhvd25lcktleXMsIGtleUhleEFkZHJlc3Nlcyk7XG4gICAgICB0aGlzLmNoZWNrUGVybWlzc2lvbnMoYWN0aXZlUGVybWlzc2lvbktleXMsIGtleUhleEFkZHJlc3Nlcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENoZWNrIHJlY2VpdmUgYWRkcmVzc2VzIGZvciBmdW5kc1xuICAgICAgLy8gQ2hlY2sgZm9yIGZpcnN0IGRlcml2ZWQgd2FsbGV0IHdpdGggZnVuZHNcbiAgICAgIC8vIFJlY2VpdmUgYWRkcmVzc2VzIGFyZSBkZXJpdmVkIGZyb20gdGhlIHVzZXIga2V5XG4gICAgICBmb3IgKGxldCBpID0gc3RhcnRJZHg7IGkgPCBudW1JdGVyYXRpb24gKyBzdGFydElkeDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gYDAvMC8wLyR7aX1gO1xuICAgICAgICBjb25zdCB1c2VyS2V5ID0ga2V5c1swXS5kZXJpdmVQYXRoKGRlcml2YXRpb25QYXRoKTtcbiAgICAgICAgY29uc3QgeHB1YiA9IHVzZXJLZXkubmV1dGVyZWQoKTtcbiAgICAgICAgY29uc3QgcmVjZWl2ZUFkZHJlc3MgPSB0aGlzLnB1YlRvSGV4QWRkcmVzcyh0aGlzLnhwdWJUb1VuY29tcHJlc3NlZFB1Yih4cHViLnRvQmFzZTU4KCkpKTtcbiAgICAgICAgY29uc3QgYWRkcmVzcyA9IFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHJlY2VpdmVBZGRyZXNzKTtcbiAgICAgICAgLy8gY2FsbCB0aGUgbm9kZSB0byBnZXQgb3VyIGFjY291bnQgYmFsYW5jZVxuICAgICAgICBjb25zdCBhY2NvdW50SW5mbyA9IGF3YWl0IHRoaXMuZ2V0QWNjb3VudEJhbGFuY2VzRnJvbU5vZGUoYWRkcmVzcyk7XG5cbiAgICAgICAgaWYgKGFjY291bnRJbmZvLmRhdGFbMF0gJiYgYWNjb3VudEluZm8uZGF0YVswXS5iYWxhbmNlID4gU0FGRV9UUk9OX1RSQU5TQUNUSU9OX0ZFRSkge1xuICAgICAgICAgIGFjY291bnQgPSBhY2NvdW50SW5mbztcbiAgICAgICAgICByZWNvdmVyeUFtb3VudCA9IGFjY291bnRJbmZvLmRhdGFbMF0uYmFsYW5jZTtcbiAgICAgICAgICB1c2VyWFBydiA9IHVzZXJLZXkudG9CYXNlNTgoKTsgLy8gYXNzaWduIGRlcml2ZWQgdXNlclhQcnhcbiAgICAgICAgICBpc1JlY2VpdmVBZGRyZXNzID0gdHJ1ZTtcbiAgICAgICAgICByZWNvdmVyeUZyb21BZGRySGV4ID0gcmVjZWl2ZUFkZHJlc3M7XG4gICAgICAgICAgcmVjb3ZlcnlUb0FkZHJlc3NIZXggPSBiaXRnb0hleEFkZHI7XG4gICAgICAgICAgYWRkcmVzc0luZm8gPSB7XG4gICAgICAgICAgICBhZGRyZXNzLFxuICAgICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYSBzd2VlcCBwb3RlbnRpYWxseSBuZWVkcyB0byBwYXkgZm9yIG11bHRpLXNpZyB0cmFuc2ZlciwgZGVzdGluYXRpb24gYWNjb3VudCBhY3RpdmF0aW9uIGFuZCBiYW5kd2lkdGhcbiAgICAvLyBUUk9OIGZvdW5kYXRpb24gcmVjb21tZW5kcyAyLjEgVFJYIGZvciBndWFyYW50ZWVkIGNvbmZpcm1hdGlvblxuICAgIGlmICghcmVjb3ZlcnlBbW91bnQgfHwgU0FGRV9UUk9OX1RSQU5TQUNUSU9OX0ZFRSA+PSByZWNvdmVyeUFtb3VudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQW1vdW50IG9mIGZ1bmRzIHRvIHJlY292ZXIgJHtyZWNvdmVyeUFtb3VudH0gaXMgbGVzcyB0aGFuICR7U0FGRV9UUk9OX1RSQU5TQUNUSU9OX0ZFRX0gYW5kIHdvdWxkbid0IGJlIGFibGUgdG8gZnVuZCBhIHNlbmRgXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlY292ZXJ5QW1vdW50TWludXNGZWVzID0gcmVjb3ZlcnlBbW91bnQgLSBTQUZFX1RST05fVFJBTlNBQ1RJT05fRkVFO1xuICAgIGNvbnN0IGJ1aWxkVHggPSBhd2FpdCB0aGlzLmdldEJ1aWxkVHJhbnNhY3Rpb24ocmVjb3ZlcnlUb0FkZHJlc3NIZXgsIHJlY292ZXJ5RnJvbUFkZHJIZXgsIHJlY292ZXJ5QW1vdW50TWludXNGZWVzKTtcblxuICAgIC8vIGNvbnN0cnVjdCBvdXIgdHhcbiAgICBjb25zdCB0eEJ1aWxkZXIgPSAoZ2V0QnVpbGRlcih0aGlzLmdldENoYWluKCkpIGFzIFdyYXBwZWRCdWlsZGVyKS5mcm9tKGJ1aWxkVHgpO1xuICAgIC8vIERlZmF1bHQgZXhwaXJ5IGlzIDEgbWludXRlIHdoaWNoIGlzIHRvbyBzaG9ydCBmb3IgcmVjb3ZlcnkgcHVycG9zZXNcbiAgICAvLyBleHRlbmQgdGhlIGV4cGlyeSB0byAxIGRheVxuICAgIHR4QnVpbGRlci5leHRlbmRWYWxpZFRvKFJFQ09WRVJfVFJBTlNBQ1RJT05fRVhQSVJZKTtcbiAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgLy8gdGhpcyB0eCBzaG91bGQgYmUgZW5vdWdoIHRvIGRyb3AgaW50byBhIG5vZGVcbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICByZXR1cm4gdGhpcy5mb3JtYXRGb3JPZmZsaW5lVmF1bHQodHgsIFNBRkVfVFJPTl9UUkFOU0FDVElPTl9GRUUsIHJlY292ZXJ5QW1vdW50TWludXNGZWVzLCBhZGRyZXNzSW5mbyk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlclBydiA9IHRoaXMueHBydlRvQ29tcHJlc3NlZFBydih1c2VyWFBydik7XG5cbiAgICB0eEJ1aWxkZXIuc2lnbih7IGtleTogdXNlclBydiB9KTtcblxuICAgIC8vIGtycyByZWNvdmVyaWVzIGRvbid0IGdldCBzaWduZWRcbiAgICBpZiAoIWlzS3JzUmVjb3ZlcnkgJiYgIWlzUmVjZWl2ZUFkZHJlc3MpIHtcbiAgICAgIGNvbnN0IGJhY2t1cFhQcnYgPSBrZXlzWzFdLnRvQmFzZTU4KCk7XG4gICAgICBjb25zdCBiYWNrdXBQcnYgPSB0aGlzLnhwcnZUb0NvbXByZXNzZWRQcnYoYmFja3VwWFBydik7XG5cbiAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBiYWNrdXBQcnYgfSk7XG4gICAgfVxuICAgIGNvbnN0IHR4U2lnbmVkID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KHR4U2lnbmVkLCBTQUZFX1RST05fVFJBTlNBQ1RJT05fRkVFLCByZWNvdmVyeUFtb3VudE1pbnVzRmVlcywgYWRkcmVzc0luZm8pO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBuYXRpdmUgVFJYIHJlY292ZXJpZXMgb2YgcmVjZWl2ZSBhZGRyZXNzZXMgaW4gYmF0Y2ggd2l0aG91dCBCaXRHby5cbiAgICogRnVuZHMgd2lsbCBiZSByZWNvdmVyZWQgdG8gYmFzZSBhZGRyZXNzIGZpcnN0LiBZb3UgbmVlZCB0byBpbml0aWF0ZSBhbm90aGVyIHN3ZWVwIHR4biBhZnRlciB0aGF0LlxuICAgKiBOb3RlOiB0aGVyZSB3aWxsIGJlIGFub3RoZXIgcmVjb3ZlclRva2VuQ29uc29saWRhdGlvbnMgZnVuY3Rpb24gdG8gc3VwcG9ydCB0b2tlbiByZWNvdmVyIGZyb20gcmVjZWl2ZSBhZGRyZXNzZXMuXG4gICAqXG4gICAqIEBwYXJhbSB7Q29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9uc30gcGFyYW1zIC0gb3B0aW9ucyBmb3IgY29uc29saWRhdGlvbiByZWNvdmVyeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXJhbXMuc3RhcnRpbmdTY2FuSW5kZXhdIC0gcmVjZWl2ZSBhZGRyZXNzIGluZGV4IHRvIHN0YXJ0IHNjYW5uaW5nIGZyb20uIGRlZmF1bHQgdG8gMSAoaW5jbHVzaXZlKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXJhbXMuZW5kaW5nU2NhbkluZGV4XSAtIHJlY2VpdmUgYWRkcmVzcyBpbmRleCB0byBlbmQgc2Nhbm5pbmcgYXQuIGRlZmF1bHQgdG8gc3RhcnRpbmdTY2FuSW5kZXggKyAyMCAoZXhjbHVzaXZlKS5cbiAgICovXG4gIGFzeW5jIHJlY292ZXJDb25zb2xpZGF0aW9ucyhwYXJhbXM6IENvbnNvbGlkYXRpb25SZWNvdmVyeU9wdGlvbnMpOiBQcm9taXNlPENvbnNvbGlkYXRpb25SZWNvdmVyeUJhdGNoPiB7XG4gICAgY29uc3QgaXNVbnNpZ25lZENvbnNvbGlkYXRpb25zID0gZ2V0SXNVbnNpZ25lZFN3ZWVwKHBhcmFtcyk7XG4gICAgY29uc3Qgc3RhcnRJZHggPSBwYXJhbXMuc3RhcnRpbmdTY2FuSW5kZXggfHwgMTtcbiAgICBjb25zdCBlbmRJZHggPSBwYXJhbXMuZW5kaW5nU2NhbkluZGV4IHx8IHN0YXJ0SWR4ICsgREVGQVVMVF9TQ0FOX0ZBQ1RPUjtcblxuICAgIGlmIChzdGFydElkeCA8IDEgfHwgZW5kSWR4IDw9IHN0YXJ0SWR4IHx8IGVuZElkeCAtIHN0YXJ0SWR4ID4gMTAgKiBERUZBVUxUX1NDQU5fRkFDVE9SKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIHN0YXJ0aW5nIG9yIGVuZGluZyBpbmRleCB0byBzY2FuIGZvciBhZGRyZXNzZXMuIHN0YXJ0aW5nU2NhbkluZGV4OiAke3N0YXJ0SWR4fSwgZW5kaW5nU2NhbkluZGV4OiAke2VuZElkeH0uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBrZXlzID0gZ2V0QmlwMzJLZXlzKHRoaXMuYml0Z28sIHBhcmFtcywgeyByZXF1aXJlQml0R29YcHViOiBmYWxzZSB9KTtcbiAgICBjb25zdCBiYXNlQWRkckhleCA9IHRoaXMucHViVG9IZXhBZGRyZXNzKHRoaXMueHB1YlRvVW5jb21wcmVzc2VkUHViKHBhcmFtcy5iaXRnb0tleSkpO1xuXG4gICAgY29uc3QgdHhuc0JhdGNoOiBSZWNvdmVyeVRyYW5zYWN0aW9uW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gc3RhcnRJZHg7IGkgPCBlbmRJZHg7IGkrKykge1xuICAgICAgY29uc3QgZGVyaXZhdGlvblBhdGggPSBgMC8wLzAvJHtpfWA7XG4gICAgICBjb25zdCB1c2VyS2V5ID0ga2V5c1swXS5kZXJpdmVQYXRoKGRlcml2YXRpb25QYXRoKTtcbiAgICAgIGNvbnN0IHVzZXJLZXlYUHViID0gdXNlcktleS5uZXV0ZXJlZCgpO1xuICAgICAgY29uc3QgcmVjZWl2ZUFkZHJlc3NIZXggPSB0aGlzLnB1YlRvSGV4QWRkcmVzcyh0aGlzLnhwdWJUb1VuY29tcHJlc3NlZFB1Yih1c2VyS2V5WFB1Yi50b0Jhc2U1OCgpKSk7XG4gICAgICBjb25zdCByZWNlaXZlQWRkcmVzcyA9IFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHJlY2VpdmVBZGRyZXNzSGV4KTtcbiAgICAgIC8vIGNhbGwgdGhlIG5vZGUgdG8gZ2V0IG91ciBhY2NvdW50IGJhbGFuY2VcbiAgICAgIGNvbnN0IGFjY291bnRJbmZvID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50QmFsYW5jZXNGcm9tTm9kZShyZWNlaXZlQWRkcmVzcyk7XG5cbiAgICAgIGlmIChhY2NvdW50SW5mby5kYXRhWzBdICYmIGFjY291bnRJbmZvLmRhdGFbMF0uYmFsYW5jZSA+IFNBRkVfVFJPTl9UUkFOU0FDVElPTl9GRUUpIHtcbiAgICAgICAgbGV0IHJlY292ZXJ5QW1vdW50ID0gMDtcbiAgICAgICAgLy8gVG9rZW5zIG11c3QgYmUgY29uc29saWRhdGUgYmVmb3JlIHRoZSBuYXRpdmUgYXNzZXQuIEZpcnN0IGNvbnN0cnVjdCB0b2tlbiB0eG5zXG4gICAgICAgIGxldCByYXdUb2tlblR4bjogYW55IHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIGNoZWNrIGZvciBwb3NzaWJsZSB0b2tlbiByZWNvdmVyeSwgcmVjb3ZlciB0aGUgdG9rZW4gcHJvdmlkZSBieSB1c2VyXG4gICAgICAgIGlmIChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MpIHtcbiAgICAgICAgICBpZiAoYWNjb3VudEluZm8uZGF0YVswXS5iYWxhbmNlID4gU0FGRV9UUk9OX1RPS0VOX1RSQU5TQUNUSU9OX0ZFRSAmJiBhY2NvdW50SW5mby5kYXRhWzBdLnRyYzIwWzBdKSB7XG4gICAgICAgICAgICBjb25zdCB0b2tlbkRhdGFBcnJheSA9IGFjY291bnRJbmZvLmRhdGFbMF0udHJjMjA7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRva2VuRGF0YSBvZiB0b2tlbkRhdGFBcnJheSkge1xuICAgICAgICAgICAgICBjb25zdCBjb250cmFjdEFkZHJlc3MgPSBPYmplY3Qua2V5cyh0b2tlbkRhdGEpIGFzIEFycmF5PHN0cmluZz47XG4gICAgICAgICAgICAgIGlmIChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MgPT09IGNvbnRyYWN0QWRkcmVzc1swXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFtb3VudCA9IHRva2VuRGF0YVtjb250cmFjdEFkZHJlc3NbMF1dO1xuICAgICAgICAgICAgICAgIGNvbnN0IHRva2VuQ29udHJhY3RBZGRySGV4ID0gVXRpbHMuZ2V0SGV4QWRkcmVzc0Zyb21CYXNlNThBZGRyZXNzKGNvbnRyYWN0QWRkcmVzc1swXSk7XG4gICAgICAgICAgICAgICAgcmF3VG9rZW5UeG4gPSAoXG4gICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmdldFRyaWdnZXJTbWFydENvbnRyYWN0VHJhbnNhY3Rpb24oXG4gICAgICAgICAgICAgICAgICAgIGJhc2VBZGRySGV4LFxuICAgICAgICAgICAgICAgICAgICByZWNlaXZlQWRkcmVzc0hleCxcbiAgICAgICAgICAgICAgICAgICAgYW1vdW50LFxuICAgICAgICAgICAgICAgICAgICB0b2tlbkNvbnRyYWN0QWRkckhleFxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICkudHJhbnNhY3Rpb247XG4gICAgICAgICAgICAgICAgcmVjb3ZlcnlBbW91bnQgPSBwYXJzZUludChhbW91bnQsIDEwKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBidWlsZCBhbmQgc2lnbiB0b2tlbiB0eG5zXG4gICAgICAgICAgaWYgKHJhd1Rva2VuVHhuKSB7XG4gICAgICAgICAgICBjb25zdCBhZGRyZXNzSW5mbyA9IHtcbiAgICAgICAgICAgICAgYWRkcmVzczogcmVjZWl2ZUFkZHJlc3MsXG4gICAgICAgICAgICAgIGNoYWluOiAwLFxuICAgICAgICAgICAgICBpbmRleDogaSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKHRoaXMuZ2V0Q2hhaW4oKSkuZnJvbShyYXdUb2tlblR4bik7XG4gICAgICAgICAgICAvLyBEZWZhdWx0IGV4cGlyeSBpcyAxIG1pbnV0ZSB3aGljaCBpcyB0b28gc2hvcnQgZm9yIHJlY292ZXJ5IHB1cnBvc2VzXG4gICAgICAgICAgICAvLyBleHRlbmQgdGhlIGV4cGlyeSB0byAxIGRheVxuICAgICAgICAgICAgdHhCdWlsZGVyLmV4dGVuZFZhbGlkVG8oUkVDT1ZFUl9UUkFOU0FDVElPTl9FWFBJUlkpO1xuICAgICAgICAgICAgLy8gdGhpcyB0eCBzaG91bGQgYmUgZW5vdWdoIHRvIGRyb3AgaW50byBhIG5vZGVcbiAgICAgICAgICAgIGlmICghaXNVbnNpZ25lZENvbnNvbGlkYXRpb25zKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHVzZXJQcnYgPSB0aGlzLnhwcnZUb0NvbXByZXNzZWRQcnYodXNlcktleS50b0Jhc2U1OCgpKTtcbiAgICAgICAgICAgICAgLy8gcmVjZWl2ZSBhZGRyZXNzIG9ubHkgbmVlZHMgdG8gYmUgc2lnbmVkIGJ5IHVzZXIga2V5XG4gICAgICAgICAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB1c2VyUHJ2IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgICAgIHR4bnNCYXRjaC5wdXNoKFxuICAgICAgICAgICAgICB0aGlzLmZvcm1hdEZvck9mZmxpbmVWYXVsdCh0eCwgU0FGRV9UUk9OX1RPS0VOX1RSQU5TQUNUSU9OX0ZFRSwgcmVjb3ZlcnlBbW91bnQsIGFkZHJlc3NJbmZvKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgYWRkcmVzc0JhbGFuY2UgPSBhY2NvdW50SW5mby5kYXRhWzBdLmJhbGFuY2U7XG4gICAgICAgICAgY29uc3QgYWRkcmVzc0luZm8gPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiByZWNlaXZlQWRkcmVzcyxcbiAgICAgICAgICAgIGNoYWluOiAwLFxuICAgICAgICAgICAgaW5kZXg6IGksXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCByZWNvdmVyeUFtb3VudCA9IGFkZHJlc3NCYWxhbmNlIC0gU0FGRV9UUk9OX1RSQU5TQUNUSU9OX0ZFRTtcbiAgICAgICAgICBjb25zdCBidWlsZFR4ID0gYXdhaXQgdGhpcy5nZXRCdWlsZFRyYW5zYWN0aW9uKGJhc2VBZGRySGV4LCByZWNlaXZlQWRkcmVzc0hleCwgcmVjb3ZlcnlBbW91bnQpO1xuICAgICAgICAgIC8vIGNvbnN0cnVjdCBvdXIgdHhcbiAgICAgICAgICBjb25zdCB0eEJ1aWxkZXIgPSAoZ2V0QnVpbGRlcih0aGlzLmdldENoYWluKCkpIGFzIFdyYXBwZWRCdWlsZGVyKS5mcm9tKGJ1aWxkVHgpO1xuICAgICAgICAgIC8vIERlZmF1bHQgZXhwaXJ5IGlzIDEgbWludXRlIHdoaWNoIGlzIHRvbyBzaG9ydCBmb3IgcmVjb3ZlcnkgcHVycG9zZXNcbiAgICAgICAgICAvLyBleHRlbmQgdGhlIGV4cGlyeSB0byAxIGRheVxuICAgICAgICAgIHR4QnVpbGRlci5leHRlbmRWYWxpZFRvKFJFQ09WRVJfVFJBTlNBQ1RJT05fRVhQSVJZKTtcblxuICAgICAgICAgIGlmICghaXNVbnNpZ25lZENvbnNvbGlkYXRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCB1c2VyUHJ2ID0gdGhpcy54cHJ2VG9Db21wcmVzc2VkUHJ2KHVzZXJLZXkudG9CYXNlNTgoKSk7XG4gICAgICAgICAgICAvLyByZWNlaXZlIGFkZHJlc3Mgb25seSBuZWVkcyB0byBiZSBzaWduZWQgYnkgdXNlciBrZXlcbiAgICAgICAgICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiB1c2VyUHJ2IH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgICAgIHR4bnNCYXRjaC5wdXNoKHRoaXMuZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KHR4LCBTQUZFX1RST05fVFJBTlNBQ1RJT05fRkVFLCByZWNvdmVyeUFtb3VudCwgYWRkcmVzc0luZm8pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0cmFuc2FjdGlvbnM6IHR4bnNCYXRjaCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGxhaW4gYSBUcm9uIHRyYW5zYWN0aW9uIGZyb20gdHhIZXhcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgZXhwbGFpblRyYW5zYWN0aW9uKHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8VHJvblRyYW5zYWN0aW9uRXhwbGFuYXRpb24+IHtcbiAgICBjb25zdCB0eEhleCA9IHBhcmFtcy50eEhleCB8fCAocGFyYW1zLmhhbGZTaWduZWQgJiYgcGFyYW1zLmhhbGZTaWduZWQudHhIZXgpO1xuICAgIGlmICghdHhIZXggfHwgIXBhcmFtcy5mZWVJbmZvKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgZXhwbGFpbiB0eCBwYXJhbWV0ZXJzJyk7XG4gICAgfVxuICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIodGhpcy5nZXRDaGFpbigpKS5mcm9tKHR4SGV4KTtcbiAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGNvbnN0IG91dHB1dHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFtb3VudDogdHgub3V0cHV0c1swXS52YWx1ZS50b1N0cmluZygpLFxuICAgICAgICBhZGRyZXNzOiB0eC5vdXRwdXRzWzBdLmFkZHJlc3MsIC8vIFNob3VsZCB0dXJuIGl0IGludG8gYSByZWFkYWJsZSBmb3JtYXQsIGFrYSBiYXNlNThcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIGNvbnN0IGRpc3BsYXlPcmRlciA9IFtcbiAgICAgICdpZCcsXG4gICAgICAnb3V0cHV0QW1vdW50JyxcbiAgICAgICdjaGFuZ2VBbW91bnQnLFxuICAgICAgJ291dHB1dHMnLFxuICAgICAgJ2NoYW5nZU91dHB1dHMnLFxuICAgICAgJ2ZlZScsXG4gICAgICAndGltZXN0YW1wJyxcbiAgICAgICdleHBpcmF0aW9uJyxcbiAgICBdO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRpc3BsYXlPcmRlcixcbiAgICAgIGlkOiB0eC5pZCxcbiAgICAgIG91dHB1dHMsXG4gICAgICBvdXRwdXRBbW91bnQ6IG91dHB1dHNbMF0uYW1vdW50LFxuICAgICAgY2hhbmdlT3V0cHV0czogW10sIC8vIGFjY291bnQgYmFzZWQgZG9lcyBub3QgdXNlIGNoYW5nZSBvdXRwdXRzXG4gICAgICBjaGFuZ2VBbW91bnQ6ICcwJywgLy8gYWNjb3VudCBiYXNlIGRvZXMgbm90IG1ha2UgY2hhbmdlXG4gICAgICBmZWU6IHBhcmFtcy5mZWVJbmZvLFxuICAgICAgdGltZXN0YW1wOiB0eC52YWxpZEZyb20sXG4gICAgICBleHBpcmF0aW9uOiB0eC52YWxpZFRvLFxuICAgIH07XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgYXVkaXREZWNyeXB0ZWRLZXkocGFyYW1zOiBBdWRpdERlY3J5cHRlZEtleVBhcmFtcykge1xuICAgIHRocm93IG5ldyBNZXRob2ROb3RJbXBsZW1lbnRlZEVycm9yKCk7XG4gIH1cbn1cbiJdfQ==