@bitgo-beta/abstract-cosmos 0.0.0-semantic-release-managed

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 (56) hide show
  1. package/.eslintignore +5 -0
  2. package/.mocharc.yml +8 -0
  3. package/CHANGELOG.md +1056 -0
  4. package/LICENSE +191 -0
  5. package/README.md +1 -0
  6. package/dist/resources/MsgCompiled.d.ts +1212 -0
  7. package/dist/resources/MsgCompiled.js +2761 -0
  8. package/dist/src/cosmosCoin.d.ts +196 -0
  9. package/dist/src/cosmosCoin.d.ts.map +1 -0
  10. package/dist/src/cosmosCoin.js +718 -0
  11. package/dist/src/index.d.ts +3 -0
  12. package/dist/src/index.d.ts.map +1 -0
  13. package/dist/src/index.js +21 -0
  14. package/dist/src/lib/ContractCallBuilder.d.ts +13 -0
  15. package/dist/src/lib/ContractCallBuilder.d.ts.map +1 -0
  16. package/dist/src/lib/ContractCallBuilder.js +61 -0
  17. package/dist/src/lib/StakingActivateBuilder.d.ts +13 -0
  18. package/dist/src/lib/StakingActivateBuilder.d.ts.map +1 -0
  19. package/dist/src/lib/StakingActivateBuilder.js +61 -0
  20. package/dist/src/lib/StakingDeactivateBuilder.d.ts +13 -0
  21. package/dist/src/lib/StakingDeactivateBuilder.d.ts.map +1 -0
  22. package/dist/src/lib/StakingDeactivateBuilder.js +61 -0
  23. package/dist/src/lib/StakingRedelegateBuilder.d.ts +13 -0
  24. package/dist/src/lib/StakingRedelegateBuilder.d.ts.map +1 -0
  25. package/dist/src/lib/StakingRedelegateBuilder.js +61 -0
  26. package/dist/src/lib/StakingWithdrawRewardsBuilder.d.ts +13 -0
  27. package/dist/src/lib/StakingWithdrawRewardsBuilder.d.ts.map +1 -0
  28. package/dist/src/lib/StakingWithdrawRewardsBuilder.js +61 -0
  29. package/dist/src/lib/constants.d.ts +11 -0
  30. package/dist/src/lib/constants.d.ts.map +1 -0
  31. package/dist/src/lib/constants.js +14 -0
  32. package/dist/src/lib/iface.d.ts +109 -0
  33. package/dist/src/lib/iface.d.ts.map +1 -0
  34. package/dist/src/lib/iface.js +20 -0
  35. package/dist/src/lib/index.d.ts +14 -0
  36. package/dist/src/lib/index.d.ts.map +1 -0
  37. package/dist/src/lib/index.js +63 -0
  38. package/dist/src/lib/keyPair.d.ts +18 -0
  39. package/dist/src/lib/keyPair.d.ts.map +1 -0
  40. package/dist/src/lib/keyPair.js +51 -0
  41. package/dist/src/lib/transaction.d.ts +64 -0
  42. package/dist/src/lib/transaction.d.ts.map +1 -0
  43. package/dist/src/lib/transaction.js +333 -0
  44. package/dist/src/lib/transactionBuilder.d.ts +86 -0
  45. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  46. package/dist/src/lib/transactionBuilder.js +181 -0
  47. package/dist/src/lib/transferBuilder.d.ts +13 -0
  48. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  49. package/dist/src/lib/transferBuilder.js +61 -0
  50. package/dist/src/lib/utils.d.ts +351 -0
  51. package/dist/src/lib/utils.d.ts.map +1 -0
  52. package/dist/src/lib/utils.js +856 -0
  53. package/dist/tsconfig.tsbuildinfo +1 -0
  54. package/package.json +60 -0
  55. package/resources/MsgCompiled.d.ts +1212 -0
  56. package/resources/MsgCompiled.js +2761 -0
@@ -0,0 +1,718 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.CosmosCoin = void 0;
40
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
41
+ const secp256k1_1 = require("@bitgo-beta/secp256k1");
42
+ const bignumber_js_1 = require("bignumber.js");
43
+ const buffer_1 = require("buffer");
44
+ const crypto_1 = require("crypto");
45
+ const _ = __importStar(require("lodash"));
46
+ const querystring = __importStar(require("querystring"));
47
+ const request = __importStar(require("superagent"));
48
+ const url = __importStar(require("url"));
49
+ const constants_1 = require("./lib/constants");
50
+ const utils_1 = __importDefault(require("./lib/utils"));
51
+ const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
52
+ class CosmosCoin extends sdk_core_1.BaseCoin {
53
+ constructor(bitgo, staticsCoin) {
54
+ super(bitgo);
55
+ if (!staticsCoin) {
56
+ throw new Error('missing required constructor parameter staticsCoin');
57
+ }
58
+ this._staticsCoin = staticsCoin;
59
+ }
60
+ static createInstance(bitgo, staticsCoin) {
61
+ return new CosmosCoin(bitgo, staticsCoin);
62
+ }
63
+ /**
64
+ * Creates an instance of TransactionBuilderFactory for the coin specific sdk
65
+ */
66
+ getBuilder() {
67
+ throw new Error('Method not implemented.');
68
+ }
69
+ /** @inheritDoc **/
70
+ getBaseFactor() {
71
+ throw new Error('Method not implemented');
72
+ }
73
+ /** @inheritDoc **/
74
+ getChain() {
75
+ return this._staticsCoin.name;
76
+ }
77
+ /** @inheritDoc **/
78
+ getFamily() {
79
+ return this._staticsCoin.family;
80
+ }
81
+ /** @inheritDoc **/
82
+ getFullName() {
83
+ return this._staticsCoin.fullName;
84
+ }
85
+ /** @inheritDoc */
86
+ supportsTss() {
87
+ return true;
88
+ }
89
+ /** inherited doc */
90
+ getDefaultMultisigType() {
91
+ return sdk_core_1.multisigTypes.tss;
92
+ }
93
+ /** @inheritDoc **/
94
+ getMPCAlgorithm() {
95
+ return 'ecdsa';
96
+ }
97
+ /** @inheritDoc **/
98
+ isValidPub(pub) {
99
+ return utils_1.default.isValidPublicKey(pub);
100
+ }
101
+ /** @inheritDoc **/
102
+ isValidPrv(prv) {
103
+ return utils_1.default.isValidPrivateKey(prv);
104
+ }
105
+ isValidAddress(address) {
106
+ throw new Error('Method not implemented.');
107
+ }
108
+ /**
109
+ * Builds a funds recovery transaction without BitGo
110
+ * @param {RecoveryOptions} params parameters needed to construct and
111
+ * (maybe) sign the transaction
112
+ *
113
+ * @returns {CosmosLikeCoinRecoveryOutput} the serialized transaction hex string and index
114
+ * of the address being swept
115
+ */
116
+ async recover(params) {
117
+ const isUnsignedSweep = this.isUnsignedSweep(params);
118
+ this.validateRecoveryParams(params, isUnsignedSweep);
119
+ const { senderAddress, publicKey, keyShares } = await this.getSenderDetails(params, isUnsignedSweep);
120
+ const [chainId, accountDetails, balances] = await Promise.all([
121
+ this.getChainId(),
122
+ this.getAccountDetails(senderAddress),
123
+ this.getAccountBalance(senderAddress),
124
+ ]);
125
+ const { actualBalance, remainingBalances } = this.processBalances(balances);
126
+ const messages = this.buildTransactionMessages(senderAddress, params.recoveryDestination, actualBalance, remainingBalances);
127
+ return this.buildAndSignTransaction({
128
+ messages,
129
+ chainId,
130
+ accountDetails,
131
+ publicKey: publicKey || '',
132
+ isUnsignedSweep,
133
+ keyShares,
134
+ });
135
+ }
136
+ /**
137
+ * Validates the recovery parameters
138
+ */
139
+ validateRecoveryParams(params, isUnsignedSweep) {
140
+ if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
141
+ throw new Error('invalid recoveryDestination');
142
+ }
143
+ if (!isUnsignedSweep) {
144
+ if (!params.userKey)
145
+ throw new Error('missing userKey');
146
+ if (!params.backupKey)
147
+ throw new Error('missing backupKey');
148
+ if (!params.walletPassphrase)
149
+ throw new Error('missing wallet passphrase');
150
+ }
151
+ }
152
+ /**
153
+ * Checks if this is an unsigned sweep operation
154
+ */
155
+ isUnsignedSweep(params) {
156
+ return !params.userKey && !params.backupKey && !params.walletPassphrase;
157
+ }
158
+ /**
159
+ * Gets sender details including address, public key and key shares
160
+ */
161
+ async getSenderDetails(params, isUnsignedSweep) {
162
+ const MPC = new sdk_core_1.Ecdsa();
163
+ if (isUnsignedSweep) {
164
+ return {
165
+ senderAddress: params.rootAddress,
166
+ publicKey: MPC.deriveUnhardened(params.bitgoKey || '', constants_1.ROOT_PATH).slice(0, 66),
167
+ };
168
+ }
169
+ const keyShares = await this.getKeyShares(params);
170
+ const publicKey = MPC.deriveUnhardened(keyShares.commonKeyChain, constants_1.ROOT_PATH).slice(0, 66);
171
+ return {
172
+ senderAddress: this.getAddressFromPublicKey(publicKey),
173
+ publicKey,
174
+ keyShares,
175
+ };
176
+ }
177
+ /**
178
+ * Gets key shares from recovery parameters
179
+ */
180
+ async getKeyShares(params) {
181
+ if (!params.userKey || !params.backupKey || !params.walletPassphrase) {
182
+ throw new Error('Missing required key parameters');
183
+ }
184
+ const userKey = params.userKey.replace(/\s/g, '');
185
+ const backupKey = params.backupKey.replace(/\s/g, '');
186
+ const walletPassphrase = params.walletPassphrase;
187
+ if (!userKey || !backupKey) {
188
+ throw new Error('Invalid key format');
189
+ }
190
+ return await sdk_core_1.ECDSAUtils.getMpcV2RecoveryKeyShares(userKey, backupKey, walletPassphrase);
191
+ }
192
+ /**
193
+ * Processes account balances and validates sufficient funds
194
+ */
195
+ processBalances(balances) {
196
+ if (!balances?.length) {
197
+ throw new Error('No balance found on account');
198
+ }
199
+ const denomination = this.getDenomination();
200
+ if (!denomination) {
201
+ throw new Error('Invalid denomination');
202
+ }
203
+ let nativeBalance = new bignumber_js_1.BigNumber(0);
204
+ const remainingBalances = [];
205
+ const gasAmountDetails = this.getGasAmountDetails();
206
+ if (!gasAmountDetails?.gasAmount) {
207
+ throw new Error('Invalid gas amount');
208
+ }
209
+ const gasAmount = new bignumber_js_1.BigNumber(gasAmountDetails.gasAmount);
210
+ balances.forEach((balance) => {
211
+ if (!balance.amount) {
212
+ throw new Error('Invalid balance amount');
213
+ }
214
+ if (balance.denom === denomination) {
215
+ nativeBalance = new bignumber_js_1.BigNumber(balance.amount);
216
+ }
217
+ else {
218
+ remainingBalances.push(balance);
219
+ }
220
+ });
221
+ const actualBalance = nativeBalance.minus(gasAmount);
222
+ if (actualBalance.isLessThanOrEqualTo(0)) {
223
+ throw new Error('Did not have enough funds to recover');
224
+ }
225
+ return { nativeBalance, remainingBalances, actualBalance };
226
+ }
227
+ /**
228
+ * Builds transaction messages for all balances
229
+ */
230
+ buildTransactionMessages(senderAddress, recoveryDestination, actualBalance, remainingBalances) {
231
+ const nativeSendMessage = {
232
+ fromAddress: senderAddress,
233
+ toAddress: recoveryDestination,
234
+ amount: [
235
+ {
236
+ denom: this.getDenomination(),
237
+ amount: actualBalance.toFixed(),
238
+ },
239
+ ],
240
+ };
241
+ const otherTokenMessages = remainingBalances.map((balance) => ({
242
+ fromAddress: senderAddress,
243
+ toAddress: recoveryDestination,
244
+ amount: [balance],
245
+ }));
246
+ return [...otherTokenMessages, nativeSendMessage];
247
+ }
248
+ /**
249
+ * Builds and signs the transaction
250
+ */
251
+ async buildAndSignTransaction(params) {
252
+ if (!params.chainId) {
253
+ throw new Error('Invalid chain ID');
254
+ }
255
+ const [accountNumber, sequenceNo] = params.accountDetails;
256
+ if (!accountNumber || !sequenceNo) {
257
+ throw new Error('Invalid account details');
258
+ }
259
+ const denomination = this.getDenomination();
260
+ const gasAmountDetails = this.getGasAmountDetails();
261
+ if (!denomination || !gasAmountDetails?.gasAmount || !gasAmountDetails?.gasLimit) {
262
+ throw new Error('Invalid gas configuration');
263
+ }
264
+ const gasBudget = {
265
+ amount: [
266
+ {
267
+ denom: denomination,
268
+ amount: gasAmountDetails.gasAmount,
269
+ },
270
+ ],
271
+ gasLimit: gasAmountDetails.gasLimit,
272
+ };
273
+ const txnBuilder = this.getBuilder()
274
+ .getTransferBuilder()
275
+ .messages(params.messages)
276
+ .gasBudget(gasBudget)
277
+ .sequence(Number(sequenceNo))
278
+ .accountNumber(Number(accountNumber))
279
+ .chainId(params.chainId)
280
+ .publicKey(params.publicKey);
281
+ const unsignedTransaction = (await txnBuilder.build());
282
+ if (!unsignedTransaction) {
283
+ throw new Error('Failed to build unsigned transaction');
284
+ }
285
+ if (params.isUnsignedSweep) {
286
+ return {
287
+ signableHex: unsignedTransaction.signablePayload.toString('hex'),
288
+ };
289
+ }
290
+ return this.signTransactionWithMpc(unsignedTransaction, txnBuilder, params.keyShares, params.publicKey);
291
+ }
292
+ /**
293
+ * Signs the transaction with MPC
294
+ */
295
+ /**
296
+ * Signs the transaction using MPC (Multi-Party Computation)
297
+ * @param unsignedTransaction The unsigned transaction to sign
298
+ * @param txnBuilder The transaction builder instance
299
+ * @param keyShares The key shares for MPC signing
300
+ * @param publicKey The public key for verification
301
+ * @returns The signed transaction output
302
+ * @throws Error if validation fails or signing process encounters an error
303
+ */
304
+ async signTransactionWithMpc(unsignedTransaction, txnBuilder, keyShares, publicKey) {
305
+ // Validate inputs
306
+ if (!unsignedTransaction?.signablePayload) {
307
+ throw new Error('Invalid unsigned transaction');
308
+ }
309
+ if (!keyShares?.userKeyShare || !keyShares?.backupKeyShare || !keyShares?.commonKeyChain) {
310
+ throw new Error('Invalid key shares');
311
+ }
312
+ if (!publicKey) {
313
+ throw new Error('Invalid public key');
314
+ }
315
+ try {
316
+ const MPC = new sdk_core_1.Ecdsa();
317
+ const message = unsignedTransaction.signablePayload;
318
+ // Get hash function and compute message hash
319
+ const hashFunction = utils_1.default.getHashFunction() || (0, crypto_1.createHash)('sha256');
320
+ if (!hashFunction) {
321
+ throw new Error('Failed to get hash function');
322
+ }
323
+ const messageHash = hashFunction.update(message).digest();
324
+ // Sign the transaction
325
+ const signature = await sdk_core_1.ECDSAUtils.signRecoveryMpcV2(messageHash, keyShares.userKeyShare, keyShares.backupKeyShare, keyShares.commonKeyChain);
326
+ // Verify the signature
327
+ const signableHex = unsignedTransaction.signablePayload.toString('hex');
328
+ const signableBuffer = buffer_1.Buffer.from(signableHex, 'hex');
329
+ MPC.verify(signableBuffer, signature, this.getHashFunction());
330
+ // Get cosmos key pair and validate
331
+ const cosmosKeyPair = this.getKeyPair(publicKey);
332
+ if (!cosmosKeyPair) {
333
+ throw new Error('Invalid cosmos key pair');
334
+ }
335
+ // Add signature to transaction
336
+ txnBuilder.addSignature({ pub: cosmosKeyPair.getKeys().pub }, buffer_1.Buffer.from(signature.r + signature.s, 'hex'));
337
+ // Build final transaction
338
+ const signedTransaction = await txnBuilder.build();
339
+ if (!signedTransaction) {
340
+ throw new Error('Failed to build signed transaction');
341
+ }
342
+ return {
343
+ serializedTx: signedTransaction.toBroadcastFormat(),
344
+ };
345
+ }
346
+ catch (error) {
347
+ throw new Error(`Failed to sign transaction: ${error.message}`);
348
+ }
349
+ }
350
+ /**
351
+ * Builds a redelegate transaction
352
+ * @param {RecoveryOptions} params parameters needed to construct and
353
+ * (maybe) sign the transaction
354
+ *
355
+ * @returns {CosmosLikeCoinRecoveryOutput} the serialized transaction hex string
356
+ */
357
+ async redelegate(params) {
358
+ if (!params.validatorSrcAddress || !this.isValidAddress(params.validatorSrcAddress)) {
359
+ throw new Error('invalid validatorSrcAddress');
360
+ }
361
+ if (!params.validatorDstAddress || !this.isValidAddress(params.validatorDstAddress)) {
362
+ throw new Error('invalid validatorDstAddress');
363
+ }
364
+ if (!params.userKey) {
365
+ throw new Error('missing userKey');
366
+ }
367
+ if (!params.backupKey) {
368
+ throw new Error('missing backupKey');
369
+ }
370
+ if (!params.walletPassphrase) {
371
+ throw new Error('missing wallet passphrase');
372
+ }
373
+ if (!params.amountToRedelegate) {
374
+ throw new Error('missing amountToRedelegate');
375
+ }
376
+ const userKey = params.userKey.replace(/\s/g, '');
377
+ const backupKey = params.backupKey.replace(/\s/g, '');
378
+ const { userKeyShare, backupKeyShare, commonKeyChain } = await sdk_core_1.ECDSAUtils.getMpcV2RecoveryKeyShares(userKey, backupKey, params.walletPassphrase); // baseAddress is not extracted
379
+ const MPC = new sdk_core_1.Ecdsa();
380
+ const chainId = await this.getChainId();
381
+ const publicKey = MPC.deriveUnhardened(commonKeyChain, constants_1.ROOT_PATH).slice(0, 66);
382
+ const senderAddress = this.getAddressFromPublicKey(publicKey);
383
+ const [accountNumber, sequenceNo] = await this.getAccountDetails(senderAddress);
384
+ const gasBudget = {
385
+ amount: [{ denom: this.getDenomination(), amount: this.getGasAmountDetails().gasAmount }],
386
+ gasLimit: this.getGasAmountDetails().gasLimit,
387
+ };
388
+ const amount = {
389
+ denom: this.getDenomination(),
390
+ amount: new bignumber_js_1.BigNumber(params.amountToRedelegate).toFixed(),
391
+ };
392
+ const sendMessage = [
393
+ {
394
+ delegatorAddress: senderAddress,
395
+ validatorSrcAddress: params.validatorSrcAddress,
396
+ validatorDstAddress: params.validatorDstAddress,
397
+ amount: amount,
398
+ },
399
+ ];
400
+ const txnBuilder = this.getBuilder().getStakingRedelegateBuilder();
401
+ txnBuilder
402
+ .messages(sendMessage)
403
+ .gasBudget(gasBudget)
404
+ .publicKey(publicKey)
405
+ .sequence(Number(sequenceNo))
406
+ .accountNumber(Number(accountNumber))
407
+ .chainId(chainId);
408
+ const unsignedTransaction = (await txnBuilder.build());
409
+ let serializedTx = unsignedTransaction.toBroadcastFormat();
410
+ const signableHex = unsignedTransaction.signablePayload.toString('hex');
411
+ const message = unsignedTransaction.signablePayload;
412
+ const messageHash = (utils_1.default.getHashFunction() || (0, crypto_1.createHash)('sha256')).update(message).digest();
413
+ const signature = await sdk_core_1.ECDSAUtils.signRecoveryMpcV2(messageHash, userKeyShare, backupKeyShare, commonKeyChain);
414
+ const signableBuffer = buffer_1.Buffer.from(signableHex, 'hex');
415
+ MPC.verify(signableBuffer, signature, this.getHashFunction());
416
+ const cosmosKeyPair = this.getKeyPair(publicKey);
417
+ txnBuilder.addSignature({ pub: cosmosKeyPair.getKeys().pub }, buffer_1.Buffer.from(signature.r + signature.s, 'hex'));
418
+ const signedTransaction = await txnBuilder.build();
419
+ serializedTx = signedTransaction.toBroadcastFormat();
420
+ return { serializedTx: serializedTx };
421
+ }
422
+ /** @inheritDoc **/
423
+ async verifyTransaction(params) {
424
+ let totalAmount = new bignumber_js_1.BigNumber(0);
425
+ const { txPrebuild, txParams } = params;
426
+ const rawTx = txPrebuild.txHex;
427
+ if (!rawTx) {
428
+ throw new Error('missing required tx prebuild property txHex');
429
+ }
430
+ const transaction = await this.getBuilder().from(rawTx).build();
431
+ const explainedTx = transaction.explainTransaction();
432
+ if (txParams.recipients && txParams.recipients.length > 0) {
433
+ const filteredRecipients = txParams.recipients?.map((recipient) => _.pick(recipient, ['address', 'amount']));
434
+ const filteredOutputs = explainedTx.outputs.map((output) => _.pick(output, ['address', 'amount']));
435
+ if (!_.isEqual(filteredOutputs, filteredRecipients)) {
436
+ throw new Error('Tx outputs does not match with expected txParams recipients');
437
+ }
438
+ // WithdrawDelegatorRewards and ContractCall transaction don't have amount
439
+ if (transaction.type !== sdk_core_1.TransactionType.StakingWithdraw && transaction.type !== sdk_core_1.TransactionType.ContractCall) {
440
+ for (const recipients of txParams.recipients) {
441
+ totalAmount = totalAmount.plus(recipients.amount);
442
+ }
443
+ if (!totalAmount.isEqualTo(explainedTx.outputAmount)) {
444
+ throw new Error('Tx total amount does not match with expected total amount field');
445
+ }
446
+ }
447
+ }
448
+ return true;
449
+ }
450
+ /** @inheritDoc **/
451
+ async explainTransaction(options) {
452
+ if (!options.txHex) {
453
+ throw new Error('missing required txHex parameter');
454
+ }
455
+ try {
456
+ const transactionBuilder = this.getBuilder().from(options.txHex);
457
+ const transaction = await transactionBuilder.build();
458
+ return transaction.explainTransaction();
459
+ }
460
+ catch (e) {
461
+ throw new Error('Invalid transaction: ' + e.message);
462
+ }
463
+ }
464
+ /**
465
+ * Sign a transaction with a single private key
466
+ * @param params parameters in the form of { txPrebuild: {txHex}, prv }
467
+ * @returns signed transaction in the form of { txHex }
468
+ */
469
+ async signTransaction(params) {
470
+ const txHex = params?.txPrebuild?.txHex;
471
+ const privateKey = params?.prv;
472
+ if (!txHex) {
473
+ throw new sdk_core_1.SigningError('missing required txPrebuild parameter: params.txPrebuild.txHex');
474
+ }
475
+ if (!privateKey) {
476
+ throw new sdk_core_1.SigningError('missing required prv parameter: params.prv');
477
+ }
478
+ const txBuilder = this.getBuilder().from(params.txPrebuild.txHex);
479
+ txBuilder.sign({ key: params.prv });
480
+ const transaction = await txBuilder.build();
481
+ if (!transaction) {
482
+ throw new sdk_core_1.SigningError('Failed to build signed transaction');
483
+ }
484
+ const serializedTx = transaction.toBroadcastFormat();
485
+ return {
486
+ txHex: serializedTx,
487
+ };
488
+ }
489
+ /** @inheritDoc **/
490
+ async parseTransaction(params) {
491
+ const transactionExplanation = await this.explainTransaction({ txHex: params.txHex });
492
+ if (!transactionExplanation) {
493
+ throw new Error('Invalid transaction');
494
+ }
495
+ if (transactionExplanation.outputs.length <= 0) {
496
+ return {
497
+ inputs: [],
498
+ outputs: [],
499
+ };
500
+ }
501
+ const senderAddress = transactionExplanation.outputs[0].address;
502
+ const feeAmount = new bignumber_js_1.BigNumber(transactionExplanation.fee.fee === '' ? '0' : transactionExplanation.fee.fee);
503
+ const inputs = [
504
+ {
505
+ address: senderAddress,
506
+ amount: new bignumber_js_1.BigNumber(transactionExplanation.outputAmount).plus(feeAmount).toFixed(),
507
+ },
508
+ ];
509
+ const outputs = transactionExplanation.outputs.map((output) => {
510
+ return {
511
+ address: output.address,
512
+ amount: new bignumber_js_1.BigNumber(output.amount).toFixed(),
513
+ };
514
+ });
515
+ return {
516
+ inputs,
517
+ outputs,
518
+ };
519
+ }
520
+ /**
521
+ * Get the public node url from the Environments constant we have defined
522
+ */
523
+ getPublicNodeUrl() {
524
+ throw new Error('Method not implemented.');
525
+ }
526
+ /**
527
+ * Get account number from public node
528
+ */
529
+ async getAccountFromNode(senderAddress) {
530
+ const nodeUrl = this.getPublicNodeUrl();
531
+ const getAccountPath = '/cosmos/auth/v1beta1/accounts/';
532
+ const fullEndpoint = nodeUrl + getAccountPath + senderAddress;
533
+ try {
534
+ return await request.get(fullEndpoint).send();
535
+ }
536
+ catch (e) {
537
+ console.debug(e);
538
+ }
539
+ throw new Error(`Unable to call endpoint ${getAccountPath + senderAddress} from node: ${nodeUrl}`);
540
+ }
541
+ /**
542
+ * Get balance from public node
543
+ */
544
+ async getBalanceFromNode(senderAddress) {
545
+ const nodeUrl = this.getPublicNodeUrl();
546
+ const getBalancePath = '/cosmos/bank/v1beta1/balances/';
547
+ const fullEndpoint = nodeUrl + getBalancePath + senderAddress;
548
+ try {
549
+ return await request.get(fullEndpoint).send();
550
+ }
551
+ catch (e) {
552
+ console.debug(e);
553
+ }
554
+ throw new Error(`Unable to call endpoint ${getBalancePath + senderAddress} from node: ${nodeUrl}`);
555
+ }
556
+ /**
557
+ * Get chain id from public node
558
+ */
559
+ async getChainIdFromNode() {
560
+ const nodeUrl = this.getPublicNodeUrl();
561
+ const getLatestBlockPath = '/cosmos/base/tendermint/v1beta1/blocks/latest';
562
+ const fullEndpoint = nodeUrl + getLatestBlockPath;
563
+ try {
564
+ return await request.get(fullEndpoint).send();
565
+ }
566
+ catch (e) {
567
+ console.debug(e);
568
+ }
569
+ throw new Error(`Unable to call endpoint ${getLatestBlockPath} from node: ${nodeUrl}`);
570
+ }
571
+ /**
572
+ * Helper to fetch account balance
573
+ */
574
+ async getAccountBalance(senderAddress) {
575
+ const response = await this.getBalanceFromNode(senderAddress);
576
+ if (response.status !== 200) {
577
+ throw new Error('Account not found');
578
+ }
579
+ return response.body.balances;
580
+ }
581
+ /**
582
+ * Helper to fetch chainId
583
+ */
584
+ async getChainId() {
585
+ const response = await this.getChainIdFromNode();
586
+ if (response.status !== 200) {
587
+ throw new Error('Account not found');
588
+ }
589
+ return response.body.block.header.chain_id;
590
+ }
591
+ /**
592
+ * Helper to fetch account number
593
+ */
594
+ async getAccountDetails(senderAddress) {
595
+ const response = await this.getAccountFromNode(senderAddress);
596
+ if (response.status !== 200) {
597
+ throw new Error('Account not found');
598
+ }
599
+ return [response.body.account.account_number, response.body.account.sequence];
600
+ }
601
+ /** @inheritDoc **/
602
+ generateKeyPair(seed) {
603
+ if (!seed) {
604
+ // An extended private key has both a normal 256 bit private key and a 256
605
+ // bit chain code, both of which must be random. 512 bits is therefore the
606
+ // maximum entropy and gives us maximum security against cracking.
607
+ seed = (0, crypto_1.randomBytes)(512 / 8);
608
+ }
609
+ const extendedKey = secp256k1_1.bip32.fromSeed(seed);
610
+ return {
611
+ pub: extendedKey.neutered().toBase58(),
612
+ prv: extendedKey.toBase58(),
613
+ };
614
+ }
615
+ /**
616
+ * Retrieves the address from a public key.
617
+ * @param {string} pubKey - The public key.
618
+ * @returns {string} The corresponding address.
619
+ */
620
+ getAddressFromPublicKey(pubKey) {
621
+ throw new Error('Method not implemented');
622
+ }
623
+ /** @inheritDoc **/
624
+ async isWalletAddress(params) {
625
+ const addressDetails = this.getAddressDetails(params.address);
626
+ if (!this.isValidAddress(addressDetails.address)) {
627
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${addressDetails.address}`);
628
+ }
629
+ const rootAddress = params.coinSpecific.rootAddress;
630
+ if (addressDetails.address !== rootAddress) {
631
+ throw new sdk_core_1.UnexpectedAddressError(`address validation failure: ${addressDetails.address} vs ${rootAddress}`);
632
+ }
633
+ return true;
634
+ }
635
+ /** @inheritDoc **/
636
+ getHashFunction() {
637
+ return utils_1.default.getHashFunction();
638
+ }
639
+ /**
640
+ * Process address into address and memo id
641
+ *
642
+ * @param address the address
643
+ * @returns object containing address and memo id
644
+ */
645
+ getAddressDetails(address) {
646
+ const destinationDetails = url.parse(address);
647
+ const destinationAddress = destinationDetails.pathname || '';
648
+ // address doesn't have a memo id
649
+ if (destinationDetails.pathname === address) {
650
+ return {
651
+ address: address,
652
+ memoId: undefined,
653
+ };
654
+ }
655
+ if (!destinationDetails.query) {
656
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
657
+ }
658
+ const queryDetails = querystring.parse(destinationDetails.query);
659
+ if (!queryDetails.memoId) {
660
+ // if there are more properties, the query details need to contain the memo id property
661
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
662
+ }
663
+ if (Array.isArray(queryDetails.memoId)) {
664
+ throw new sdk_core_1.InvalidAddressError(`memoId may only be given at most once, but found ${queryDetails.memoId.length} instances in address ${address}`);
665
+ }
666
+ if (Array.isArray(queryDetails.memoId) && queryDetails.memoId.length !== 1) {
667
+ // valid addresses can only contain one memo id
668
+ throw new sdk_core_1.InvalidAddressError(`invalid address '${address}', must contain exactly one memoId`);
669
+ }
670
+ const [memoId] = _.castArray(queryDetails.memoId) || undefined;
671
+ if (!this.isValidMemoId(memoId)) {
672
+ throw new sdk_core_1.InvalidMemoIdError(`invalid address: '${address}', memoId is not valid`);
673
+ }
674
+ return {
675
+ address: destinationAddress,
676
+ memoId,
677
+ };
678
+ }
679
+ /**
680
+ * Return boolean indicating whether a memo id is valid
681
+ *
682
+ * @param memoId memo id
683
+ * @returns true if memo id is valid
684
+ */
685
+ isValidMemoId(memoId) {
686
+ return utils_1.default.isValidMemoId(memoId);
687
+ }
688
+ /**
689
+ * Helper method to return the respective coin's base unit
690
+ */
691
+ getDenomination() {
692
+ throw new Error('Method not implemented');
693
+ }
694
+ /**
695
+ * Helper method to fetch gas amount details for respective coin
696
+ */
697
+ getGasAmountDetails() {
698
+ throw new Error('Method not implemented');
699
+ }
700
+ /**
701
+ * Helper method to get key pair for individual coin
702
+ * @param publicKey
703
+ */
704
+ getKeyPair(publicKey) {
705
+ throw new Error('Method not implemented');
706
+ }
707
+ /** @inheritDoc **/
708
+ auditDecryptedKey({ multiSigType, publicKey, prv }) {
709
+ if (multiSigType !== 'tss') {
710
+ throw new Error('Unsupported multiSigType');
711
+ }
712
+ else {
713
+ (0, sdk_lib_mpc_1.auditEcdsaPrivateKey)(prv, publicKey);
714
+ }
715
+ }
716
+ }
717
+ exports.CosmosCoin = CosmosCoin;
718
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zbW9zQ29pbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3Ntb3NDb2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1EQXVCOEI7QUFFOUIscURBQThDO0FBRTlDLCtDQUF5QztBQUN6QyxtQ0FBZ0M7QUFDaEMsbUNBQXVEO0FBQ3ZELDBDQUE0QjtBQUM1Qix5REFBMkM7QUFDM0Msb0RBQXNDO0FBQ3RDLHlDQUEyQjtBQWUzQiwrQ0FBNEM7QUFDNUMsd0RBQWdDO0FBQ2hDLHlEQUErRDtBQWlCL0QsTUFBYSxVQUFrQyxTQUFRLG1CQUFRO0lBRTdELFlBQXNCLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUN4RSxDQUFDO1FBRUQsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUM7SUFDbEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBZ0IsRUFBRSxXQUF1QztRQUM3RSxPQUFPLElBQUksVUFBVSxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxVQUFVO1FBQ1IsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxtQkFBbUI7SUFDbkIsYUFBYTtRQUNYLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsbUJBQW1CO0lBQ25CLFFBQVE7UUFDTixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDO0lBQ2hDLENBQUM7SUFFRCxtQkFBbUI7SUFDbkIsU0FBUztRQUNQLE9BQU8sSUFBSSxDQUFDLFlB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QUVEOzs7T0FHRztJQUNILFVBQVUsQ0FBQyxTQUFpQjtRQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVELG1CQUFtQjtJQUNuQixpQkFBaUIsQ0FBQyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUEyQjtRQUN6RSxJQUFJLFlBQVksS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDOUMsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFBLGtDQUFvQixFQUFDLEdBQWEsRUFBRSxTQUFtQixDQUFDLENBQUM7UUFDM0QsQ0FBQztJQUNILENBQUM7Q0FDRjtBQWx5QkQsZ0NBa3lCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEF1ZGl0RGVjcnlwdGVkS2V5UGFyYW1zLFxuICBCYXNlQ29pbixcbiAgQmFzZVRyYW5zYWN0aW9uLFxuICBCaXRHb0Jhc2UsXG4gIEVjZHNhLFxuICBFQ0RTQVV0aWxzLFxuICBFeHBsYW5hdGlvblJlc3VsdCxcbiAgSW52YWxpZEFkZHJlc3NFcnJvcixcbiAgSW52YWxpZE1lbW9JZEVycm9yLFxuICBLZXlQYWlyLFxuICBNUENBbGdvcml0aG0sXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnbmluZ0Vycm9yLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBUcmFuc2FjdGlvblR5cGUsXG4gIFVuZXhwZWN0ZWRBZGRyZXNzRXJyb3IsXG4gIFZlcmlmeUFkZHJlc3NPcHRpb25zLFxuICBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IEJhc2VDb2luIGFzIFN0YXRpY3NCYXNlQ29pbiwgQ29pbkZhbWlseSB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgYmlwMzIgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0IHsgQ29pbiB9IGZyb20gJ0Bjb3NtanMvc3RhcmdhdGUnO1xuaW1wb3J0IHsgQmlnTnVtYmVyIH0gZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5pbXBvcnQgeyBjcmVhdGVIYXNoLCBIYXNoLCByYW5kb21CeXRlcyB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBxdWVyeXN0cmluZyBmcm9tICdxdWVyeXN0cmluZyc7XG5pbXBvcnQgKiBhcyByZXF1ZXN0IGZyb20gJ3N1cGVyYWdlbnQnO1xuaW1wb3J0ICogYXMgdXJsIGZyb20gJ3VybCc7XG5pbXBvcnQge1xuICBDb3Ntb3NLZXlQYWlyLFxuICBDb3Ntb3NMaWtlQ29pblJlY292ZXJ5T3V0cHV0LFxuICBDb3Ntb3NUcmFuc2FjdGlvbixcbiAgRmVlRGF0YSxcbiAgR2FzQW1vdW50RGV0YWlscyxcbiAgUmVjb3ZlcnlPcHRpb25zLFxuICBSZWRlbGVnYXRlTWVzc2FnZSxcbiAgU2VuZE1lc3NhZ2UsXG4gIENvc21vc1RyYW5zYWN0aW9uQnVpbGRlcixcbiAgS2V5U2hhcmVzLFxuICBUcmFuc2FjdGlvbkJ1aWxkUGFyYW1zLFxuICBCYWxhbmNlUmVzdWx0LFxufSBmcm9tICcuL2xpYic7XG5pbXBvcnQgeyBST09UX1BBVEggfSBmcm9tICcuL2xpYi9jb25zdGFudHMnO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4vbGliL3V0aWxzJztcbmltcG9ydCB7IGF1ZGl0RWNkc2FQcml2YXRlS2V5IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWxpYi1tcGMnO1xuXG4vKipcbiAqIENvc21vcyBhY2NvdW50cyBzdXBwb3J0IG1lbW8gSWQgYmFzZWQgYWRkcmVzc2VzXG4gKi9cbmludGVyZmFjZSBBZGRyZXNzRGV0YWlscyB7XG4gIGFkZHJlc3M6IHN0cmluZztcbiAgbWVtb0lkPzogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIENvc21vcyBhY2NvdW50cyBzdXBwb3J0IG1lbW8gSWQgYmFzZWQgYWRkcmVzc2VzXG4gKi9cbmludGVyZmFjZSBDb3Ntb3NDb2luU3BlY2lmaWMge1xuICByb290QWRkcmVzczogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgQ29zbW9zQ29pbjxDdXN0b21NZXNzYWdlID0gbmV2ZXI+IGV4dGVuZHMgQmFzZUNvaW4ge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX3N0YXRpY3NDb2luOiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+O1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlSW5zdGFuY2UoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KTogQmFzZUNvaW4ge1xuICAgIHJldHVybiBuZXcgQ29zbW9zQ29pbihiaXRnbywgc3RhdGljc0NvaW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSBmb3IgdGhlIGNvaW4gc3BlY2lmaWMgc2RrXG4gICAqL1xuICBnZXRCdWlsZGVyKCk6IGFueSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICBnZXRCYXNlRmFjdG9yKCk6IHN0cmluZyB8IG51bWJlciB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKiovXG4gIGdldENoYWluKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRpY3NDb2luLm5hbWU7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKiovXG4gIGdldEZhbWlseSgpOiBDb2luRmFtaWx5IHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4uZmFtaWx5O1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICBnZXRGdWxsTmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9zdGF0aWNzQ29pbi5mdWxsTmFtZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBpbmhlcml0ZWQgZG9jICovXG4gIGdldERlZmF1bHRNdWx0aXNpZ1R5cGUoKTogTXVsdGlzaWdUeXBlIHtcbiAgICByZXR1cm4gbXVsdGlzaWdUeXBlcy50c3M7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKiovXG4gIGdldE1QQ0FsZ29yaXRobSgpOiBNUENBbGdvcml0aG0ge1xuICAgIHJldHVybiAnZWNkc2EnO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkocHViKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqKi9cbiAgaXNWYWxpZFBydihwcnY6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB1dGlscy5pc1ZhbGlkUHJpdmF0ZUtleShwcnYpO1xuICB9XG5cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGZ1bmRzIHJlY292ZXJ5IHRyYW5zYWN0aW9uIHdpdGhvdXQgQml0R29cbiAgICogQHBhcmFtIHtSZWNvdmVyeU9wdGlvbnN9IHBhcmFtcyBwYXJhbWV0ZXJzIG5lZWRlZCB0byBjb25zdHJ1Y3QgYW5kXG4gICAqIChtYXliZSkgc2lnbiB0aGUgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHJldHVybnMge0Nvc21vc0xpa2VDb2luUmVjb3ZlcnlPdXRwdXR9IHRoZSBzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGhleCBzdHJpbmcgYW5kIGluZGV4XG4gICAqIG9mIHRoZSBhZGRyZXNzIGJlaW5nIHN3ZXB0XG4gICAqL1xuICBhc3luYyByZWNvdmVyKHBhcmFtczogUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxDb3Ntb3NMaWtlQ29pblJlY292ZXJ5T3V0cHV0PiB7XG4gICAgY29uc3QgaXNVbnNpZ25lZFN3ZWVwID0gdGhpcy5pc1Vuc2lnbmVkU3dlZXAocGFyYW1zKTtcbiAgICB0aGlzLnZhbGlkYXRlUmVjb3ZlcnlQYXJhbXMocGFyYW1zLCBpc1Vuc2lnbmVkU3dlZXApO1xuXG4gICAgY29uc3QgeyBzZW5kZXJBZGRyZXNzLCBwdWJsaWNLZXksIGtleVNoYXJlcyB9ID0gYXdhaXQgdGhpcy5nZXRTZW5kZXJEZXRhaWxzKHBhcmFtcywgaXNVbnNpZ25lZFN3ZWVwKTtcblxuICAgIGNvbnN0IFtjaGFpbklkLCBhY2NvdW50RGV0YWlscywgYmFsYW5jZXNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgdGhpcy5nZXRDaGFpbklkKCksXG4gICAgICB0aGlzLmdldEFjY291bnREZXRhaWxzKHNlbmRlckFkZHJlc3MpLFxuICAgICAgdGhpcy5nZXRBY2NvdW50QmFsYW5jZShzZW5kZXJBZGRyZXNzKSxcbiAgICBdKTtcblxuICAgIGNvbnN0IHsgYWN0dWFsQmFsYW5jZSwgcmVtYWluaW5nQmFsYW5jZXMgfSA9IHRoaXMucHJvY2Vzc0JhbGFuY2VzKGJhbGFuY2VzKTtcbiAgICBjb25zdCBtZXNzYWdlcyA9IHRoaXMuYnVpbGRUcmFuc2FjdGlvbk1lc3NhZ2VzKFxuICAgICAgc2VuZGVyQWRkcmVzcyxcbiAgICAgIHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgYWN0dWFsQmFsYW5jZSxcbiAgICAgIHJlbWFpbmluZ0JhbGFuY2VzXG4gICAgKTtcblxuICAgIHJldHVybiB0aGlzLmJ1aWxkQW5kU2lnblRyYW5zYWN0aW9uKHtcbiAgICAgIG1lc3NhZ2VzLFxuICAgICAgY2hhaW5JZCxcbiAgICAgIGFjY291bnREZXRhaWxzLFxuICAgICAgcHVibGljS2V5OiBwdWJsaWNLZXkgfHwgJycsXG4gICAgICBpc1Vuc2lnbmVkU3dlZXAsXG4gICAgICBrZXlTaGFyZXMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSByZWNvdmVyeSBwYXJhbWV0ZXJzXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlUmVjb3ZlcnlQYXJhbXMocGFyYW1zOiBSZWNvdmVyeU9wdGlvbnMsIGlzVW5zaWduZWRTd2VlcDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24gfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgcmVjb3ZlcnlEZXN0aW5hdGlvbicpO1xuICAgIH1cblxuICAgIGlmICghaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICBpZiAoIXBhcmFtcy51c2VyS2V5KSB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgdXNlcktleScpO1xuICAgICAgaWYgKCFwYXJhbXMuYmFja3VwS2V5KSB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgYmFja3VwS2V5Jyk7XG4gICAgICBpZiAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB0aHJvdyBuZXcgRXJyb3IoJ21pc3Npbmcgd2FsbGV0IHBhc3NwaHJhc2UnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoaXMgaXMgYW4gdW5zaWduZWQgc3dlZXAgb3BlcmF0aW9uXG4gICAqL1xuICBwcml2YXRlIGlzVW5zaWduZWRTd2VlcChwYXJhbXM6IFJlY292ZXJ5T3B0aW9ucyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhcGFyYW1zLnVzZXJLZXkgJiYgIXBhcmFtcy5iYWNrdXBLZXkgJiYgIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgc2VuZGVyIGRldGFpbHMgaW5jbHVkaW5nIGFkZHJlc3MsIHB1YmxpYyBrZXkgYW5kIGtleSBzaGFyZXNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0U2VuZGVyRGV0YWlscyhcbiAgICBwYXJhbXM6IFJlY292ZXJ5T3B0aW9ucyxcbiAgICBpc1Vuc2lnbmVkU3dlZXA6IGJvb2xlYW5cbiAgKTogUHJvbWlzZTx7XG4gICAgc2VuZGVyQWRkcmVzczogc3RyaW5nO1xuICAgIHB1YmxpY0tleT86IHN0cmluZztcbiAgICBrZXlTaGFyZXM/OiBLZXlTaGFyZXM7XG4gIH0+IHtcbiAgICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcblxuICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNlbmRlckFkZHJlc3M6IHBhcmFtcy5yb290QWRkcmVzcyBhcyBzdHJpbmcsXG4gICAgICAgIHB1YmxpY0tleTogTVBDLmRlcml2ZVVuaGFyZGVuZWQocGFyYW1zLmJpdGdvS2V5IHx8ICcnLCBST09UX1BBVEgpLnNsaWNlKDAsIDY2KSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3Qga2V5U2hhcmVzID0gYXdhaXQgdGhpcy5nZXRLZXlTaGFyZXMocGFyYW1zKTtcbiAgICBjb25zdCBwdWJsaWNLZXkgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChrZXlTaGFyZXMuY29tbW9uS2V5Q2hhaW4sIFJPT1RfUEFUSCkuc2xpY2UoMCwgNjYpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHNlbmRlckFkZHJlc3M6IHRoaXMuZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkocHVibGljS2V5KSxcbiAgICAgIHB1YmxpY0tleSxcbiAgICAgIGtleVNoYXJlcyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMga2V5IHNoYXJlcyBmcm9tIHJlY292ZXJ5IHBhcmFtZXRlcnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZ2V0S2V5U2hhcmVzKHBhcmFtczogUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxLZXlTaGFyZXM+IHtcbiAgICBpZiAoIXBhcmFtcy51c2VyS2V5IHx8ICFwYXJhbXMuYmFja3VwS2V5IHx8ICFwYXJhbXMud2FsbGV0UGFzc3BocmFzZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIGtleSBwYXJhbWV0ZXJzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlcktleSA9IHBhcmFtcy51c2VyS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgY29uc3QgYmFja3VwS2V5ID0gcGFyYW1zLmJhY2t1cEtleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSBwYXJhbXMud2FsbGV0UGFzc3BocmFzZTtcblxuICAgIGlmICghdXNlcktleSB8fCAhYmFja3VwS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQga2V5IGZvcm1hdCcpO1xuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCBFQ0RTQVV0aWxzLmdldE1wY1YyUmVjb3ZlcnlLZXlTaGFyZXModXNlcktleSwgYmFja3VwS2V5LCB3YWxsZXRQYXNzcGhyYXNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9jZXNzZXMgYWNjb3VudCBiYWxhbmNlcyBhbmQgdmFsaWRhdGVzIHN1ZmZpY2llbnQgZnVuZHNcbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc0JhbGFuY2VzKGJhbGFuY2VzOiBDb2luW10pOiBCYWxhbmNlUmVzdWx0IHtcbiAgICBpZiAoIWJhbGFuY2VzPy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYmFsYW5jZSBmb3VuZCBvbiBhY2NvdW50Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVub21pbmF0aW9uID0gdGhpcy5nZXREZW5vbWluYXRpb24oKTtcbiAgICBpZiAoIWRlbm9taW5hdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRlbm9taW5hdGlvbicpO1xuICAgIH1cblxuICAgIGxldCBuYXRpdmVCYWxhbmNlID0gbmV3IEJpZ051bWJlcigwKTtcbiAgICBjb25zdCByZW1haW5pbmdCYWxhbmNlczogQ29pbltdID0gW107XG5cbiAgICBjb25zdCBnYXNBbW91bnREZXRhaWxzID0gdGhpcy5nZXRHYXNBbW91bnREZXRhaWxzKCk7XG4gICAgaWYgKCFnYXNBbW91bnREZXRhaWxzPy5nYXNBbW91bnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBnYXMgYW1vdW50Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgZ2FzQW1vdW50ID0gbmV3IEJpZ051bWJlcihnYXNBbW91bnREZXRhaWxzLmdhc0Ftb3VudCk7XG4gICAgYmFsYW5jZXMuZm9yRWFjaCgoYmFsYW5jZSkgPT4ge1xuICAgICAgaWYgKCFiYWxhbmNlLmFtb3VudCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYmFsYW5jZSBhbW91bnQnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGJhbGFuY2UuZGVub20gPT09IGRlbm9taW5hdGlvbikge1xuICAgICAgICBuYXRpdmVCYWxhbmNlID0gbmV3IEJpZ051bWJlcihiYWxhbmNlLmFtb3VudCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZW1haW5pbmdCYWxhbmNlcy5wdXNoKGJhbGFuY2UpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgYWN0dWFsQmFsYW5jZSA9IG5hdGl2ZUJhbGFuY2UubWludXMoZ2FzQW1vdW50KTtcbiAgICBpZiAoYWN0dWFsQmFsYW5jZS5pc0xlc3NUaGFuT3JFcXVhbFRvKDApKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpZCBub3QgaGF2ZSBlbm91Z2ggZnVuZHMgdG8gcmVjb3ZlcicpO1xuICAgIH1cblxuICAgIHJldHVybiB7IG5hdGl2ZUJhbGFuY2UsIHJlbWFpbmluZ0JhbGFuY2VzLCBhY3R1YWxCYWxhbmNlIH07XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRyYW5zYWN0aW9uIG1lc3NhZ2VzIGZvciBhbGwgYmFsYW5jZXNcbiAgICovXG4gIHByaXZhdGUgYnVpbGRUcmFuc2FjdGlvbk1lc3NhZ2VzKFxuICAgIHNlbmRlckFkZHJlc3M6IHN0cmluZyxcbiAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBzdHJpbmcsXG4gICAgYWN0dWFsQmFsYW5jZTogQmlnTnVtYmVyLFxuICAgIHJlbWFpbmluZ0JhbGFuY2VzOiBDb2luW11cbiAgKTogU2VuZE1lc3NhZ2VbXSB7XG4gICAgY29uc3QgbmF0aXZlU2VuZE1lc3NhZ2U6IFNlbmRNZXNzYWdlID0ge1xuICAgICAgZnJvbUFkZHJlc3M6IHNlbmRlckFkZHJlc3MsXG4gICAgICB0b0FkZHJlc3M6IHJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICBhbW91bnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRlbm9tOiB0aGlzLmdldERlbm9taW5hdGlvbigpLFxuICAgICAgICAgIGFtb3VudDogYWN0dWFsQmFsYW5jZS50b0ZpeGVkKCksXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG5cbiAgICBjb25zdCBvdGhlclRva2VuTWVzc2FnZXMgPSByZW1haW5pbmdCYWxhbmNlcy5tYXAoKGJhbGFuY2UpID0+ICh7XG4gICAgICBmcm9tQWRkcmVzczogc2VuZGVyQWRkcmVzcyxcbiAgICAgIHRvQWRkcmVzczogcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgIGFtb3VudDogW2JhbGFuY2VdLFxuICAgIH0pKTtcblxuICAgIHJldHVybiBbLi4ub3RoZXJUb2tlbk1lc3NhZ2VzLCBuYXRpdmVTZW5kTWVzc2FnZV07XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGFuZCBzaWducyB0aGUgdHJhbnNhY3Rpb25cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYnVpbGRBbmRTaWduVHJhbnNhY3Rpb24ocGFyYW1zOiBUcmFuc2FjdGlvbkJ1aWxkUGFyYW1zKTogUHJvbWlzZTxDb3Ntb3NMaWtlQ29pblJlY292ZXJ5T3V0cHV0PiB7XG4gICAgaWYgKCFwYXJhbXMuY2hhaW5JZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNoYWluIElEJyk7XG4gICAgfVxuXG4gICAgY29uc3QgW2FjY291bnROdW1iZXIsIHNlcXVlbmNlTm9dID0gcGFyYW1zLmFjY291bnREZXRhaWxzO1xuICAgIGlmICghYWNjb3VudE51bWJlciB8fCAhc2VxdWVuY2VObykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGFjY291bnQgZGV0YWlscycpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbm9taW5hdGlvbiA9IHRoaXMuZ2V0RGVub21pbmF0aW9uKCk7XG4gICAgY29uc3QgZ2FzQW1vdW50RGV0YWlscyA9IHRoaXMuZ2V0R2FzQW1vdW50RGV0YWlscygpO1xuICAgIGlmICghZGVub21pbmF0aW9uIHx8ICFnYXNBbW91bnREZXRhaWxzPy5nYXNBbW91bnQgfHwgIWdhc0Ftb3VudERldGFpbHM/Lmdhc0xpbWl0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZ2FzIGNvbmZpZ3VyYXRpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCBnYXNCdWRnZXQ6IEZlZURhdGEgPSB7XG4gICAgICBhbW91bnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIGRlbm9tOiBkZW5vbWluYXRpb24sXG4gICAgICAgICAgYW1vdW50OiBnYXNBbW91bnREZXRhaWxzLmdhc0Ftb3VudCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBnYXNMaW1pdDogZ2FzQW1vdW50RGV0YWlscy5nYXNMaW1pdCxcbiAgICB9O1xuXG4gICAgY29uc3QgdHhuQnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpXG4gICAgICAuZ2V0VHJhbnNmZXJCdWlsZGVyKClcbiAgICAgIC5tZXNzYWdlcyhwYXJhbXMubWVzc2FnZXMpXG4gICAgICAuZ2FzQnVkZ2V0KGdhc0J1ZGdldClcbiAgICAgIC5zZXF1ZW5jZShOdW1iZXIoc2VxdWVuY2VObykpXG4gICAgICAuYWNjb3VudE51bWJlcihOdW1iZXIoYWNjb3VudE51bWJlcikpXG4gICAgICAuY2hhaW5JZChwYXJhbXMuY2hhaW5JZClcbiAgICAgIC5wdWJsaWNLZXkocGFyYW1zLnB1YmxpY0tleSk7XG5cbiAgICBjb25zdCB1bnNpZ25lZFRyYW5zYWN0aW9uID0gKGF3YWl0IHR4bkJ1aWxkZXIuYnVpbGQoKSkgYXMgQ29zbW9zVHJhbnNhY3Rpb248Q3VzdG9tTWVzc2FnZT47XG4gICAgaWYgKCF1bnNpZ25lZFRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBidWlsZCB1bnNpZ25lZCB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMuaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzaWduYWJsZUhleDogdW5zaWduZWRUcmFuc2FjdGlvbi5zaWduYWJsZVBheWxvYWQudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zaWduVHJhbnNhY3Rpb25XaXRoTXBjKHVuc2lnbmVkVHJhbnNhY3Rpb24sIHR4bkJ1aWxkZXIsIHBhcmFtcy5rZXlTaGFyZXMhLCBwYXJhbXMucHVibGljS2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWducyB0aGUgdHJhbnNhY3Rpb24gd2l0aCBNUENcbiAgICovXG4gIC8qKlxuICAgKiBTaWducyB0aGUgdHJhbnNhY3Rpb24gdXNpbmcgTVBDIChNdWx0aS1QYXJ0eSBDb21wdXRhdGlvbilcbiAgICogQHBhcmFtIHVuc2lnbmVkVHJhbnNhY3Rpb24gVGhlIHVuc2lnbmVkIHRyYW5zYWN0aW9uIHRvIHNpZ25cbiAgICogQHBhcmFtIHR4bkJ1aWxkZXIgVGhlIHRyYW5zYWN0aW9uIGJ1aWxkZXIgaW5zdGFuY2VcbiAgICogQHBhcmFtIGtleVNoYXJlcyBUaGUga2V5IHNoYXJlcyBmb3IgTVBDIHNpZ25pbmdcbiAgICogQHBhcmFtIHB1YmxpY0tleSBUaGUgcHVibGljIGtleSBmb3IgdmVyaWZpY2F0aW9uXG4gICAqIEByZXR1cm5zIFRoZSBzaWduZWQgdHJhbnNhY3Rpb24gb3V0cHV0XG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgdmFsaWRhdGlvbiBmYWlscyBvciBzaWduaW5nIHByb2Nlc3MgZW5jb3VudGVycyBhbiBlcnJvclxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHNpZ25UcmFuc2FjdGlvbldpdGhNcGMoXG4gICAgdW5zaWduZWRUcmFuc2FjdGlvbjogQ29zbW9zVHJhbnNhY3Rpb248Q3VzdG9tTWVzc2FnZT4sXG4gICAgdHhuQnVpbGRlcjogQ29zbW9zVHJhbnNhY3Rpb25CdWlsZGVyLFxuICAgIGtleVNoYXJlczogS2V5U2hhcmVzLFxuICAgIHB1YmxpY0tleTogc3RyaW5nXG4gICk6IFByb21pc2U8Q29zbW9zTGlrZUNvaW5SZWNvdmVyeU91dHB1dD4ge1xuICAgIC8vIFZhbGlkYXRlIGlucHV0c1xuICAgIGlmICghdW5zaWduZWRUcmFuc2FjdGlvbj8uc2lnbmFibGVQYXlsb2FkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdW5zaWduZWQgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBpZiAoIWtleVNoYXJlcz8udXNlcktleVNoYXJlIHx8ICFrZXlTaGFyZXM/LmJhY2t1cEtleVNoYXJlIHx8ICFrZXlTaGFyZXM/LmNvbW1vbktleUNoYWluKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQga2V5IHNoYXJlcycpO1xuICAgIH1cblxuICAgIGlmICghcHVibGljS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcHVibGljIGtleScpO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSB1bnNpZ25lZFRyYW5zYWN0aW9uLnNpZ25hYmxlUGF5bG9hZDtcblxuICAgICAgLy8gR2V0IGhhc2ggZnVuY3Rpb24gYW5kIGNvbXB1dGUgbWVzc2FnZSBoYXNoXG4gICAgICBjb25zdCBoYXNoRnVuY3Rpb24gPSB1dGlscy5nZXRIYXNoRnVuY3Rpb24oKSB8fCBjcmVhdGVIYXNoKCdzaGEyNTYnKTtcbiAgICAgIGlmICghaGFzaEZ1bmN0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGdldCBoYXNoIGZ1bmN0aW9uJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlSGFzaCA9IGhhc2hGdW5jdGlvbi51cGRhdGUobWVzc2FnZSkuZGlnZXN0KCk7XG5cbiAgICAgIC8vIFNpZ24gdGhlIHRyYW5zYWN0aW9uXG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBFQ0RTQVV0aWxzLnNpZ25SZWNvdmVyeU1wY1YyKFxuICAgICAgICBtZXNzYWdlSGFzaCxcbiAgICAgICAga2V5U2hhcmVzLnVzZXJLZXlTaGFyZSxcbiAgICAgICAga2V5U2hhcmVzLmJhY2t1cEtleVNoYXJlLFxuICAgICAgICBrZXlTaGFyZXMuY29tbW9uS2V5Q2hhaW5cbiAgICAgICk7XG5cbiAgICAgIC8vIFZlcmlmeSB0aGUgc2lnbmF0dXJlXG4gICAgICBjb25zdCBzaWduYWJsZUhleCA9IHVuc2lnbmVkVHJhbnNhY3Rpb24uc2lnbmFibGVQYXlsb2FkLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIGNvbnN0IHNpZ25hYmxlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICAgIE1QQy52ZXJpZnkoc2lnbmFibGVCdWZmZXIsIHNpZ25hdHVyZSwgdGhpcy5nZXRIYXNoRnVuY3Rpb24oKSk7XG5cbiAgICAgIC8vIEdldCBjb3Ntb3Mga2V5IHBhaXIgYW5kIHZhbGlkYXRlXG4gICAgICBjb25zdCBjb3Ntb3NLZXlQYWlyID0gdGhpcy5nZXRLZXlQYWlyKHB1YmxpY0tleSk7XG4gICAgICBpZiAoIWNvc21vc0tleVBhaXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvc21vcyBrZXkgcGFpcicpO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgc2lnbmF0dXJlIHRvIHRyYW5zYWN0aW9uXG4gICAgICB0eG5CdWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogY29zbW9zS2V5UGFpci5nZXRLZXlzKCkucHViIH0sIEJ1ZmZlci5mcm9tKHNpZ25hdHVyZS5yICsgc2lnbmF0dXJlLnMsICdoZXgnKSk7XG5cbiAgICAgIC8vIEJ1aWxkIGZpbmFsIHRyYW5zYWN0aW9uXG4gICAgICBjb25zdCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IHR4bkJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGlmICghc2lnbmVkVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gYnVpbGQgc2lnbmVkIHRyYW5zYWN0aW9uJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNlcmlhbGl6ZWRUeDogc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHNpZ24gdHJhbnNhY3Rpb246ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgcmVkZWxlZ2F0ZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge1JlY292ZXJ5T3B0aW9uc30gcGFyYW1zIHBhcmFtZXRlcnMgbmVlZGVkIHRvIGNvbnN0cnVjdCBhbmRcbiAgICogKG1heWJlKSBzaWduIHRoZSB0cmFuc2FjdGlvblxuICAgKlxuICAgKiBAcmV0dXJucyB7Q29zbW9zTGlrZUNvaW5SZWNvdmVyeU91dHB1dH0gdGhlIHNlcmlhbGl6ZWQgdHJhbnNhY3Rpb24gaGV4IHN0cmluZ1xuICAgKi9cbiAgYXN5bmMgcmVkZWxlZ2F0ZShcbiAgICBwYXJhbXM6IFJlY292ZXJ5T3B0aW9ucyAmIHtcbiAgICAgIHZhbGlkYXRvclNyY0FkZHJlc3M6IHN0cmluZztcbiAgICAgIHZhbGlkYXRvckRzdEFkZHJlc3M6IHN0cmluZztcbiAgICAgIGFtb3VudFRvUmVkZWxlZ2F0ZTogc3RyaW5nO1xuICAgIH1cbiAgKTogUHJvbWlzZTxDb3Ntb3NMaWtlQ29pblJlY292ZXJ5T3V0cHV0PiB7XG4gICAgaWYgKCFwYXJhbXMudmFsaWRhdG9yU3JjQWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMudmFsaWRhdG9yU3JjQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCB2YWxpZGF0b3JTcmNBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMudmFsaWRhdG9yRHN0QWRkcmVzcyB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMudmFsaWRhdG9yRHN0QWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCB2YWxpZGF0b3JEc3RBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJhbXMudXNlcktleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHVzZXJLZXknKTtcbiAgICB9XG5cbiAgICBpZiAoIXBhcmFtcy5iYWNrdXBLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiYWNrdXBLZXknKTtcbiAgICB9XG5cbiAgICBpZiAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3Npbmcgd2FsbGV0IHBhc3NwaHJhc2UnKTtcbiAgICB9XG5cbiAgICBpZiAoIXBhcmFtcy5hbW91bnRUb1JlZGVsZWdhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBhbW91bnRUb1JlZGVsZWdhdGUnKTtcbiAgICB9XG5cbiAgICBjb25zdCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBiYWNrdXBLZXkgPSBwYXJhbXMuYmFja3VwS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG5cbiAgICBjb25zdCB7IHVzZXJLZXlTaGFyZSwgYmFja3VwS2V5U2hhcmUsIGNvbW1vbktleUNoYWluIH0gPSBhd2FpdCBFQ0RTQVV0aWxzLmdldE1wY1YyUmVjb3ZlcnlLZXlTaGFyZXMoXG4gICAgICB1c2VyS2V5LFxuICAgICAgYmFja3VwS2V5LFxuICAgICAgcGFyYW1zLndhbGxldFBhc3NwaHJhc2VcbiAgICApOyAvLyBiYXNlQWRkcmVzcyBpcyBub3QgZXh0cmFjdGVkXG5cbiAgICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcbiAgICBjb25zdCBjaGFpbklkID0gYXdhaXQgdGhpcy5nZXRDaGFpbklkKCk7XG4gICAgY29uc3QgcHVibGljS2V5ID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoY29tbW9uS2V5Q2hhaW4sIFJPT1RfUEFUSCkuc2xpY2UoMCwgNjYpO1xuICAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSB0aGlzLmdldEFkZHJlc3NGcm9tUHVibGljS2V5KHB1YmxpY0tleSk7XG5cbiAgICBjb25zdCBbYWNjb3VudE51bWJlciwgc2VxdWVuY2VOb10gPSBhd2FpdCB0aGlzLmdldEFjY291bnREZXRhaWxzKHNlbmRlckFkZHJlc3MpO1xuICAgIGNvbnN0IGdhc0J1ZGdldDogRmVlRGF0YSA9IHtcbiAgICAgIGFtb3VudDogW3sgZGVub206IHRoaXMuZ2V0RGVub21pbmF0aW9uKCksIGFtb3VudDogdGhpcy5nZXRHYXNBbW91bnREZXRhaWxzKCkuZ2FzQW1vdW50IH1dLFxuICAgICAgZ2FzTGltaXQ6IHRoaXMuZ2V0R2FzQW1vdW50RGV0YWlscygpLmdhc0xpbWl0LFxuICAgIH07XG5cbiAgICBjb25zdCBhbW91bnQ6IENvaW4gPSB7XG4gICAgICBkZW5vbTogdGhpcy5nZXREZW5vbWluYXRpb24oKSxcbiAgICAgIGFtb3VudDogbmV3IEJpZ051bWJlcihwYXJhbXMuYW1vdW50VG9SZWRlbGVnYXRlKS50b0ZpeGVkKCksXG4gICAgfTtcblxuICAgIGNvbnN0IHNlbmRNZXNzYWdlOiBSZWRlbGVnYXRlTWVzc2FnZVtdID0gW1xuICAgICAge1xuICAgICAgICBkZWxlZ2F0b3JBZGRyZXNzOiBzZW5kZXJBZGRyZXNzLFxuICAgICAgICB2YWxpZGF0b3JTcmNBZGRyZXNzOiBwYXJhbXMudmFsaWRhdG9yU3JjQWRkcmVzcyxcbiAgICAgICAgdmFsaWRhdG9yRHN0QWRkcmVzczogcGFyYW1zLnZhbGlkYXRvckRzdEFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogYW1vdW50LFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgY29uc3QgdHhuQnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpLmdldFN0YWtpbmdSZWRlbGVnYXRlQnVpbGRlcigpO1xuICAgIHR4bkJ1aWxkZXJcbiAgICAgIC5tZXNzYWdlcyhzZW5kTWVzc2FnZSlcbiAgICAgIC5nYXNCdWRnZXQoZ2FzQnVkZ2V0KVxuICAgICAgLnB1YmxpY0tleShwdWJsaWNLZXkpXG4gICAgICAuc2VxdWVuY2UoTnVtYmVyKHNlcXVlbmNlTm8pKVxuICAgICAgLmFjY291bnROdW1iZXIoTnVtYmVyKGFjY291bnROdW1iZXIpKVxuICAgICAgLmNoYWluSWQoY2hhaW5JZCk7XG5cbiAgICBjb25zdCB1bnNpZ25lZFRyYW5zYWN0aW9uID0gKGF3YWl0IHR4bkJ1aWxkZXIuYnVpbGQoKSkgYXMgQ29zbW9zVHJhbnNhY3Rpb248Q3VzdG9tTWVzc2FnZT47XG4gICAgbGV0IHNlcmlhbGl6ZWRUeCA9IHVuc2lnbmVkVHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICBjb25zdCBzaWduYWJsZUhleCA9IHVuc2lnbmVkVHJhbnNhY3Rpb24uc2lnbmFibGVQYXlsb2FkLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBtZXNzYWdlID0gdW5zaWduZWRUcmFuc2FjdGlvbi5zaWduYWJsZVBheWxvYWQ7XG4gICAgY29uc3QgbWVzc2FnZUhhc2ggPSAodXRpbHMuZ2V0SGFzaEZ1bmN0aW9uKCkgfHwgY3JlYXRlSGFzaCgnc2hhMjU2JykpLnVwZGF0ZShtZXNzYWdlKS5kaWdlc3QoKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBFQ0RTQVV0aWxzLnNpZ25SZWNvdmVyeU1wY1YyKG1lc3NhZ2VIYXNoLCB1c2VyS2V5U2hhcmUsIGJhY2t1cEtleVNoYXJlLCBjb21tb25LZXlDaGFpbik7XG4gICAgY29uc3Qgc2lnbmFibGVCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYWJsZUhleCwgJ2hleCcpO1xuICAgIE1QQy52ZXJpZnkoc2lnbmFibGVCdWZmZXIsIHNpZ25hdHVyZSwgdGhpcy5nZXRIYXNoRnVuY3Rpb24oKSk7XG4gICAgY29uc3QgY29zbW9zS2V5UGFpciA9IHRoaXMuZ2V0S2V5UGFpcihwdWJsaWNLZXkpO1xuICAgIHR4bkJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiBjb3Ntb3NLZXlQYWlyLmdldEtleXMoKS5wdWIgfSwgQnVmZmVyLmZyb20oc2lnbmF0dXJlLnIgKyBzaWduYXR1cmUucywgJ2hleCcpKTtcbiAgICBjb25zdCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IHR4bkJ1aWxkZXIuYnVpbGQoKTtcbiAgICBzZXJpYWxpemVkVHggPSBzaWduZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgcmV0dXJuIHsgc2VyaWFsaXplZFR4OiBzZXJpYWxpemVkVHggfTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqKi9cbiAgYXN5bmMgdmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBsZXQgdG90YWxBbW91bnQgPSBuZXcgQmlnTnVtYmVyKDApO1xuICAgIGNvbnN0IHsgdHhQcmVidWlsZCwgdHhQYXJhbXMgfSA9IHBhcmFtcztcbiAgICBjb25zdCByYXdUeCA9IHR4UHJlYnVpbGQudHhIZXg7XG4gICAgaWYgKCFyYXdUeCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIHR4IHByZWJ1aWxkIHByb3BlcnR5IHR4SGV4Jyk7XG4gICAgfVxuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gYXdhaXQgdGhpcy5nZXRCdWlsZGVyKCkuZnJvbShyYXdUeCkuYnVpbGQoKTtcbiAgICBjb25zdCBleHBsYWluZWRUeCA9IHRyYW5zYWN0aW9uLmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuICAgIGlmICh0eFBhcmFtcy5yZWNpcGllbnRzICYmIHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgZmlsdGVyZWRSZWNpcGllbnRzID0gdHhQYXJhbXMucmVjaXBpZW50cz8ubWFwKChyZWNpcGllbnQpID0+IF8ucGljayhyZWNpcGllbnQsIFsnYWRkcmVzcycsICdhbW91bnQnXSkpO1xuICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXRzID0gZXhwbGFpbmVkVHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4gXy5waWNrKG91dHB1dCwgWydhZGRyZXNzJywgJ2Ftb3VudCddKSk7XG5cbiAgICAgIGlmICghXy5pc0VxdWFsKGZpbHRlcmVkT3V0cHV0cywgZmlsdGVyZWRSZWNpcGllbnRzKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJyk7XG4gICAgICB9XG4gICAgICAvLyBXaXRoZHJhd0RlbGVnYXRvclJld2FyZHMgYW5kIENvbnRyYWN0Q2FsbCB0cmFuc2FjdGlvbiBkb24ndCBoYXZlIGFtb3VudFxuICAgICAgaWYgKHRyYW5zYWN0aW9uLnR5cGUgIT09IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXcgJiYgdHJhbnNhY3Rpb24udHlwZSAhPT0gVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCkge1xuICAgICAgICBmb3IgKGNvbnN0IHJlY2lwaWVudHMgb2YgdHhQYXJhbXMucmVjaXBpZW50cykge1xuICAgICAgICAgIHRvdGFsQW1vdW50ID0gdG90YWxBbW91bnQucGx1cyhyZWNpcGllbnRzLmFtb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0b3RhbEFtb3VudC5pc0VxdWFsVG8oZXhwbGFpbmVkVHgub3V0cHV0QW1vdW50KSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVHggdG90YWwgYW1vdW50IGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdG90YWwgYW1vdW50IGZpZWxkJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKiovXG4gIGFzeW5jIGV4cGxhaW5UcmFuc2FjdGlvbihvcHRpb25zOiB7IHR4SGV4OiBzdHJpbmcgfSk6IFByb21pc2U8RXhwbGFuYXRpb25SZXN1bHQ+IHtcbiAgICBpZiAoIW9wdGlvbnMudHhIZXgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCB0eEhleCBwYXJhbWV0ZXInKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uQnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpLmZyb20ob3B0aW9ucy50eEhleCk7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGF3YWl0IHRyYW5zYWN0aW9uQnVpbGRlci5idWlsZCgpO1xuICAgICAgcmV0dXJuIHRyYW5zYWN0aW9uLmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogJyArIGUubWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNpZ24gYSB0cmFuc2FjdGlvbiB3aXRoIGEgc2luZ2xlIHByaXZhdGUga2V5XG4gICAqIEBwYXJhbSBwYXJhbXMgcGFyYW1ldGVycyBpbiB0aGUgZm9ybSBvZiB7IHR4UHJlYnVpbGQ6IHt0eEhleH0sIHBydiB9XG4gICAqIEByZXR1cm5zIHNpZ25lZCB0cmFuc2FjdGlvbiBpbiB0aGUgZm9ybSBvZiB7IHR4SGV4IH1cbiAgICovXG4gIGFzeW5jIHNpZ25UcmFuc2FjdGlvbihcbiAgICBwYXJhbXM6IFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMgJiB7IHR4UHJlYnVpbGQ6IHsgdHhIZXg6IHN0cmluZyB9OyBwcnY6IHN0cmluZyB9XG4gICk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB0eEhleCA9IHBhcmFtcz8udHhQcmVidWlsZD8udHhIZXg7XG4gICAgY29uc3QgcHJpdmF0ZUtleSA9IHBhcmFtcz8ucHJ2O1xuICAgIGlmICghdHhIZXgpIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQgdHhQcmVidWlsZCBwYXJhbWV0ZXI6IHBhcmFtcy50eFByZWJ1aWxkLnR4SGV4Jyk7XG4gICAgfVxuICAgIGlmICghcHJpdmF0ZUtleSkge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignbWlzc2luZyByZXF1aXJlZCBwcnYgcGFyYW1ldGVyOiBwYXJhbXMucHJ2Jyk7XG4gICAgfVxuICAgIGNvbnN0IHR4QnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpLmZyb20ocGFyYW1zLnR4UHJlYnVpbGQudHhIZXgpO1xuICAgIHR4QnVpbGRlci5zaWduKHsga2V5OiBwYXJhbXMucHJ2IH0pO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBCYXNlVHJhbnNhY3Rpb24gPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICBpZiAoIXRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgU2lnbmluZ0Vycm9yKCdGYWlsZWQgdG8gYnVpbGQgc2lnbmVkIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeCA9IHRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR4SGV4OiBzZXJpYWxpemVkVHgsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqKi9cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zICYgeyB0eEhleDogc3RyaW5nIH0pOiBQcm9taXNlPFBhcnNlZFRyYW5zYWN0aW9uPiB7XG4gICAgY29uc3QgdHJhbnNhY3Rpb25FeHBsYW5hdGlvbiA9IGF3YWl0IHRoaXMuZXhwbGFpblRyYW5zYWN0aW9uKHsgdHhIZXg6IHBhcmFtcy50eEhleCB9KTtcbiAgICBpZiAoIXRyYW5zYWN0aW9uRXhwbGFuYXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGlmICh0cmFuc2FjdGlvbkV4cGxhbmF0aW9uLm91dHB1dHMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGlucHV0czogW10sXG4gICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgfTtcbiAgICB9XG4gICAgY29uc3Qgc2VuZGVyQWRkcmVzcyA9IHRyYW5zYWN0aW9uRXhwbGFuYXRpb24ub3V0cHV0c1swXS5hZGRyZXNzO1xuICAgIGNvbnN0IGZlZUFtb3VudCA9IG5ldyBCaWdOdW1iZXIodHJhbnNhY3Rpb25FeHBsYW5hdGlvbi5mZWUuZmVlID09PSAnJyA/ICcwJyA6IHRyYW5zYWN0aW9uRXhwbGFuYXRpb24uZmVlLmZlZSk7XG4gICAgY29uc3QgaW5wdXRzID0gW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiBzZW5kZXJBZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IG5ldyBCaWdOdW1iZXIodHJhbnNhY3Rpb25FeHBsYW5hdGlvbi5vdXRwdXRBbW91bnQpLnBsdXMoZmVlQW1vdW50KS50b0ZpeGVkKCksXG4gICAgICB9LFxuICAgIF07XG4gICAgY29uc3Qgb3V0cHV0cyA9IHRyYW5zYWN0aW9uRXhwbGFuYXRpb24ub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkcmVzczogb3V0cHV0LmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogbmV3IEJpZ051bWJlcihvdXRwdXQuYW1vdW50KS50b0ZpeGVkKCksXG4gICAgICB9O1xuICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBpbnB1dHMsXG4gICAgICBvdXRwdXRzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBwdWJsaWMgbm9kZSB1cmwgZnJvbSB0aGUgRW52aXJvbm1lbnRzIGNvbnN0YW50IHdlIGhhdmUgZGVmaW5lZFxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFB1YmxpY05vZGVVcmwoKTogc3RyaW5nIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFjY291bnQgbnVtYmVyIGZyb20gcHVibGljIG5vZGVcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50RnJvbU5vZGUoc2VuZGVyQWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxyZXF1ZXN0LlJlc3BvbnNlPiB7XG4gICAgY29uc3Qgbm9kZVVybCA9IHRoaXMuZ2V0UHVibGljTm9kZVVybCgpO1xuICAgIGNvbnN0IGdldEFjY291bnRQYXRoID0gJy9jb3Ntb3MvYXV0aC92MWJldGExL2FjY291bnRzLyc7XG4gICAgY29uc3QgZnVsbEVuZHBvaW50ID0gbm9kZVVybCArIGdldEFjY291bnRQYXRoICsgc2VuZGVyQWRkcmVzcztcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHJlcXVlc3QuZ2V0KGZ1bGxFbmRwb2ludCkuc2VuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoZSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGNhbGwgZW5kcG9pbnQgJHtnZXRBY2NvdW50UGF0aCArIHNlbmRlckFkZHJlc3N9IGZyb20gbm9kZTogJHtub2RlVXJsfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBiYWxhbmNlIGZyb20gcHVibGljIG5vZGVcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXRCYWxhbmNlRnJvbU5vZGUoc2VuZGVyQWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxyZXF1ZXN0LlJlc3BvbnNlPiB7XG4gICAgY29uc3Qgbm9kZVVybCA9IHRoaXMuZ2V0UHVibGljTm9kZVVybCgpO1xuICAgIGNvbnN0IGdldEJhbGFuY2VQYXRoID0gJy9jb3Ntb3MvYmFuay92MWJldGExL2JhbGFuY2VzLyc7XG4gICAgY29uc3QgZnVsbEVuZHBvaW50ID0gbm9kZVVybCArIGdldEJhbGFuY2VQYXRoICsgc2VuZGVyQWRkcmVzcztcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHJlcXVlc3QuZ2V0KGZ1bGxFbmRwb2ludCkuc2VuZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoZSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGNhbGwgZW5kcG9pbnQgJHtnZXRCYWxhbmNlUGF0aCArIHNlbmRlckFkZHJlc3N9IGZyb20gbm9kZTogJHtub2RlVXJsfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjaGFpbiBpZCBmcm9tIHB1YmxpYyBub2RlXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0Q2hhaW5JZEZyb21Ob2RlKCk6IFByb21pc2U8cmVxdWVzdC5SZXNwb25zZT4ge1xuICAgIGNvbnN0IG5vZGVVcmwgPSB0aGlzLmdldFB1YmxpY05vZGVVcmwoKTtcbiAgICBjb25zdCBnZXRMYXRlc3RCbG9ja1BhdGggPSAnL2Nvc21vcy9iYXNlL3RlbmRlcm1pbnQvdjFiZXRhMS9ibG9ja3MvbGF0ZXN0JztcbiAgICBjb25zdCBmdWxsRW5kcG9pbnQgPSBub2RlVXJsICsgZ2V0TGF0ZXN0QmxvY2tQYXRoO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVxdWVzdC5nZXQoZnVsbEVuZHBvaW50KS5zZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5kZWJ1ZyhlKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gY2FsbCBlbmRwb2ludCAke2dldExhdGVzdEJsb2NrUGF0aH0gZnJvbSBub2RlOiAke25vZGVVcmx9YCk7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIHRvIGZldGNoIGFjY291bnQgYmFsYW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEFjY291bnRCYWxhbmNlKHNlbmRlckFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8Q29pbltdPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldEJhbGFuY2VGcm9tTm9kZShzZW5kZXJBZGRyZXNzKTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQWNjb3VudCBub3QgZm91bmQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3BvbnNlLmJvZHkuYmFsYW5jZXM7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIHRvIGZldGNoIGNoYWluSWRcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXRDaGFpbklkKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldENoYWluSWRGcm9tTm9kZSgpO1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXMgIT09IDIwMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBY2NvdW50IG5vdCBmb3VuZCcpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzcG9uc2UuYm9keS5ibG9jay5oZWFkZXIuY2hhaW5faWQ7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIHRvIGZldGNoIGFjY291bnQgbnVtYmVyXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0QWNjb3VudERldGFpbHMoc2VuZGVyQWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50RnJvbU5vZGUoc2VuZGVyQWRkcmVzcyk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjY291bnQgbm90IGZvdW5kJyk7XG4gICAgfVxuICAgIHJldHVybiBbcmVzcG9uc2UuYm9keS5hY2NvdW50LmFjY291bnRfbnVtYmVyLCByZXNwb25zZS5ib2R5LmFjY291bnQuc2VxdWVuY2VdO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICBnZW5lcmF0ZUtleVBhaXIoc2VlZD86IEJ1ZmZlcik6IEtleVBhaXIge1xuICAgIGlmICghc2VlZCkge1xuICAgICAgLy8gQW4gZXh0ZW5kZWQgcHJpdmF0ZSBrZXkgaGFzIGJvdGggYSBub3JtYWwgMjU2IGJpdCBwcml2YXRlIGtleSBhbmQgYSAyNTZcbiAgICAgIC8vIGJpdCBjaGFpbiBjb2RlLCBib3RoIG9mIHdoaWNoIG11c3QgYmUgcmFuZG9tLiA1MTIgYml0cyBpcyB0aGVyZWZvcmUgdGhlXG4gICAgICAvLyBtYXhpbXVtIGVudHJvcHkgYW5kIGdpdmVzIHVzIG1heGltdW0gc2VjdXJpdHkgYWdhaW5zdCBjcmFja2luZy5cbiAgICAgIHNlZWQgPSByYW5kb21CeXRlcyg1MTIgLyA4KTtcbiAgICB9XG4gICAgY29uc3QgZXh0ZW5kZWRLZXkgPSBiaXAzMi5mcm9tU2VlZChzZWVkKTtcbiAgICByZXR1cm4ge1xuICAgICAgcHViOiBleHRlbmRlZEtleS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCksXG4gICAgICBwcnY6IGV4dGVuZGVkS2V5LnRvQmFzZTU4KCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIGFkZHJlc3MgZnJvbSBhIHB1YmxpYyBrZXkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwdWJLZXkgLSBUaGUgcHVibGljIGtleS5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGNvcnJlc3BvbmRpbmcgYWRkcmVzcy5cbiAgICovXG4gIGdldEFkZHJlc3NGcm9tUHVibGljS2V5KHB1YktleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqKi9cbiAgYXN5bmMgaXNXYWxsZXRBZGRyZXNzKHBhcmFtczogVmVyaWZ5QWRkcmVzc09wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBhZGRyZXNzRGV0YWlscyA9IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMocGFyYW1zLmFkZHJlc3MpO1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3NEZXRhaWxzLmFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAke2FkZHJlc3NEZXRhaWxzLmFkZHJlc3N9YCk7XG4gICAgfVxuICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gKHBhcmFtcy5jb2luU3BlY2lmaWMgYXMgQ29zbW9zQ29pblNwZWNpZmljKS5yb290QWRkcmVzcztcbiAgICBpZiAoYWRkcmVzc0RldGFpbHMuYWRkcmVzcyAhPT0gcm9vdEFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yKGBhZGRyZXNzIHZhbGlkYXRpb24gZmFpbHVyZTogJHthZGRyZXNzRGV0YWlscy5hZGRyZXNzfSB2cyAke3Jvb3RBZGRyZXNzfWApO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqKi9cbiAgZ2V0SGFzaEZ1bmN0aW9uKCk6IEhhc2gge1xuICAgIHJldHVybiB1dGlscy5nZXRIYXNoRnVuY3Rpb24oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9jZXNzIGFkZHJlc3MgaW50byBhZGRyZXNzIGFuZCBtZW1vIGlkXG4gICAqXG4gICAqIEBwYXJhbSBhZGRyZXNzIHRoZSBhZGRyZXNzXG4gICAqIEByZXR1cm5zIG9iamVjdCBjb250YWluaW5nIGFkZHJlc3MgYW5kIG1lbW8gaWRcbiAgICovXG4gIGdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3M6IHN0cmluZyk6IEFkZHJlc3NEZXRhaWxzIHtcbiAgICBjb25zdCBkZXN0aW5hdGlvbkRldGFpbHMgPSB1cmwucGFyc2UoYWRkcmVzcyk7XG4gICAgY29uc3QgZGVzdGluYXRpb25BZGRyZXNzID0gZGVzdGluYXRpb25EZXRhaWxzLnBhdGhuYW1lIHx8ICcnO1xuXG4gICAgLy8gYWRkcmVzcyBkb2Vzbid0IGhhdmUgYSBtZW1vIGlkXG4gICAgaWYgKGRlc3RpbmF0aW9uRGV0YWlscy5wYXRobmFtZSA9PT0gYWRkcmVzcykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkcmVzczogYWRkcmVzcyxcbiAgICAgICAgbWVtb0lkOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmICghZGVzdGluYXRpb25EZXRhaWxzLnF1ZXJ5KSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAke2FkZHJlc3N9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgcXVlcnlEZXRhaWxzID0gcXVlcnlzdHJpbmcucGFyc2UoZGVzdGluYXRpb25EZXRhaWxzLnF1ZXJ5KTtcbiAgICBpZiAoIXF1ZXJ5RGV0YWlscy5tZW1vSWQpIHtcbiAgICAgIC8vIGlmIHRoZXJlIGFyZSBtb3JlIHByb3BlcnRpZXMsIHRoZSBxdWVyeSBkZXRhaWxzIG5lZWQgdG8gY29udGFpbiB0aGUgbWVtbyBpZCBwcm9wZXJ0eVxuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgYWRkcmVzczogJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIGlmIChBcnJheS5pc0FycmF5KHF1ZXJ5RGV0YWlscy5tZW1vSWQpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihcbiAgICAgICAgYG1lbW9JZCBtYXkgb25seSBiZSBnaXZlbiBhdCBtb3N0IG9uY2UsIGJ1dCBmb3VuZCAke3F1ZXJ5RGV0YWlscy5tZW1vSWQubGVuZ3RofSBpbnN0YW5jZXMgaW4gYWRkcmVzcyAke2FkZHJlc3N9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShxdWVyeURldGFpbHMubWVtb0lkKSAmJiBxdWVyeURldGFpbHMubWVtb0lkLmxlbmd0aCAhPT0gMSkge1xuICAgICAgLy8gdmFsaWQgYWRkcmVzc2VzIGNhbiBvbmx5IGNvbnRhaW4gb25lIG1lbW8gaWRcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKGBpbnZhbGlkIGFkZHJlc3MgJyR7YWRkcmVzc30nLCBtdXN0IGNvbnRhaW4gZXhhY3RseSBvbmUgbWVtb0lkYCk7XG4gICAgfVxuXG4gICAgY29uc3QgW21lbW9JZF0gPSBfLmNhc3RBcnJheShxdWVyeURldGFpbHMubWVtb0lkKSB8fCB1bmRlZmluZWQ7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRNZW1vSWQobWVtb0lkKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRNZW1vSWRFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAnJHthZGRyZXNzfScsIG1lbW9JZCBpcyBub3QgdmFsaWRgKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYWRkcmVzczogZGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgbWVtb0lkLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIGEgbWVtbyBpZCBpcyB2YWxpZFxuICAgKlxuICAgKiBAcGFyYW0gbWVtb0lkIG1lbW8gaWRcbiAgICogQHJldHVybnMgdHJ1ZSBpZiBtZW1vIGlkIGlzIHZhbGlkXG4gICAqL1xuICBpc1ZhbGlkTWVtb0lkKG1lbW9JZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHV0aWxzLmlzVmFsaWRNZW1vSWQobWVtb0lkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIHJldHVybiB0aGUgcmVzcGVjdGl2ZSBjb2luJ3MgYmFzZSB1bml0XG4gICAqL1xuICBnZXREZW5vbWluYXRpb24oKTogc3RyaW5nIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgbWV0aG9kIHRvIGZldGNoIGdhcyBhbW91bnQgZGV0YWlscyBmb3IgcmVzcGVjdGl2ZSBjb2luXG4gICAqL1xuICBnZXRHYXNBbW91bnREZXRhaWxzKCk6IEdhc0Ftb3VudERldGFpbHMge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBtZXRob2QgdG8gZ2V0IGtleSBwYWlyIGZvciBpbmRpdmlkdWFsIGNvaW5cbiAgICogQHBhcmFtIHB1YmxpY0tleVxuICAgKi9cbiAgZ2V0S2V5UGFpcihwdWJsaWNLZXk6IHN0cmluZyk6IENvc21vc0tleVBhaXIge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICBhdWRpdERlY3J5cHRlZEtleSh7IG11bHRpU2lnVHlwZSwgcHVibGljS2V5LCBwcnYgfTogQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMpIHtcbiAgICBpZiAobXVsdGlTaWdUeXBlICE9PSAndHNzJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBtdWx0aVNpZ1R5cGUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXVkaXRFY2RzYVByaXZhdGVLZXkocHJ2IGFzIHN0cmluZywgcHVibGljS2V5IGFzIHN0cmluZyk7XG4gICAgfVxuICB9XG59XG4iXX0=