@bitgo-beta/sdk-coin-near 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 (72) hide show
  1. package/.eslintignore +5 -0
  2. package/.mocharc.yml +8 -0
  3. package/CHANGELOG.md +784 -0
  4. package/LICENSE +191 -0
  5. package/README.md +30 -0
  6. package/dist/src/index.d.ts +6 -0
  7. package/dist/src/index.d.ts.map +1 -0
  8. package/dist/src/index.js +22 -0
  9. package/dist/src/lib/constants.d.ts +16 -0
  10. package/dist/src/lib/constants.d.ts.map +1 -0
  11. package/dist/src/lib/constants.js +19 -0
  12. package/dist/src/lib/contractCallWrapper.d.ts +33 -0
  13. package/dist/src/lib/contractCallWrapper.d.ts.map +1 -0
  14. package/dist/src/lib/contractCallWrapper.js +71 -0
  15. package/dist/src/lib/errors.d.ts +5 -0
  16. package/dist/src/lib/errors.d.ts.map +1 -0
  17. package/dist/src/lib/errors.js +12 -0
  18. package/dist/src/lib/fungibleTokenTransferBuilder.d.ts +64 -0
  19. package/dist/src/lib/fungibleTokenTransferBuilder.d.ts.map +1 -0
  20. package/dist/src/lib/fungibleTokenTransferBuilder.js +158 -0
  21. package/dist/src/lib/iface.d.ts +42 -0
  22. package/dist/src/lib/iface.d.ts.map +1 -0
  23. package/dist/src/lib/iface.js +3 -0
  24. package/dist/src/lib/index.d.ts +13 -0
  25. package/dist/src/lib/index.d.ts.map +1 -0
  26. package/dist/src/lib/index.js +59 -0
  27. package/dist/src/lib/keyPair.d.ts +25 -0
  28. package/dist/src/lib/keyPair.d.ts.map +1 -0
  29. package/dist/src/lib/keyPair.js +86 -0
  30. package/dist/src/lib/stakingActivateBuilder.d.ts +32 -0
  31. package/dist/src/lib/stakingActivateBuilder.d.ts.map +1 -0
  32. package/dist/src/lib/stakingActivateBuilder.js +105 -0
  33. package/dist/src/lib/stakingDeactivateBuilder.d.ts +32 -0
  34. package/dist/src/lib/stakingDeactivateBuilder.d.ts.map +1 -0
  35. package/dist/src/lib/stakingDeactivateBuilder.js +104 -0
  36. package/dist/src/lib/stakingWithdrawBuilder.d.ts +32 -0
  37. package/dist/src/lib/stakingWithdrawBuilder.d.ts.map +1 -0
  38. package/dist/src/lib/stakingWithdrawBuilder.js +104 -0
  39. package/dist/src/lib/storageDepositTransferBuilder.d.ts +36 -0
  40. package/dist/src/lib/storageDepositTransferBuilder.d.ts.map +1 -0
  41. package/dist/src/lib/storageDepositTransferBuilder.js +115 -0
  42. package/dist/src/lib/transaction.d.ts +117 -0
  43. package/dist/src/lib/transaction.d.ts.map +1 -0
  44. package/dist/src/lib/transaction.js +613 -0
  45. package/dist/src/lib/transactionBuilder.d.ts +95 -0
  46. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  47. package/dist/src/lib/transactionBuilder.js +241 -0
  48. package/dist/src/lib/transactionBuilderFactory.d.ts +34 -0
  49. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -0
  50. package/dist/src/lib/transactionBuilderFactory.js +84 -0
  51. package/dist/src/lib/transferBuilder.d.ts +26 -0
  52. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  53. package/dist/src/lib/transferBuilder.js +87 -0
  54. package/dist/src/lib/utils.d.ts +71 -0
  55. package/dist/src/lib/utils.d.ts.map +1 -0
  56. package/dist/src/lib/utils.js +139 -0
  57. package/dist/src/lib/walletInitializationBuilder.d.ts +12 -0
  58. package/dist/src/lib/walletInitializationBuilder.d.ts.map +1 -0
  59. package/dist/src/lib/walletInitializationBuilder.js +20 -0
  60. package/dist/src/near.d.ts +217 -0
  61. package/dist/src/near.d.ts.map +1 -0
  62. package/dist/src/near.js +853 -0
  63. package/dist/src/nep141Token.d.ts +20 -0
  64. package/dist/src/nep141Token.d.ts.map +1 -0
  65. package/dist/src/nep141Token.js +101 -0
  66. package/dist/src/register.d.ts +3 -0
  67. package/dist/src/register.d.ts.map +1 -0
  68. package/dist/src/register.js +15 -0
  69. package/dist/src/tnear.d.ts +7 -0
  70. package/dist/src/tnear.d.ts.map +1 -0
  71. package/dist/src/tnear.js +11 -0
  72. package/package.json +63 -0
@@ -0,0 +1,613 @@
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.Transaction = void 0;
40
+ const bs58_1 = __importDefault(require("bs58"));
41
+ const js_sha256_1 = require("js-sha256");
42
+ const nearAPI = __importStar(require("near-api-js"));
43
+ const transaction_1 = require("near-api-js/lib/transaction");
44
+ const crypto_1 = require("@near-js/crypto");
45
+ const transactions_1 = require("@near-js/transactions");
46
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
47
+ const constants_1 = require("./constants");
48
+ const keyPair_1 = require("./keyPair");
49
+ const utils_1 = __importDefault(require("./utils"));
50
+ class Transaction extends sdk_core_1.BaseTransaction {
51
+ constructor(coinConfig) {
52
+ super(coinConfig);
53
+ }
54
+ get nearTransaction() {
55
+ return this._nearTransaction;
56
+ }
57
+ set nearTransaction(tx) {
58
+ this._nearTransaction = tx;
59
+ this._id = utils_1.default.base58Encode(this.getTransactionHash());
60
+ }
61
+ /** @inheritdoc */
62
+ canSign(key) {
63
+ try {
64
+ new keyPair_1.KeyPair({ prv: key.key });
65
+ return true;
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ }
71
+ /** @inheritdoc */
72
+ toBroadcastFormat() {
73
+ if (!this._nearTransaction) {
74
+ throw new sdk_core_1.InvalidTransactionError('Empty transaction data');
75
+ }
76
+ const txSeralized = this._nearSignedTransaction
77
+ ? Buffer.from(this._nearSignedTransaction.encode()).toString('base64')
78
+ : Buffer.from(this._nearTransaction.encode()).toString('base64');
79
+ return txSeralized;
80
+ }
81
+ /** @inheritdoc */
82
+ toJson() {
83
+ if (!this._nearTransaction) {
84
+ throw new sdk_core_1.InvalidTransactionError('Empty transaction data');
85
+ }
86
+ const parsedActions = [];
87
+ const actions = this._nearTransaction.actions;
88
+ actions.map((action) => {
89
+ let parsedAction = {};
90
+ if (action.enum === 'transfer' && action.transfer) {
91
+ parsedAction = { transfer: action.transfer };
92
+ }
93
+ else if (action.enum === 'functionCall' && action.functionCall) {
94
+ const functionCall = action.functionCall;
95
+ parsedAction = {
96
+ functionCall: {
97
+ methodName: functionCall.methodName,
98
+ args: JSON.parse(Buffer.from(functionCall.args).toString()),
99
+ gas: functionCall.gas.toString(),
100
+ deposit: functionCall.deposit.toString(),
101
+ },
102
+ };
103
+ }
104
+ parsedActions.push(parsedAction);
105
+ });
106
+ let signature;
107
+ if (this._nearSignedTransaction?.signature?.ed25519Signature) {
108
+ signature = {
109
+ keyType: crypto_1.KeyType.ED25519,
110
+ data: new Uint8Array(this._nearSignedTransaction.signature.ed25519Signature.data),
111
+ };
112
+ }
113
+ let publicKey;
114
+ if (this._nearTransaction.publicKey?.ed25519Key) {
115
+ const rawBytes = new Uint8Array(this._nearTransaction.publicKey.ed25519Key.data);
116
+ const encoded = nearAPI.utils.serialize.base_encode(rawBytes);
117
+ publicKey = `ed25519:${encoded}`;
118
+ }
119
+ return {
120
+ id: this._id,
121
+ signerId: this._nearTransaction.signerId,
122
+ publicKey: publicKey,
123
+ nonce: this._nearTransaction.nonce,
124
+ receiverId: this._nearTransaction.receiverId,
125
+ actions: parsedActions,
126
+ signature: signature ? signature : undefined,
127
+ };
128
+ }
129
+ /**
130
+ * Set the transaction type.
131
+ *
132
+ * @param {TransactionType} transactionType The transaction type to be set.
133
+ */
134
+ setTransactionType(transactionType) {
135
+ this._type = transactionType;
136
+ }
137
+ /**
138
+ * Sets this transaction payload
139
+ *
140
+ * @param rawTx
141
+ */
142
+ fromRawTransaction(rawTx) {
143
+ const bufferRawTransaction = constants_1.HEX_REGEX.test(rawTx) ? Buffer.from(rawTx, 'hex') : Buffer.from(rawTx, 'base64');
144
+ try {
145
+ const signedTx = nearAPI.utils.serialize.deserialize(nearAPI.transactions.SCHEMA.SignedTransaction, bufferRawTransaction);
146
+ signedTx.transaction.actions = signedTx.transaction.actions.map((a) => {
147
+ const action = new transactions_1.Action(a);
148
+ switch (action.enum) {
149
+ case 'transfer': {
150
+ if (action.transfer?.deposit) {
151
+ return (0, transaction_1.transfer)(BigInt(action.transfer.deposit));
152
+ }
153
+ break;
154
+ }
155
+ case 'functionCall': {
156
+ if (action.functionCall) {
157
+ return (0, transaction_1.functionCall)(action.functionCall.methodName, new Uint8Array(action.functionCall.args), BigInt(action.functionCall.gas), BigInt(action.functionCall.deposit));
158
+ }
159
+ break;
160
+ }
161
+ }
162
+ return action;
163
+ });
164
+ this._nearSignedTransaction = signedTx;
165
+ this._nearTransaction = signedTx.transaction;
166
+ this._id = utils_1.default.base58Encode(this.getTransactionHash());
167
+ }
168
+ catch (e) {
169
+ try {
170
+ const unsignedTx = nearAPI.utils.serialize.deserialize(nearAPI.transactions.SCHEMA.Transaction, bufferRawTransaction);
171
+ unsignedTx.actions = unsignedTx.actions.map((a) => {
172
+ const action = new transactions_1.Action(a);
173
+ switch (action.enum) {
174
+ case 'transfer': {
175
+ if (action.transfer?.deposit) {
176
+ return (0, transaction_1.transfer)(BigInt(action.transfer.deposit));
177
+ }
178
+ break;
179
+ }
180
+ case 'functionCall': {
181
+ if (action.functionCall) {
182
+ return (0, transaction_1.functionCall)(action.functionCall.methodName, new Uint8Array(action.functionCall.args), BigInt(action.functionCall.gas), BigInt(action.functionCall.deposit));
183
+ }
184
+ break;
185
+ }
186
+ }
187
+ return action;
188
+ });
189
+ this._nearTransaction = unsignedTx;
190
+ this._id = utils_1.default.base58Encode(this.getTransactionHash());
191
+ }
192
+ catch (e) {
193
+ throw new sdk_core_1.InvalidTransactionError('unable to build transaction from raw');
194
+ }
195
+ }
196
+ this.loadInputsAndOutputs();
197
+ }
198
+ /**
199
+ * Sign this transaction
200
+ *
201
+ * @param {KeyPair} signer key
202
+ */
203
+ sign(signer) {
204
+ if (!this._nearTransaction) {
205
+ throw new sdk_core_1.InvalidTransactionError('empty transaction to sign');
206
+ }
207
+ const serializedTxHash = this.getTransactionHash();
208
+ const signature = signer.signMessageinUint8Array(serializedTxHash);
209
+ this._nearSignedTransaction = new nearAPI.transactions.SignedTransaction({
210
+ transaction: this._nearTransaction,
211
+ signature: new nearAPI.transactions.Signature({
212
+ keyType: this._nearTransaction.publicKey.keyType,
213
+ data: signature,
214
+ }),
215
+ });
216
+ this.loadInputsAndOutputs();
217
+ }
218
+ /**
219
+ * set transaction type by staking contract method names.
220
+ * @param methodName method name to match and set the transaction type
221
+ */
222
+ setTypeByFunctionCall(methodName) {
223
+ switch (methodName) {
224
+ case constants_1.StakingContractMethodNames.DepositAndStake:
225
+ this.setTransactionType(sdk_core_1.TransactionType.StakingActivate);
226
+ break;
227
+ case constants_1.StakingContractMethodNames.Unstake:
228
+ this.setTransactionType(sdk_core_1.TransactionType.StakingDeactivate);
229
+ break;
230
+ case constants_1.StakingContractMethodNames.Withdraw:
231
+ this.setTransactionType(sdk_core_1.TransactionType.StakingWithdraw);
232
+ break;
233
+ case constants_1.FT_TRANSFER:
234
+ this.setTransactionType(sdk_core_1.TransactionType.Send);
235
+ break;
236
+ case constants_1.STORAGE_DEPOSIT:
237
+ this.setTransactionType(sdk_core_1.TransactionType.StorageDeposit);
238
+ break;
239
+ }
240
+ }
241
+ /**
242
+ * Check if method is allowed on Near account-lib implementation.
243
+ * This method should check on all contracts added to Near.
244
+ * @param methodName contract call method name to check if it's allowed.
245
+ */
246
+ validateMethodAllowed(methodName) {
247
+ const allowedMethods = [...Object.values(constants_1.StakingContractMethodNames), ...constants_1.FUNGIBLE_TOKEN_RELATED_METHODS];
248
+ if (!allowedMethods.includes(methodName)) {
249
+ throw new sdk_core_1.InvalidTransactionError('unsupported function call in raw transaction');
250
+ }
251
+ }
252
+ /**
253
+ * Check if valid methods are present for batching of actions
254
+ *
255
+ * @param {TxAction[]} actions list of near transaction actions
256
+ * @returns {void}
257
+ */
258
+ validateBatchingMethods(actions) {
259
+ actions.every((action) => {
260
+ if (action.enum !== 'functionCall' || !action.functionCall) {
261
+ throw new sdk_core_1.InvalidTransactionError('invalid action for batching');
262
+ }
263
+ });
264
+ if (actions[0].functionCall?.methodName !== constants_1.STORAGE_DEPOSIT ||
265
+ actions[1].functionCall?.methodName !== constants_1.FT_TRANSFER) {
266
+ throw new sdk_core_1.InvalidTransactionError('invalid action sequence: expected storage_deposit followed by ft_transfer');
267
+ }
268
+ }
269
+ /**
270
+ * Build input and output field for this transaction
271
+ *
272
+ */
273
+ loadInputsAndOutputs() {
274
+ if (!this._nearTransaction.actions || !this._nearTransaction.actions.length) {
275
+ throw new sdk_core_1.InvalidTransactionError('no actions in raw transaction');
276
+ }
277
+ // TODO: modify this for send-many support
278
+ // currently only storage deposit + ft transfer are allowed for batching
279
+ if (this._nearTransaction.actions.length > 2) {
280
+ throw new sdk_core_1.InvalidTransactionError('too many actions in raw transaction');
281
+ }
282
+ // check for correct sequence of actions
283
+ if (this._nearTransaction.actions.length === 2) {
284
+ this.validateBatchingMethods(this._nearTransaction.actions);
285
+ }
286
+ const action = this._nearTransaction.actions[0];
287
+ const actions = this._nearTransaction.actions;
288
+ switch (action.enum) {
289
+ case 'transfer':
290
+ this.setTransactionType(sdk_core_1.TransactionType.Send);
291
+ break;
292
+ case 'functionCall':
293
+ if (action.functionCall) {
294
+ const methodName = action.functionCall.methodName;
295
+ this.validateMethodAllowed(methodName);
296
+ this.setTypeByFunctionCall(methodName);
297
+ }
298
+ break;
299
+ default:
300
+ throw new sdk_core_1.InvalidTransactionError('unsupported action in raw transaction');
301
+ }
302
+ // if there are 2 actions, we know for sure that it is storage deposit + ft transfer
303
+ if (actions.length === 2) {
304
+ this.setTransactionType(sdk_core_1.TransactionType.Send);
305
+ }
306
+ const outputs = [];
307
+ const inputs = [];
308
+ actions.map((action) => {
309
+ switch (this.type) {
310
+ case sdk_core_1.TransactionType.Send:
311
+ if (action.transfer) {
312
+ const amount = action.transfer.deposit.toString();
313
+ inputs.push({
314
+ address: this._nearTransaction.signerId,
315
+ value: amount,
316
+ coin: this._coinConfig.name,
317
+ });
318
+ outputs.push({
319
+ address: this._nearTransaction.receiverId,
320
+ value: amount,
321
+ coin: this._coinConfig.name,
322
+ });
323
+ }
324
+ else if (action.functionCall) {
325
+ if (action.functionCall.methodName === 'ft_transfer') {
326
+ const parsedArgs = JSON.parse(Buffer.from(action.functionCall.args).toString());
327
+ inputs.push({
328
+ address: this._nearTransaction.signerId,
329
+ value: parsedArgs.amount,
330
+ coin: this._coinConfig.name,
331
+ });
332
+ outputs.push({
333
+ address: parsedArgs.receiver_id,
334
+ value: parsedArgs.amount,
335
+ coin: this._coinConfig.name,
336
+ });
337
+ }
338
+ }
339
+ break;
340
+ case sdk_core_1.TransactionType.StakingActivate:
341
+ if (action.functionCall) {
342
+ const stakingAmount = action.functionCall.deposit.toString();
343
+ inputs.push({
344
+ address: this._nearTransaction.signerId,
345
+ value: stakingAmount,
346
+ coin: this._coinConfig.name,
347
+ });
348
+ outputs.push({
349
+ address: this._nearTransaction.receiverId,
350
+ value: stakingAmount,
351
+ coin: this._coinConfig.name,
352
+ });
353
+ }
354
+ break;
355
+ case sdk_core_1.TransactionType.StakingWithdraw:
356
+ if (action.functionCall) {
357
+ const stakingWithdrawAmount = JSON.parse(Buffer.from(action.functionCall.args).toString()).amount;
358
+ inputs.push({
359
+ address: this._nearTransaction.receiverId,
360
+ value: stakingWithdrawAmount,
361
+ coin: this._coinConfig.name,
362
+ });
363
+ outputs.push({
364
+ address: this._nearTransaction.signerId,
365
+ value: stakingWithdrawAmount,
366
+ coin: this._coinConfig.name,
367
+ });
368
+ }
369
+ break;
370
+ case sdk_core_1.TransactionType.StorageDeposit:
371
+ break;
372
+ }
373
+ });
374
+ this._outputs = outputs;
375
+ this._inputs = inputs;
376
+ }
377
+ /**
378
+ * Returns a complete explanation for a transfer transaction
379
+ * @param {TxData} json The transaction data in json format
380
+ * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
381
+ * @returns {TransactionExplanation}
382
+ */
383
+ explainTransferTransaction(json, explanationResult) {
384
+ return {
385
+ ...explanationResult,
386
+ outputAmount: json.actions[0].transfer?.deposit.toString() || '',
387
+ outputs: [
388
+ {
389
+ address: json.receiverId,
390
+ amount: json.actions[0].transfer?.deposit.toString() || '',
391
+ },
392
+ ],
393
+ };
394
+ }
395
+ /**
396
+ * Returns a complete explanation for a staking activate transaction
397
+ * @param {TxData} json The transaction data in json format
398
+ * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
399
+ * @returns {TransactionExplanation}
400
+ */
401
+ explainStakingActivateTransaction(json, explanationResult) {
402
+ return {
403
+ ...explanationResult,
404
+ outputAmount: json.actions[0].functionCall?.deposit.toString() || '',
405
+ outputs: [
406
+ {
407
+ address: json.receiverId,
408
+ amount: json.actions[0].functionCall?.deposit.toString() || '',
409
+ },
410
+ ],
411
+ };
412
+ }
413
+ /**
414
+ * Returns a complete explanation for a staking withdraw transaction
415
+ * @param {TxData} json The transaction data in json format
416
+ * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
417
+ * @returns {TransactionExplanation}
418
+ */
419
+ explainStakingWithdrawTransaction(json, explanationResult) {
420
+ const amount = json.actions[0].functionCall?.args.amount;
421
+ return {
422
+ ...explanationResult,
423
+ outputAmount: amount,
424
+ outputs: [
425
+ {
426
+ address: json.signerId,
427
+ amount: amount,
428
+ },
429
+ ],
430
+ };
431
+ }
432
+ /**
433
+ * Calculates the total fungible token amount & total native near amount
434
+ *
435
+ * @param {Action[]} actions the list of delegate transaction actions
436
+ * @returns {String} either native near amount or fungible token amount
437
+ */
438
+ calculateTotalOutputAmount(actions) {
439
+ let hasFtTransfer = false;
440
+ let hasStorageDeposit = false;
441
+ let totalTokenAmount = BigInt(0);
442
+ let totalNearDeposit = BigInt(0);
443
+ for (const action of actions) {
444
+ if (action.functionCall) {
445
+ const functionCall = action.functionCall;
446
+ const methodName = functionCall.methodName;
447
+ const args = functionCall.args;
448
+ const deposit = BigInt(functionCall.deposit);
449
+ if (methodName === constants_1.FT_TRANSFER) {
450
+ hasFtTransfer = true;
451
+ const amountStr = args['amount'];
452
+ if (args.amount) {
453
+ totalTokenAmount += BigInt(amountStr);
454
+ }
455
+ }
456
+ if (methodName === constants_1.STORAGE_DEPOSIT) {
457
+ hasStorageDeposit = true;
458
+ totalNearDeposit += deposit;
459
+ }
460
+ }
461
+ }
462
+ if (hasFtTransfer) {
463
+ return totalTokenAmount.toString();
464
+ }
465
+ else if (hasStorageDeposit) {
466
+ return totalNearDeposit.toString();
467
+ }
468
+ return '';
469
+ }
470
+ /**
471
+ * Returns a complete explanation for a token transfer transaction
472
+ * @param {TxData} json The transaction data in json format
473
+ * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
474
+ * @returns {TransactionExplanation}
475
+ */
476
+ explainTokenTransferTransaction(json, explanationResult) {
477
+ const actions = json.actions;
478
+ const outputAmount = this.calculateTotalOutputAmount(actions);
479
+ const outputs = [];
480
+ actions.map((action) => {
481
+ if (action.functionCall) {
482
+ const functionCall = action.functionCall;
483
+ if (functionCall.methodName === constants_1.FT_TRANSFER) {
484
+ const amountStr = functionCall.args['amount'];
485
+ const receiverId = functionCall.args['receiver_id'];
486
+ // in ft transfer, the outer receiver id will be contract address of the token
487
+ const tokenName = utils_1.default.findTokenNameFromContractAddress(json.receiverId);
488
+ const output = {
489
+ address: receiverId,
490
+ amount: amountStr,
491
+ };
492
+ if (tokenName) {
493
+ output.tokenName = tokenName;
494
+ }
495
+ outputs.push(output);
496
+ }
497
+ }
498
+ });
499
+ return {
500
+ ...explanationResult,
501
+ outputAmount: outputAmount,
502
+ outputs: outputs,
503
+ };
504
+ }
505
+ /**
506
+ * Returns a complete explanation for a storage deposit transaction
507
+ * @param {TxData} json The transaction data in json format
508
+ * @param {TransactionExplanation} explanationResult The transaction explanation to be completed
509
+ * @returns {TransactionExplanation}
510
+ */
511
+ explainStorageDepositTransaction(json, explanationResult) {
512
+ const actions = json.actions;
513
+ const outputAmount = this.calculateTotalOutputAmount(actions);
514
+ const outputs = [];
515
+ actions.map((action) => {
516
+ if (action.functionCall) {
517
+ const functionCall = action.functionCall;
518
+ if (functionCall.methodName === constants_1.STORAGE_DEPOSIT) {
519
+ const receiverId = functionCall.args && functionCall.args['account_id']
520
+ ? functionCall.args['account_id']
521
+ : json.signerId;
522
+ // in storage deposit, the outer receiver id will be contract address of the token
523
+ const tokenName = utils_1.default.findTokenNameFromContractAddress(json.receiverId);
524
+ const output = {
525
+ address: receiverId,
526
+ amount: functionCall.deposit,
527
+ };
528
+ if (tokenName) {
529
+ output.tokenName = tokenName;
530
+ }
531
+ outputs.push(output);
532
+ }
533
+ }
534
+ });
535
+ return {
536
+ ...explanationResult,
537
+ outputAmount: outputAmount,
538
+ outputs: outputs,
539
+ };
540
+ }
541
+ /** @inheritdoc */
542
+ explainTransaction() {
543
+ const result = this.toJson();
544
+ const displayOrder = ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'];
545
+ const outputs = [];
546
+ const explanationResult = {
547
+ // txhash used to identify the transactions
548
+ id: result.id || '',
549
+ displayOrder,
550
+ outputAmount: '0',
551
+ changeAmount: '0',
552
+ changeOutputs: [],
553
+ outputs,
554
+ fee: { fee: '' },
555
+ type: this.type,
556
+ };
557
+ switch (this.type) {
558
+ case sdk_core_1.TransactionType.Send:
559
+ if (result.actions.length > 1 || result.actions[0].functionCall) {
560
+ return this.explainTokenTransferTransaction(result, explanationResult);
561
+ }
562
+ return this.explainTransferTransaction(result, explanationResult);
563
+ case sdk_core_1.TransactionType.StakingActivate:
564
+ return this.explainStakingActivateTransaction(result, explanationResult);
565
+ case sdk_core_1.TransactionType.StakingDeactivate:
566
+ return explanationResult;
567
+ case sdk_core_1.TransactionType.StakingWithdraw:
568
+ return this.explainStakingWithdrawTransaction(result, explanationResult);
569
+ case sdk_core_1.TransactionType.StorageDeposit:
570
+ return this.explainStorageDepositTransaction(result, explanationResult);
571
+ default:
572
+ throw new sdk_core_1.InvalidTransactionError('Transaction type not supported');
573
+ }
574
+ }
575
+ getTransactionHash() {
576
+ const serializedTx = nearAPI.utils.serialize.serialize(nearAPI.transactions.SCHEMA.Transaction, this._nearTransaction);
577
+ return new Uint8Array(js_sha256_1.sha256.array(serializedTx));
578
+ }
579
+ get signablePayload() {
580
+ if (!this._nearTransaction) {
581
+ throw new sdk_core_1.InvalidTransactionError('empty transaction');
582
+ }
583
+ return Buffer.from(this.getTransactionHash());
584
+ }
585
+ /**
586
+ * Constructs a signed payload using construct.signTx
587
+ * This method will be called during the build step if a TSS signature
588
+ * is added and will set the signTransaction which is the txHex that will be broadcasted
589
+ * As well as add the signature used to sign to the signature array in hex format
590
+ *
591
+ * @param {Buffer} signature The signature to be added to a near transaction
592
+ */
593
+ constructSignedPayload(signature) {
594
+ this._nearSignedTransaction = new nearAPI.transactions.SignedTransaction({
595
+ transaction: this._nearTransaction,
596
+ signature: new nearAPI.transactions.Signature({
597
+ keyType: this._nearTransaction.publicKey.keyType,
598
+ data: signature,
599
+ }),
600
+ });
601
+ this.loadInputsAndOutputs();
602
+ }
603
+ /** @inheritdoc **/
604
+ get signature() {
605
+ const signatures = [];
606
+ if (this._nearSignedTransaction && this._nearSignedTransaction.signature.ed25519Signature) {
607
+ signatures.push(bs58_1.default.encode(this._nearSignedTransaction.signature.ed25519Signature.data));
608
+ }
609
+ return signatures;
610
+ }
611
+ }
612
+ exports.Transaction = Transaction;
613
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUEwQjtBQUMxQix5Q0FBbUM7QUFDbkMscURBQXVDO0FBQ3ZDLDZEQUFxRTtBQUNyRSw0Q0FBMEM7QUFDMUMsd0RBQWtIO0FBRWxILG1EQVE4QjtBQUc5QiwyQ0FNcUI7QUFFckIsdUNBQW9DO0FBQ3BDLG9EQUE0QjtBQUU1QixNQUFhLFdBQVksU0FBUSwwQkFBZTtJQUk5QyxZQUFZLFVBQWdDO1FBQzFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7SUFFRCxJQUFJLGVBQWUsQ0FBQyxFQUFvQztRQUN0RCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEdBQUcsZUFBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsT0FBTyxDQUFDLEdBQVk7UUFDbEIsSUFBSSxDQUFDO1lBQ0gsSUFBSSxpQkFBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsc0JBQXNCO1lBQzdDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7WUFDdEUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ25FLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsTUFBTTtRQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksa0NBQXVCLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUM5RCxDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQWEsRUFBRSxDQUFDO1FBQ25DLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3JCLElBQUksWUFBWSxHQUFXLEVBQUUsQ0FBQztZQUM5QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssVUFBVSxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbEQsWUFBWSxHQUFHLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMvQyxDQUFDO2lCQUFNLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxjQUFjLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNqRSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDO2dCQUN6QyxZQUFZLEdBQUc7b0JBQ2IsWUFBWSxFQUFFO3dCQUNaLFVBQVUsRUFBRSxZQUFZLENBQUMsVUFBVTt3QkFDbkMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7d0JBQzNELEdBQUcsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRTt3QkFDaEMsT0FBTyxFQUFFLFlBQVksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFO3FCQUN6QztpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUNELGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLFNBQWdDLENBQUM7UUFDckMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLENBQUM7WUFDN0QsU0FBUyxHQUFHO2dCQUNWLE9BQU8sRUFBRSxnQkFBTyxDQUFDLE9BQU87Z0JBQ3hCLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQzthQUNsRixDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksU0FBNkIsQ0FBQztRQUNsQyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDaEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzlELFNBQVMsR0FBRyxXQUFXLE9BQU8sRUFBRSxDQUFDO1FBQ25DLENBQUM7UUFFRCxPQUFPO1lBQ0wsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHO1lBQ1osUUFBUSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRO1lBQ3hDLFNBQVMsRUFBRSxTQUFTO1lBQ3BCLEtBQUssRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSztZQUNsQyxVQUFVLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVU7WUFDNUMsT0FBTyxFQUFFLGFBQWE7WUFDdEIsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTO1NBQzdDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGtCQUFrQixDQUFDLGVBQWdDO1FBQ2pELElBQUksQ0FBQyxLQUFLLEdBQUcsZUFBZSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsa0JBQWtCLENBQUMsS0FBYTtRQUM5QixNQUFNLG9CQUFvQixHQUFHLHFCQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDOUcsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUNsRCxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFDN0Msb0JBQW9CLENBQ0EsQ0FBQztZQUN2QixRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtnQkFDcEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxxQkFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixRQUFRLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDcEIsS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDO3dCQUNoQixJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUM7NEJBQzdCLE9BQU8sSUFBQSxzQkFBUSxFQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7d0JBQ25ELENBQUM7d0JBQ0QsTUFBTTtvQkFDUixDQUFDO29CQUNELEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQzt3QkFDcEIsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7NEJBQ3hCLE9BQU8sSUFBQSwwQkFBWSxFQUNqQixNQUFNLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFDOUIsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFDeEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEVBQy9CLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUNwQyxDQUFDO3dCQUNKLENBQUM7d0JBQ0QsTUFBTTtvQkFDUixDQUFDO2dCQUNILENBQUM7Z0JBQ0QsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsUUFBUSxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDO1lBQzdDLElBQUksQ0FBQyxHQUFHLEdBQUcsZUFBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1FBQzNELENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsSUFBSSxDQUFDO2dCQUNILE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FDcEQsT0FBTyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUN2QyxvQkFBb0IsQ0FDRSxDQUFDO2dCQUN6QixVQUFVLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7b0JBQ2hELE1BQU0sTUFBTSxHQUFHLElBQUkscUJBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDL0IsUUFBUSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7d0JBQ3BCLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQzs0QkFDaEIsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDO2dDQUM3QixPQUFPLElBQUEsc0JBQVEsRUFBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDOzRCQUNuRCxDQUFDOzRCQUNELE1BQU07d0JBQ1IsQ0FBQzt3QkFDRCxLQUFLLGNBQWMsQ0FBQyxDQUFDLENBQUM7NEJBQ3BCLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dDQUN4QixPQUFPLElBQUEsMEJBQVksRUFDakIsTUFBTSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQzlCLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQ3hDLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUMvQixNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FDcEMsQ0FBQzs0QkFDSixDQUFDOzRCQUNELE1BQU07d0JBQ1IsQ0FBQztvQkFDSCxDQUFDO29CQUNELE9BQU8sTUFBTSxDQUFDO2dCQUNoQixDQUFDLENBQUMsQ0FBQztnQkFDSCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsVUFBVSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsR0FBRyxHQUFHLGVBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxNQUFNLElBQUksa0NBQXVCLENBQUMsc0NBQXNDLENBQUMsQ0FBQztZQUM1RSxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRDs7OztPQUlHO0lBRUgsSUFBSSxDQUFDLE1BQWU7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQ25ELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25FLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUM7WUFDdkUsV0FBVyxFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDbEMsU0FBUyxFQUFFLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUM7Z0JBQzVDLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLE9BQU87Z0JBQ2hELElBQUksRUFBRSxTQUFTO2FBQ2hCLENBQUM7U0FDSCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0sscUJBQXFCLENBQUMsVUFBa0I7UUFDOUMsUUFBUSxVQUFVLEVBQUUsQ0FBQztZQUNuQixLQUFLLHNDQUEwQixDQUFDLGVBQWU7Z0JBQzdDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQywwQkFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUN6RCxNQUFNO1lBQ1IsS0FBSyxzQ0FBMEIsQ0FBQyxPQUFPO2dCQUNyQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2dCQUMzRCxNQUFNO1lBQ1IsS0FBSyxzQ0FBMEIsQ0FBQyxRQUFRO2dCQUN0QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDekQsTUFBTTtZQUNSLEtBQUssdUJBQVc7Z0JBQ2QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLDBCQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzlDLE1BQU07WUFDUixLQUFLLDJCQUFlO2dCQUNsQixJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDeEQsTUFBTTtRQUNWLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLHFCQUFxQixDQUFDLFVBQWtCO1FBQzlDLE1BQU0sY0FBYyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLHNDQUEwQixDQUFDLEVBQUUsR0FBRywwQ0FBOEIsQ0FBQyxDQUFDO1FBQ3pHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDekMsTUFBTSxJQUFJLGtDQUF1QixDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDcEYsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLHVCQUF1QixDQUFDLE9BQW1CO1FBQ2pELE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUN2QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssY0FBYyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUMzRCxNQUFNLElBQUksa0NBQXVCLENBQUMsNkJBQTZCLENBQUMsQ0FBQztZQUNuRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUNFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsVUFBVSxLQUFLLDJCQUFlO1lBQ3ZELE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsVUFBVSxLQUFLLHVCQUFXLEVBQ25ELENBQUM7WUFDRCxNQUFNLElBQUksa0NBQXVCLENBQUMsMkVBQTJFLENBQUMsQ0FBQztRQUNqSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILG9CQUFvQjtRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDNUUsTUFBTSxJQUFJLGtDQUF1QixDQUFDLCtCQUErQixDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELDBDQUEwQztRQUMxQyx3RUFBd0U7UUFDeEUsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3QyxNQUFNLElBQUksa0NBQXVCLENBQUMscUNBQXFDLENBQUMsQ0FBQztRQUMzRSxDQUFDO1FBQ0Qsd0NBQXdDO1FBQ3hDLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM5RCxDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDO1FBRTlDLFFBQVEsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3BCLEtBQUssVUFBVTtnQkFDYixJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDOUMsTUFBTTtZQUNSLEtBQUssY0FBYztnQkFDakIsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ3hCLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDO29CQUNsRCxJQUFJLENBQUMscUJBQXFCLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ3ZDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDekMsQ0FBQztnQkFDRCxNQUFNO1lBQ1I7Z0JBQ0UsTUFBTSxJQUFJLGtDQUF1QixDQUFDLHVDQUF1QyxDQUFDLENBQUM7UUFDL0UsQ0FBQztRQUNELG9GQUFvRjtRQUNwRixJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLDBCQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFZLEVBQUUsQ0FBQztRQUM1QixNQUFNLE1BQU0sR0FBWSxFQUFFLENBQUM7UUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3JCLFFBQVEsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNsQixLQUFLLDBCQUFlLENBQUMsSUFBSTtvQkFDdkIsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7d0JBQ3BCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO3dCQUNsRCxNQUFNLENBQUMsSUFBSSxDQUFDOzRCQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUTs0QkFDdkMsS0FBSyxFQUFFLE1BQU07NEJBQ2IsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTt5QkFDNUIsQ0FBQyxDQUFDO3dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUM7NEJBQ1gsT0FBTyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVOzRCQUN6QyxLQUFLLEVBQUUsTUFBTTs0QkFDYixJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJO3lCQUM1QixDQUFDLENBQUM7b0JBQ0wsQ0FBQzt5QkFBTSxJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQzt3QkFDL0IsSUFBSSxNQUFNLENBQUMsWUFBWSxDQUFDLFVBQVUsS0FBSyxhQUFhLEVBQUUsQ0FBQzs0QkFDckQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQzs0QkFDaEYsTUFBTSxDQUFDLElBQUksQ0FBQztnQ0FDVixPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVE7Z0NBQ3ZDLEtBQUssRUFBRSxVQUFVLENBQUMsTUFBTTtnQ0FDeEIsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTs2QkFDNUIsQ0FBQyxDQUFDOzRCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0NBQ1gsT0FBTyxFQUFFLFVBQVUsQ0FBQyxXQUFXO2dDQUMvQixLQUFLLEVBQUUsVUFBVSxDQUFDLE1BQU07Z0NBQ3hCLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7NkJBQzVCLENBQUMsQ0FBQzt3QkFDTCxDQUFDO29CQUNILENBQUM7b0JBQ0QsTUFBTTtnQkFDUixLQUFLLDBCQUFlLENBQUMsZUFBZTtvQkFDbEMsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7d0JBQ3hCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO3dCQUM3RCxNQUFNLENBQUMsSUFBSSxDQUFDOzRCQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUTs0QkFDdkMsS0FBSyxFQUFFLGFBQWE7NEJBQ3BCLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7eUJBQzVCLENBQUMsQ0FBQzt3QkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDOzRCQUNYLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVTs0QkFDekMsS0FBSyxFQUFFLGFBQWE7NEJBQ3BCLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7eUJBQzVCLENBQUMsQ0FBQztvQkFDTCxDQUFDO29CQUNELE1BQU07Z0JBQ1IsS0FBSywwQkFBZSxDQUFDLGVBQWU7b0JBQ2xDLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO3dCQUN4QixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDO3dCQUNsRyxNQUFNLENBQUMsSUFBSSxDQUFDOzRCQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVTs0QkFDekMsS0FBSyxFQUFFLHFCQUFxQjs0QkFDNUIsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTt5QkFDNUIsQ0FBQyxDQUFDO3dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUM7NEJBQ1gsT0FBTyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFROzRCQUN2QyxLQUFLLEVBQUUscUJBQXFCOzRCQUM1QixJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJO3lCQUM1QixDQUFDLENBQUM7b0JBQ0wsQ0FBQztvQkFDRCxNQUFNO2dCQUNSLEtBQUssMEJBQWUsQ0FBQyxjQUFjO29CQUNqQyxNQUFNO1lBQ1YsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsMEJBQTBCLENBQUMsSUFBWSxFQUFFLGlCQUF5QztRQUNoRixPQUFPO1lBQ0wsR0FBRyxpQkFBaUI7WUFDcEIsWUFBWSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFO1lBQ2hFLE9BQU8sRUFBRTtnQkFDUDtvQkFDRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVU7b0JBQ3hCLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRTtpQkFDM0Q7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxpQ0FBaUMsQ0FBQyxJQUFZLEVBQUUsaUJBQXlDO1FBQ3ZGLE9BQU87WUFDTCxHQUFHLGlCQUFpQjtZQUNwQixZQUFZLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUU7WUFDcEUsT0FBTyxFQUFFO2dCQUNQO29CQUNFLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVTtvQkFDeEIsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFO2lCQUMvRDthQUNGO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGlDQUFpQyxDQUFDLElBQVksRUFBRSxpQkFBeUM7UUFDdkYsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQWdCLENBQUM7UUFDbkUsT0FBTztZQUNMLEdBQUcsaUJBQWlCO1lBQ3BCLFlBQVksRUFBRSxNQUFNO1lBQ3BCLE9BQU8sRUFBRTtnQkFDUDtvQkFDRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVE7b0JBQ3RCLE1BQU0sRUFBRSxNQUFNO2lCQUNmO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsMEJBQTBCLENBQUMsT0FBaUI7UUFDMUMsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksaUJBQWlCLEdBQUcsS0FBSyxDQUFDO1FBRTlCLElBQUksZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLElBQUksZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWpDLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7WUFDN0IsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3hCLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUM7Z0JBQ3pDLE1BQU0sVUFBVSxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUM7Z0JBQzNDLE1BQU0sSUFBSSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUM7Z0JBQy9CLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzdDLElBQUksVUFBVSxLQUFLLHVCQUFXLEVBQUUsQ0FBQztvQkFDL0IsYUFBYSxHQUFHLElBQUksQ0FBQztvQkFDckIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBVyxDQUFDO29CQUMzQyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQzt3QkFDaEIsZ0JBQWdCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUN4QyxDQUFDO2dCQUNILENBQUM7Z0JBQ0QsSUFBSSxVQUFVLEtBQUssMkJBQWUsRUFBRSxDQUFDO29CQUNuQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7b0JBQ3pCLGdCQUFnQixJQUFJLE9BQU8sQ0FBQztnQkFDOUIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixPQUFPLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JDLENBQUM7YUFBTSxJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDN0IsT0FBTyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNyQyxDQUFDO1FBQ0QsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCwrQkFBK0IsQ0FBQyxJQUFZLEVBQUUsaUJBQXlDO1FBQ3JGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDN0IsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlELE1BQU0sT0FBTyxHQUE0QixFQUFFLENBQUM7UUFDNUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3JCLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUN4QixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDO2dCQUN6QyxJQUFJLFlBQVksQ0FBQyxVQUFVLEtBQUssdUJBQVcsRUFBRSxDQUFDO29CQUM1QyxNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBVyxDQUFDO29CQUN4RCxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBVyxDQUFDO29CQUM5RCw4RUFBOEU7b0JBQzlFLE1BQU0sU0FBUyxHQUFHLGVBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQzFFLE1BQU0sTUFBTSxHQUEwQjt3QkFDcEMsT0FBTyxFQUFFLFVBQVU7d0JBQ25CLE1BQU0sRUFBRSxTQUFTO3FCQUNsQixDQUFDO29CQUNGLElBQUksU0FBUyxFQUFFLENBQUM7d0JBQ2QsTUFBTSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7b0JBQy9CLENBQUM7b0JBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDdkIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU87WUFDTCxHQUFHLGlCQUFpQjtZQUNwQixZQUFZLEVBQUUsWUFBWTtZQUMxQixPQUFPLEVBQUUsT0FBTztTQUNqQixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZ0NBQWdDLENBQUMsSUFBWSxFQUFFLGlCQUF5QztRQUN0RixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQzdCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM5RCxNQUFNLE9BQU8sR0FBNEIsRUFBRSxDQUFDO1FBQzVDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNyQixJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDeEIsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQztnQkFDekMsSUFBSSxZQUFZLENBQUMsVUFBVSxLQUFLLDJCQUFlLEVBQUUsQ0FBQztvQkFDaEQsTUFBTSxVQUFVLEdBQ2QsWUFBWSxDQUFDLElBQUksSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQzt3QkFDbEQsQ0FBQyxDQUFFLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFZO3dCQUM3QyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztvQkFDcEIsa0ZBQWtGO29CQUNsRixNQUFNLFNBQVMsR0FBRyxlQUFLLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUMxRSxNQUFNLE1BQU0sR0FBMEI7d0JBQ3BDLE9BQU8sRUFBRSxVQUFVO3dCQUNuQixNQUFNLEVBQUUsWUFBWSxDQUFDLE9BQU87cUJBQzdCLENBQUM7b0JBQ0YsSUFBSSxTQUFTLEVBQUUsQ0FBQzt3QkFDZCxNQUFNLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztvQkFDL0IsQ0FBQztvQkFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUN2QixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTztZQUNMLEdBQUcsaUJBQWlCO1lBQ3BCLFlBQVksRUFBRSxZQUFZO1lBQzFCLE9BQU8sRUFBRSxPQUFPO1NBQ2pCLENBQUM7SUFDSixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGtCQUFrQjtRQUNoQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDN0IsTUFBTSxZQUFZLEdBQUcsQ0FBQyxjQUFjLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pHLE1BQU0sT0FBTyxHQUEyQixFQUFFLENBQUM7UUFDM0MsTUFBTSxpQkFBaUIsR0FBMkI7WUFDaEQsMkNBQTJDO1lBQzNDLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUU7WUFDbkIsWUFBWTtZQUNaLFlBQVksRUFBRSxHQUFHO1lBQ2pCLFlBQVksRUFBRSxHQUFHO1lBQ2pCLGFBQWEsRUFBRSxFQUFFO1lBQ2pCLE9BQU87WUFDUCxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFO1lBQ2hCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtTQUNoQixDQUFDO1FBQ0YsUUFBUSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsS0FBSywwQkFBZSxDQUFDLElBQUk7Z0JBQ3ZCLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ2hFLE9BQU8sSUFBSSxDQUFDLCtCQUErQixDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO2dCQUN6RSxDQUFDO2dCQUNELE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3BFLEtBQUssMEJBQWUsQ0FBQyxlQUFlO2dCQUNsQyxPQUFPLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUMzRSxLQUFLLDBCQUFlLENBQUMsaUJBQWlCO2dCQUNwQyxPQUFPLGlCQUFpQixDQUFDO1lBQzNCLEtBQUssMEJBQWUsQ0FBQyxlQUFlO2dCQUNsQyxPQUFPLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUMzRSxLQUFLLDBCQUFlLENBQUMsY0FBYztnQkFDakMsT0FBTyxJQUFJLENBQUMsZ0NBQWdDLENBQUMsTUFBTSxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFDMUU7Z0JBQ0UsTUFBTSxJQUFJLGtDQUF1QixDQUFDLGdDQUFnQyxDQUFDLENBQUM7UUFDeEUsQ0FBQztJQUNILENBQUM7SUFFTyxrQkFBa0I7UUFDeEIsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUNwRCxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsQ0FDdEIsQ0FBQztRQUNGLE9BQU8sSUFBSSxVQUFVLENBQUMsa0JBQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksa0NBQXVCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxzQkFBc0IsQ0FBQyxTQUFpQjtRQUN0QyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDO1lBQ3ZFLFdBQVcsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO1lBQ2xDLFNBQVMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDO2dCQUM1QyxPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxPQUFPO2dCQUNoRCxJQUFJLEVBQUUsU0FBUzthQUNoQixDQUFDO1NBQ0gsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUNELG1CQUFtQjtJQUNuQixJQUFJLFNBQVM7UUFDWCxNQUFNLFVBQVUsR0FBYSxFQUFFLENBQUM7UUFFaEMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFGLFVBQVUsQ0FBQyxJQUFJLENBQUMsY0FBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDOUYsQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7Q0FDRjtBQXRtQkQsa0NBc21CQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBiYXNlNTggZnJvbSAnYnM1OCc7XG5pbXBvcnQgeyBzaGEyNTYgfSBmcm9tICdqcy1zaGEyNTYnO1xuaW1wb3J0ICogYXMgbmVhckFQSSBmcm9tICduZWFyLWFwaS1qcyc7XG5pbXBvcnQgeyBmdW5jdGlvbkNhbGwsIHRyYW5zZmVyIH0gZnJvbSAnbmVhci1hcGktanMvbGliL3RyYW5zYWN0aW9uJztcbmltcG9ydCB7IEtleVR5cGUgfSBmcm9tICdAbmVhci1qcy9jcnlwdG8nO1xuaW1wb3J0IHsgQWN0aW9uIGFzIFR4QWN0aW9uLCBTaWduZWRUcmFuc2FjdGlvbiwgVHJhbnNhY3Rpb24gYXMgVW5zaWduZWRUcmFuc2FjdGlvbiB9IGZyb20gJ0BuZWFyLWpzL3RyYW5zYWN0aW9ucyc7XG5cbmltcG9ydCB7XG4gIEJhc2VLZXksXG4gIEJhc2VUcmFuc2FjdGlvbixcbiAgRW50cnksXG4gIEludmFsaWRUcmFuc2FjdGlvbkVycm9yLFxuICBJVHJhbnNhY3Rpb25SZWNpcGllbnQsXG4gIFRyYW5zYWN0aW9uUmVjaXBpZW50LFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IEJhc2VDb2luIGFzIENvaW5Db25maWcgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcblxuaW1wb3J0IHtcbiAgRlRfVFJBTlNGRVIsXG4gIEZVTkdJQkxFX1RPS0VOX1JFTEFURURfTUVUSE9EUyxcbiAgSEVYX1JFR0VYLFxuICBTdGFraW5nQ29udHJhY3RNZXRob2ROYW1lcyxcbiAgU1RPUkFHRV9ERVBPU0lULFxufSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBBY3Rpb24sIFNpZ25hdHVyZSwgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiwgVHhEYXRhIH0gZnJvbSAnLi9pZmFjZSc7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCB1dGlscyBmcm9tICcuL3V0aWxzJztcblxuZXhwb3J0IGNsYXNzIFRyYW5zYWN0aW9uIGV4dGVuZHMgQmFzZVRyYW5zYWN0aW9uIHtcbiAgcHJpdmF0ZSBfbmVhclRyYW5zYWN0aW9uOiBuZWFyQVBJLnRyYW5zYWN0aW9ucy5UcmFuc2FjdGlvbjtcbiAgcHJpdmF0ZSBfbmVhclNpZ25lZFRyYW5zYWN0aW9uOiBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduZWRUcmFuc2FjdGlvbjtcblxuICBjb25zdHJ1Y3Rvcihjb2luQ29uZmlnOiBSZWFkb25seTxDb2luQ29uZmlnPikge1xuICAgIHN1cGVyKGNvaW5Db25maWcpO1xuICB9XG5cbiAgZ2V0IG5lYXJUcmFuc2FjdGlvbigpOiBuZWFyQVBJLnRyYW5zYWN0aW9ucy5UcmFuc2FjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX25lYXJUcmFuc2FjdGlvbjtcbiAgfVxuXG4gIHNldCBuZWFyVHJhbnNhY3Rpb24odHg6IG5lYXJBUEkudHJhbnNhY3Rpb25zLlRyYW5zYWN0aW9uKSB7XG4gICAgdGhpcy5fbmVhclRyYW5zYWN0aW9uID0gdHg7XG4gICAgdGhpcy5faWQgPSB1dGlscy5iYXNlNThFbmNvZGUodGhpcy5nZXRUcmFuc2FjdGlvbkhhc2goKSk7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgY2FuU2lnbihrZXk6IEJhc2VLZXkpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdG9Ccm9hZGNhc3RGb3JtYXQoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuX25lYXJUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdFbXB0eSB0cmFuc2FjdGlvbiBkYXRhJyk7XG4gICAgfVxuICAgIGNvbnN0IHR4U2VyYWxpemVkID0gdGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uXG4gICAgICA/IEJ1ZmZlci5mcm9tKHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbi5lbmNvZGUoKSkudG9TdHJpbmcoJ2Jhc2U2NCcpXG4gICAgICA6IEJ1ZmZlci5mcm9tKHRoaXMuX25lYXJUcmFuc2FjdGlvbi5lbmNvZGUoKSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIHJldHVybiB0eFNlcmFsaXplZDtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB0b0pzb24oKTogVHhEYXRhIHtcbiAgICBpZiAoIXRoaXMuX25lYXJUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdFbXB0eSB0cmFuc2FjdGlvbiBkYXRhJyk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyc2VkQWN0aW9uczogQWN0aW9uW10gPSBbXTtcbiAgICBjb25zdCBhY3Rpb25zID0gdGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnM7XG4gICAgYWN0aW9ucy5tYXAoKGFjdGlvbikgPT4ge1xuICAgICAgbGV0IHBhcnNlZEFjdGlvbjogQWN0aW9uID0ge307XG4gICAgICBpZiAoYWN0aW9uLmVudW0gPT09ICd0cmFuc2ZlcicgJiYgYWN0aW9uLnRyYW5zZmVyKSB7XG4gICAgICAgIHBhcnNlZEFjdGlvbiA9IHsgdHJhbnNmZXI6IGFjdGlvbi50cmFuc2ZlciB9O1xuICAgICAgfSBlbHNlIGlmIChhY3Rpb24uZW51bSA9PT0gJ2Z1bmN0aW9uQ2FsbCcgJiYgYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICBjb25zdCBmdW5jdGlvbkNhbGwgPSBhY3Rpb24uZnVuY3Rpb25DYWxsO1xuICAgICAgICBwYXJzZWRBY3Rpb24gPSB7XG4gICAgICAgICAgZnVuY3Rpb25DYWxsOiB7XG4gICAgICAgICAgICBtZXRob2ROYW1lOiBmdW5jdGlvbkNhbGwubWV0aG9kTmFtZSxcbiAgICAgICAgICAgIGFyZ3M6IEpTT04ucGFyc2UoQnVmZmVyLmZyb20oZnVuY3Rpb25DYWxsLmFyZ3MpLnRvU3RyaW5nKCkpLFxuICAgICAgICAgICAgZ2FzOiBmdW5jdGlvbkNhbGwuZ2FzLnRvU3RyaW5nKCksXG4gICAgICAgICAgICBkZXBvc2l0OiBmdW5jdGlvbkNhbGwuZGVwb3NpdC50b1N0cmluZygpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBwYXJzZWRBY3Rpb25zLnB1c2gocGFyc2VkQWN0aW9uKTtcbiAgICB9KTtcblxuICAgIGxldCBzaWduYXR1cmU6IFNpZ25hdHVyZSB8IHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uPy5zaWduYXR1cmU/LmVkMjU1MTlTaWduYXR1cmUpIHtcbiAgICAgIHNpZ25hdHVyZSA9IHtcbiAgICAgICAga2V5VHlwZTogS2V5VHlwZS5FRDI1NTE5LFxuICAgICAgICBkYXRhOiBuZXcgVWludDhBcnJheSh0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb24uc2lnbmF0dXJlLmVkMjU1MTlTaWduYXR1cmUuZGF0YSksXG4gICAgICB9O1xuICAgIH1cbiAgICBsZXQgcHVibGljS2V5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHRoaXMuX25lYXJUcmFuc2FjdGlvbi5wdWJsaWNLZXk/LmVkMjU1MTlLZXkpIHtcbiAgICAgIGNvbnN0IHJhd0J5dGVzID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5fbmVhclRyYW5zYWN0aW9uLnB1YmxpY0tleS5lZDI1NTE5S2V5LmRhdGEpO1xuICAgICAgY29uc3QgZW5jb2RlZCA9IG5lYXJBUEkudXRpbHMuc2VyaWFsaXplLmJhc2VfZW5jb2RlKHJhd0J5dGVzKTtcbiAgICAgIHB1YmxpY0tleSA9IGBlZDI1NTE5OiR7ZW5jb2RlZH1gO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogdGhpcy5faWQsXG4gICAgICBzaWduZXJJZDogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnNpZ25lcklkLFxuICAgICAgcHVibGljS2V5OiBwdWJsaWNLZXksXG4gICAgICBub25jZTogdGhpcy5fbmVhclRyYW5zYWN0aW9uLm5vbmNlLFxuICAgICAgcmVjZWl2ZXJJZDogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnJlY2VpdmVySWQsXG4gICAgICBhY3Rpb25zOiBwYXJzZWRBY3Rpb25zLFxuICAgICAgc2lnbmF0dXJlOiBzaWduYXR1cmUgPyBzaWduYXR1cmUgOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIHRyYW5zYWN0aW9uIHR5cGUuXG4gICAqXG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25UeXBlfSB0cmFuc2FjdGlvblR5cGUgVGhlIHRyYW5zYWN0aW9uIHR5cGUgdG8gYmUgc2V0LlxuICAgKi9cbiAgc2V0VHJhbnNhY3Rpb25UeXBlKHRyYW5zYWN0aW9uVHlwZTogVHJhbnNhY3Rpb25UeXBlKTogdm9pZCB7XG4gICAgdGhpcy5fdHlwZSA9IHRyYW5zYWN0aW9uVHlwZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoaXMgdHJhbnNhY3Rpb24gcGF5bG9hZFxuICAgKlxuICAgKiBAcGFyYW0gcmF3VHhcbiAgICovXG4gIGZyb21SYXdUcmFuc2FjdGlvbihyYXdUeDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgYnVmZmVyUmF3VHJhbnNhY3Rpb24gPSBIRVhfUkVHRVgudGVzdChyYXdUeCkgPyBCdWZmZXIuZnJvbShyYXdUeCwgJ2hleCcpIDogQnVmZmVyLmZyb20ocmF3VHgsICdiYXNlNjQnKTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgc2lnbmVkVHggPSBuZWFyQVBJLnV0aWxzLnNlcmlhbGl6ZS5kZXNlcmlhbGl6ZShcbiAgICAgICAgbmVhckFQSS50cmFuc2FjdGlvbnMuU0NIRU1BLlNpZ25lZFRyYW5zYWN0aW9uLFxuICAgICAgICBidWZmZXJSYXdUcmFuc2FjdGlvblxuICAgICAgKSBhcyBTaWduZWRUcmFuc2FjdGlvbjtcbiAgICAgIHNpZ25lZFR4LnRyYW5zYWN0aW9uLmFjdGlvbnMgPSBzaWduZWRUeC50cmFuc2FjdGlvbi5hY3Rpb25zLm1hcCgoYSkgPT4ge1xuICAgICAgICBjb25zdCBhY3Rpb24gPSBuZXcgVHhBY3Rpb24oYSk7XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uLmVudW0pIHtcbiAgICAgICAgICBjYXNlICd0cmFuc2Zlcic6IHtcbiAgICAgICAgICAgIGlmIChhY3Rpb24udHJhbnNmZXI/LmRlcG9zaXQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHRyYW5zZmVyKEJpZ0ludChhY3Rpb24udHJhbnNmZXIuZGVwb3NpdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNhc2UgJ2Z1bmN0aW9uQ2FsbCc6IHtcbiAgICAgICAgICAgIGlmIChhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbkNhbGwoXG4gICAgICAgICAgICAgICAgYWN0aW9uLmZ1bmN0aW9uQ2FsbC5tZXRob2ROYW1lLFxuICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KGFjdGlvbi5mdW5jdGlvbkNhbGwuYXJncyksXG4gICAgICAgICAgICAgICAgQmlnSW50KGFjdGlvbi5mdW5jdGlvbkNhbGwuZ2FzKSxcbiAgICAgICAgICAgICAgICBCaWdJbnQoYWN0aW9uLmZ1bmN0aW9uQ2FsbC5kZXBvc2l0KVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3Rpb247XG4gICAgICB9KTtcbiAgICAgIHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbiA9IHNpZ25lZFR4O1xuICAgICAgdGhpcy5fbmVhclRyYW5zYWN0aW9uID0gc2lnbmVkVHgudHJhbnNhY3Rpb247XG4gICAgICB0aGlzLl9pZCA9IHV0aWxzLmJhc2U1OEVuY29kZSh0aGlzLmdldFRyYW5zYWN0aW9uSGFzaCgpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB1bnNpZ25lZFR4ID0gbmVhckFQSS51dGlscy5zZXJpYWxpemUuZGVzZXJpYWxpemUoXG4gICAgICAgICAgbmVhckFQSS50cmFuc2FjdGlvbnMuU0NIRU1BLlRyYW5zYWN0aW9uLFxuICAgICAgICAgIGJ1ZmZlclJhd1RyYW5zYWN0aW9uXG4gICAgICAgICkgYXMgVW5zaWduZWRUcmFuc2FjdGlvbjtcbiAgICAgICAgdW5zaWduZWRUeC5hY3Rpb25zID0gdW5zaWduZWRUeC5hY3Rpb25zLm1hcCgoYSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGFjdGlvbiA9IG5ldyBUeEFjdGlvbihhKTtcbiAgICAgICAgICBzd2l0Y2ggKGFjdGlvbi5lbnVtKSB7XG4gICAgICAgICAgICBjYXNlICd0cmFuc2Zlcic6IHtcbiAgICAgICAgICAgICAgaWYgKGFjdGlvbi50cmFuc2Zlcj8uZGVwb3NpdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFuc2ZlcihCaWdJbnQoYWN0aW9uLnRyYW5zZmVyLmRlcG9zaXQpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgJ2Z1bmN0aW9uQ2FsbCc6IHtcbiAgICAgICAgICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb25DYWxsKFxuICAgICAgICAgICAgICAgICAgYWN0aW9uLmZ1bmN0aW9uQ2FsbC5tZXRob2ROYW1lLFxuICAgICAgICAgICAgICAgICAgbmV3IFVpbnQ4QXJyYXkoYWN0aW9uLmZ1bmN0aW9uQ2FsbC5hcmdzKSxcbiAgICAgICAgICAgICAgICAgIEJpZ0ludChhY3Rpb24uZnVuY3Rpb25DYWxsLmdhcyksXG4gICAgICAgICAgICAgICAgICBCaWdJbnQoYWN0aW9uLmZ1bmN0aW9uQ2FsbC5kZXBvc2l0KVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBhY3Rpb247XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9uZWFyVHJhbnNhY3Rpb24gPSB1bnNpZ25lZFR4O1xuICAgICAgICB0aGlzLl9pZCA9IHV0aWxzLmJhc2U1OEVuY29kZSh0aGlzLmdldFRyYW5zYWN0aW9uSGFzaCgpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCd1bmFibGUgdG8gYnVpbGQgdHJhbnNhY3Rpb24gZnJvbSByYXcnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmxvYWRJbnB1dHNBbmRPdXRwdXRzKCk7XG4gIH1cblxuICAvKipcbiAgICogU2lnbiB0aGlzIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7S2V5UGFpcn0gc2lnbmVyIGtleVxuICAgKi9cblxuICBzaWduKHNpZ25lcjogS2V5UGFpcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5fbmVhclRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ2VtcHR5IHRyYW5zYWN0aW9uIHRvIHNpZ24nKTtcbiAgICB9XG4gICAgY29uc3Qgc2VyaWFsaXplZFR4SGFzaCA9IHRoaXMuZ2V0VHJhbnNhY3Rpb25IYXNoKCk7XG4gICAgY29uc3Qgc2lnbmF0dXJlID0gc2lnbmVyLnNpZ25NZXNzYWdlaW5VaW50OEFycmF5KHNlcmlhbGl6ZWRUeEhhc2gpO1xuICAgIHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbiA9IG5ldyBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICB0cmFuc2FjdGlvbjogdGhpcy5fbmVhclRyYW5zYWN0aW9uLFxuICAgICAgc2lnbmF0dXJlOiBuZXcgbmVhckFQSS50cmFuc2FjdGlvbnMuU2lnbmF0dXJlKHtcbiAgICAgICAga2V5VHlwZTogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnB1YmxpY0tleS5rZXlUeXBlLFxuICAgICAgICBkYXRhOiBzaWduYXR1cmUsXG4gICAgICB9KSxcbiAgICB9KTtcbiAgICB0aGlzLmxvYWRJbnB1dHNBbmRPdXRwdXRzKCk7XG4gIH1cblxuICAvKipcbiAgICogc2V0IHRyYW5zYWN0aW9uIHR5cGUgYnkgc3Rha2luZyBjb250cmFjdCBtZXRob2QgbmFtZXMuXG4gICAqIEBwYXJhbSBtZXRob2ROYW1lIG1ldGhvZCBuYW1lIHRvIG1hdGNoIGFuZCBzZXQgdGhlIHRyYW5zYWN0aW9uIHR5cGVcbiAgICovXG4gIHByaXZhdGUgc2V0VHlwZUJ5RnVuY3Rpb25DYWxsKG1ldGhvZE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHN3aXRjaCAobWV0aG9kTmFtZSkge1xuICAgICAgY2FzZSBTdGFraW5nQ29udHJhY3RNZXRob2ROYW1lcy5EZXBvc2l0QW5kU3Rha2U6XG4gICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgU3Rha2luZ0NvbnRyYWN0TWV0aG9kTmFtZXMuVW5zdGFrZTpcbiAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFN0YWtpbmdDb250cmFjdE1ldGhvZE5hbWVzLldpdGhkcmF3OlxuICAgICAgICB0aGlzLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1dpdGhkcmF3KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEZUX1RSQU5TRkVSOlxuICAgICAgICB0aGlzLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBTVE9SQUdFX0RFUE9TSVQ6XG4gICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdG9yYWdlRGVwb3NpdCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBtZXRob2QgaXMgYWxsb3dlZCBvbiBOZWFyIGFjY291bnQtbGliIGltcGxlbWVudGF0aW9uLlxuICAgKiBUaGlzIG1ldGhvZCBzaG91bGQgY2hlY2sgb24gYWxsIGNvbnRyYWN0cyBhZGRlZCB0byBOZWFyLlxuICAgKiBAcGFyYW0gbWV0aG9kTmFtZSBjb250cmFjdCBjYWxsIG1ldGhvZCBuYW1lIHRvIGNoZWNrIGlmIGl0J3MgYWxsb3dlZC5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVNZXRob2RBbGxvd2VkKG1ldGhvZE5hbWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGFsbG93ZWRNZXRob2RzID0gWy4uLk9iamVjdC52YWx1ZXMoU3Rha2luZ0NvbnRyYWN0TWV0aG9kTmFtZXMpLCAuLi5GVU5HSUJMRV9UT0tFTl9SRUxBVEVEX01FVEhPRFNdO1xuICAgIGlmICghYWxsb3dlZE1ldGhvZHMuaW5jbHVkZXMobWV0aG9kTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcigndW5zdXBwb3J0ZWQgZnVuY3Rpb24gY2FsbCBpbiByYXcgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdmFsaWQgbWV0aG9kcyBhcmUgcHJlc2VudCBmb3IgYmF0Y2hpbmcgb2YgYWN0aW9uc1xuICAgKlxuICAgKiBAcGFyYW0ge1R4QWN0aW9uW119IGFjdGlvbnMgbGlzdCBvZiBuZWFyIHRyYW5zYWN0aW9uIGFjdGlvbnNcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlQmF0Y2hpbmdNZXRob2RzKGFjdGlvbnM6IFR4QWN0aW9uW10pOiB2b2lkIHtcbiAgICBhY3Rpb25zLmV2ZXJ5KChhY3Rpb24pID0+IHtcbiAgICAgIGlmIChhY3Rpb24uZW51bSAhPT0gJ2Z1bmN0aW9uQ2FsbCcgfHwgIWFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdpbnZhbGlkIGFjdGlvbiBmb3IgYmF0Y2hpbmcnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoXG4gICAgICBhY3Rpb25zWzBdLmZ1bmN0aW9uQ2FsbD8ubWV0aG9kTmFtZSAhPT0gU1RPUkFHRV9ERVBPU0lUIHx8XG4gICAgICBhY3Rpb25zWzFdLmZ1bmN0aW9uQ2FsbD8ubWV0aG9kTmFtZSAhPT0gRlRfVFJBTlNGRVJcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignaW52YWxpZCBhY3Rpb24gc2VxdWVuY2U6IGV4cGVjdGVkIHN0b3JhZ2VfZGVwb3NpdCBmb2xsb3dlZCBieSBmdF90cmFuc2ZlcicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBpbnB1dCBhbmQgb3V0cHV0IGZpZWxkIGZvciB0aGlzIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqL1xuICBsb2FkSW5wdXRzQW5kT3V0cHV0cygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zIHx8ICF0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9ucy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignbm8gYWN0aW9ucyBpbiByYXcgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG4gICAgLy8gVE9ETzogbW9kaWZ5IHRoaXMgZm9yIHNlbmQtbWFueSBzdXBwb3J0XG4gICAgLy8gY3VycmVudGx5IG9ubHkgc3RvcmFnZSBkZXBvc2l0ICsgZnQgdHJhbnNmZXIgYXJlIGFsbG93ZWQgZm9yIGJhdGNoaW5nXG4gICAgaWYgKHRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zLmxlbmd0aCA+IDIpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcigndG9vIG1hbnkgYWN0aW9ucyBpbiByYXcgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG4gICAgLy8gY2hlY2sgZm9yIGNvcnJlY3Qgc2VxdWVuY2Ugb2YgYWN0aW9uc1xuICAgIGlmICh0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9ucy5sZW5ndGggPT09IDIpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVCYXRjaGluZ01ldGhvZHModGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnMpO1xuICAgIH1cblxuICAgIGNvbnN0IGFjdGlvbiA9IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zWzBdO1xuICAgIGNvbnN0IGFjdGlvbnMgPSB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9ucztcblxuICAgIHN3aXRjaCAoYWN0aW9uLmVudW0pIHtcbiAgICAgIGNhc2UgJ3RyYW5zZmVyJzpcbiAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Z1bmN0aW9uQ2FsbCc6XG4gICAgICAgIGlmIChhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgICAgY29uc3QgbWV0aG9kTmFtZSA9IGFjdGlvbi5mdW5jdGlvbkNhbGwubWV0aG9kTmFtZTtcbiAgICAgICAgICB0aGlzLnZhbGlkYXRlTWV0aG9kQWxsb3dlZChtZXRob2ROYW1lKTtcbiAgICAgICAgICB0aGlzLnNldFR5cGVCeUZ1bmN0aW9uQ2FsbChtZXRob2ROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcigndW5zdXBwb3J0ZWQgYWN0aW9uIGluIHJhdyB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICAvLyBpZiB0aGVyZSBhcmUgMiBhY3Rpb25zLCB3ZSBrbm93IGZvciBzdXJlIHRoYXQgaXQgaXMgc3RvcmFnZSBkZXBvc2l0ICsgZnQgdHJhbnNmZXJcbiAgICBpZiAoYWN0aW9ucy5sZW5ndGggPT09IDIpIHtcbiAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXRzOiBFbnRyeVtdID0gW107XG4gICAgY29uc3QgaW5wdXRzOiBFbnRyeVtdID0gW107XG4gICAgYWN0aW9ucy5tYXAoKGFjdGlvbikgPT4ge1xuICAgICAgc3dpdGNoICh0aGlzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZDpcbiAgICAgICAgICBpZiAoYWN0aW9uLnRyYW5zZmVyKSB7XG4gICAgICAgICAgICBjb25zdCBhbW91bnQgPSBhY3Rpb24udHJhbnNmZXIuZGVwb3NpdC50b1N0cmluZygpO1xuICAgICAgICAgICAgaW5wdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICAgICAgICAgIHZhbHVlOiBhbW91bnQsXG4gICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICAgICAgYWRkcmVzczogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnJlY2VpdmVySWQsXG4gICAgICAgICAgICAgIHZhbHVlOiBhbW91bnQsXG4gICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwubWV0aG9kTmFtZSA9PT0gJ2Z0X3RyYW5zZmVyJykge1xuICAgICAgICAgICAgICBjb25zdCBwYXJzZWRBcmdzID0gSlNPTi5wYXJzZShCdWZmZXIuZnJvbShhY3Rpb24uZnVuY3Rpb25DYWxsLmFyZ3MpLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgICAgICAgYWRkcmVzczogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnNpZ25lcklkLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBwYXJzZWRBcmdzLmFtb3VudCxcbiAgICAgICAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgICAgIGFkZHJlc3M6IHBhcnNlZEFyZ3MucmVjZWl2ZXJfaWQsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHBhcnNlZEFyZ3MuYW1vdW50LFxuICAgICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGU6XG4gICAgICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YWtpbmdBbW91bnQgPSBhY3Rpb24uZnVuY3Rpb25DYWxsLmRlcG9zaXQudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIGlucHV0cy5wdXNoKHtcbiAgICAgICAgICAgICAgYWRkcmVzczogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnNpZ25lcklkLFxuICAgICAgICAgICAgICB2YWx1ZTogc3Rha2luZ0Ftb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICAgICAgdmFsdWU6IHN0YWtpbmdBbW91bnQsXG4gICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1dpdGhkcmF3OlxuICAgICAgICAgIGlmIChhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgICAgICBjb25zdCBzdGFraW5nV2l0aGRyYXdBbW91bnQgPSBKU09OLnBhcnNlKEJ1ZmZlci5mcm9tKGFjdGlvbi5mdW5jdGlvbkNhbGwuYXJncykudG9TdHJpbmcoKSkuYW1vdW50O1xuICAgICAgICAgICAgaW5wdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICAgICAgdmFsdWU6IHN0YWtpbmdXaXRoZHJhd0Ftb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICAgICAgICAgIHZhbHVlOiBzdGFraW5nV2l0aGRyYXdBbW91bnQsXG4gICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3RvcmFnZURlcG9zaXQ6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5fb3V0cHV0cyA9IG91dHB1dHM7XG4gICAgdGhpcy5faW5wdXRzID0gaW5wdXRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb21wbGV0ZSBleHBsYW5hdGlvbiBmb3IgYSB0cmFuc2ZlciB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge1R4RGF0YX0ganNvbiBUaGUgdHJhbnNhY3Rpb24gZGF0YSBpbiBqc29uIGZvcm1hdFxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259IGV4cGxhbmF0aW9uUmVzdWx0IFRoZSB0cmFuc2FjdGlvbiBleHBsYW5hdGlvbiB0byBiZSBjb21wbGV0ZWRcbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259XG4gICAqL1xuICBleHBsYWluVHJhbnNmZXJUcmFuc2FjdGlvbihqc29uOiBUeERhdGEsIGV4cGxhbmF0aW9uUmVzdWx0OiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uKTogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBqc29uLmFjdGlvbnNbMF0udHJhbnNmZXI/LmRlcG9zaXQudG9TdHJpbmcoKSB8fCAnJyxcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IGpzb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICBhbW91bnQ6IGpzb24uYWN0aW9uc1swXS50cmFuc2Zlcj8uZGVwb3NpdC50b1N0cmluZygpIHx8ICcnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb21wbGV0ZSBleHBsYW5hdGlvbiBmb3IgYSBzdGFraW5nIGFjdGl2YXRlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7VHhEYXRhfSBqc29uIFRoZSB0cmFuc2FjdGlvbiBkYXRhIGluIGpzb24gZm9ybWF0XG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn0gZXhwbGFuYXRpb25SZXN1bHQgVGhlIHRyYW5zYWN0aW9uIGV4cGxhbmF0aW9uIHRvIGJlIGNvbXBsZXRlZFxuICAgKiBAcmV0dXJucyB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn1cbiAgICovXG4gIGV4cGxhaW5TdGFraW5nQWN0aXZhdGVUcmFuc2FjdGlvbihqc29uOiBUeERhdGEsIGV4cGxhbmF0aW9uUmVzdWx0OiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uKTogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBqc29uLmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5kZXBvc2l0LnRvU3RyaW5nKCkgfHwgJycsXG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBqc29uLnJlY2VpdmVySWQsXG4gICAgICAgICAgYW1vdW50OiBqc29uLmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5kZXBvc2l0LnRvU3RyaW5nKCkgfHwgJycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGNvbXBsZXRlIGV4cGxhbmF0aW9uIGZvciBhIHN0YWtpbmcgd2l0aGRyYXcgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtUeERhdGF9IGpzb24gVGhlIHRyYW5zYWN0aW9uIGRhdGEgaW4ganNvbiBmb3JtYXRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufSBleHBsYW5hdGlvblJlc3VsdCBUaGUgdHJhbnNhY3Rpb24gZXhwbGFuYXRpb24gdG8gYmUgY29tcGxldGVkXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufVxuICAgKi9cbiAgZXhwbGFpblN0YWtpbmdXaXRoZHJhd1RyYW5zYWN0aW9uKGpzb246IFR4RGF0YSwgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCBhbW91bnQgPSBqc29uLmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5hcmdzLmFtb3VudCBhcyBzdHJpbmc7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBhbW91bnQsXG4gICAgICBvdXRwdXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBqc29uLnNpZ25lcklkLFxuICAgICAgICAgIGFtb3VudDogYW1vdW50LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgdGhlIHRvdGFsIGZ1bmdpYmxlIHRva2VuIGFtb3VudCAmIHRvdGFsIG5hdGl2ZSBuZWFyIGFtb3VudFxuICAgKlxuICAgKiBAcGFyYW0ge0FjdGlvbltdfSBhY3Rpb25zIHRoZSBsaXN0IG9mIGRlbGVnYXRlIHRyYW5zYWN0aW9uIGFjdGlvbnNcbiAgICogQHJldHVybnMge1N0cmluZ30gZWl0aGVyIG5hdGl2ZSBuZWFyIGFtb3VudCBvciBmdW5naWJsZSB0b2tlbiBhbW91bnRcbiAgICovXG4gIGNhbGN1bGF0ZVRvdGFsT3V0cHV0QW1vdW50KGFjdGlvbnM6IEFjdGlvbltdKTogc3RyaW5nIHtcbiAgICBsZXQgaGFzRnRUcmFuc2ZlciA9IGZhbHNlO1xuICAgIGxldCBoYXNTdG9yYWdlRGVwb3NpdCA9IGZhbHNlO1xuXG4gICAgbGV0IHRvdGFsVG9rZW5BbW91bnQgPSBCaWdJbnQoMCk7XG4gICAgbGV0IHRvdGFsTmVhckRlcG9zaXQgPSBCaWdJbnQoMCk7XG5cbiAgICBmb3IgKGNvbnN0IGFjdGlvbiBvZiBhY3Rpb25zKSB7XG4gICAgICBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICBjb25zdCBmdW5jdGlvbkNhbGwgPSBhY3Rpb24uZnVuY3Rpb25DYWxsO1xuICAgICAgICBjb25zdCBtZXRob2ROYW1lID0gZnVuY3Rpb25DYWxsLm1ldGhvZE5hbWU7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBmdW5jdGlvbkNhbGwuYXJncztcbiAgICAgICAgY29uc3QgZGVwb3NpdCA9IEJpZ0ludChmdW5jdGlvbkNhbGwuZGVwb3NpdCk7XG4gICAgICAgIGlmIChtZXRob2ROYW1lID09PSBGVF9UUkFOU0ZFUikge1xuICAgICAgICAgIGhhc0Z0VHJhbnNmZXIgPSB0cnVlO1xuICAgICAgICAgIGNvbnN0IGFtb3VudFN0ciA9IGFyZ3NbJ2Ftb3VudCddIGFzIHN0cmluZztcbiAgICAgICAgICBpZiAoYXJncy5hbW91bnQpIHtcbiAgICAgICAgICAgIHRvdGFsVG9rZW5BbW91bnQgKz0gQmlnSW50KGFtb3VudFN0cik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChtZXRob2ROYW1lID09PSBTVE9SQUdFX0RFUE9TSVQpIHtcbiAgICAgICAgICBoYXNTdG9yYWdlRGVwb3NpdCA9IHRydWU7XG4gICAgICAgICAgdG90YWxOZWFyRGVwb3NpdCArPSBkZXBvc2l0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChoYXNGdFRyYW5zZmVyKSB7XG4gICAgICByZXR1cm4gdG90YWxUb2tlbkFtb3VudC50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoaGFzU3RvcmFnZURlcG9zaXQpIHtcbiAgICAgIHJldHVybiB0b3RhbE5lYXJEZXBvc2l0LnRvU3RyaW5nKCk7XG4gICAgfVxuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgY29tcGxldGUgZXhwbGFuYXRpb24gZm9yIGEgdG9rZW4gdHJhbnNmZXIgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtUeERhdGF9IGpzb24gVGhlIHRyYW5zYWN0aW9uIGRhdGEgaW4ganNvbiBmb3JtYXRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufSBleHBsYW5hdGlvblJlc3VsdCBUaGUgdHJhbnNhY3Rpb24gZXhwbGFuYXRpb24gdG8gYmUgY29tcGxldGVkXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufVxuICAgKi9cbiAgZXhwbGFpblRva2VuVHJhbnNmZXJUcmFuc2FjdGlvbihqc29uOiBUeERhdGEsIGV4cGxhbmF0aW9uUmVzdWx0OiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uKTogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gICAgY29uc3QgYWN0aW9ucyA9IGpzb24uYWN0aW9ucztcbiAgICBjb25zdCBvdXRwdXRBbW91bnQgPSB0aGlzLmNhbGN1bGF0ZVRvdGFsT3V0cHV0QW1vdW50KGFjdGlvbnMpO1xuICAgIGNvbnN0IG91dHB1dHM6IElUcmFuc2FjdGlvblJlY2lwaWVudFtdID0gW107XG4gICAgYWN0aW9ucy5tYXAoKGFjdGlvbikgPT4ge1xuICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25DYWxsID0gYWN0aW9uLmZ1bmN0aW9uQ2FsbDtcbiAgICAgICAgaWYgKGZ1bmN0aW9uQ2FsbC5tZXRob2ROYW1lID09PSBGVF9UUkFOU0ZFUikge1xuICAgICAgICAgIGNvbnN0IGFtb3VudFN0ciA9IGZ1bmN0aW9uQ2FsbC5hcmdzWydhbW91bnQnXSBhcyBzdHJpbmc7XG4gICAgICAgICAgY29uc3QgcmVjZWl2ZXJJZCA9IGZ1bmN0aW9uQ2FsbC5hcmdzWydyZWNlaXZlcl9pZCddIGFzIHN0cmluZztcbiAgICAgICAgICAvLyBpbiBmdCB0cmFuc2ZlciwgdGhlIG91dGVyIHJlY2VpdmVyIGlkIHdpbGwgYmUgY29udHJhY3QgYWRkcmVzcyBvZiB0aGUgdG9rZW5cbiAgICAgICAgICBjb25zdCB0b2tlbk5hbWUgPSB1dGlscy5maW5kVG9rZW5OYW1lRnJvbUNvbnRyYWN0QWRkcmVzcyhqc29uLnJlY2VpdmVySWQpO1xuICAgICAgICAgIGNvbnN0IG91dHB1dDogSVRyYW5zYWN0aW9uUmVjaXBpZW50ID0ge1xuICAgICAgICAgICAgYWRkcmVzczogcmVjZWl2ZXJJZCxcbiAgICAgICAgICAgIGFtb3VudDogYW1vdW50U3RyLFxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKHRva2VuTmFtZSkge1xuICAgICAgICAgICAgb3V0cHV0LnRva2VuTmFtZSA9IHRva2VuTmFtZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgb3V0cHV0cy5wdXNoKG91dHB1dCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZXhwbGFuYXRpb25SZXN1bHQsXG4gICAgICBvdXRwdXRBbW91bnQ6IG91dHB1dEFtb3VudCxcbiAgICAgIG91dHB1dHM6IG91dHB1dHMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgY29tcGxldGUgZXhwbGFuYXRpb24gZm9yIGEgc3RvcmFnZSBkZXBvc2l0IHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7VHhEYXRhfSBqc29uIFRoZSB0cmFuc2FjdGlvbiBkYXRhIGluIGpzb24gZm9ybWF0XG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn0gZXhwbGFuYXRpb25SZXN1bHQgVGhlIHRyYW5zYWN0aW9uIGV4cGxhbmF0aW9uIHRvIGJlIGNvbXBsZXRlZFxuICAgKiBAcmV0dXJucyB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn1cbiAgICovXG4gIGV4cGxhaW5TdG9yYWdlRGVwb3NpdFRyYW5zYWN0aW9uKGpzb246IFR4RGF0YSwgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCBhY3Rpb25zID0ganNvbi5hY3Rpb25zO1xuICAgIGNvbnN0IG91dHB1dEFtb3VudCA9IHRoaXMuY2FsY3VsYXRlVG90YWxPdXRwdXRBbW91bnQoYWN0aW9ucyk7XG4gICAgY29uc3Qgb3V0cHV0czogSVRyYW5zYWN0aW9uUmVjaXBpZW50W10gPSBbXTtcbiAgICBhY3Rpb25zLm1hcCgoYWN0aW9uKSA9PiB7XG4gICAgICBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICBjb25zdCBmdW5jdGlvbkNhbGwgPSBhY3Rpb24uZnVuY3Rpb25DYWxsO1xuICAgICAgICBpZiAoZnVuY3Rpb25DYWxsLm1ldGhvZE5hbWUgPT09IFNUT1JBR0VfREVQT1NJVCkge1xuICAgICAgICAgIGNvbnN0IHJlY2VpdmVySWQgPVxuICAgICAgICAgICAgZnVuY3Rpb25DYWxsLmFyZ3MgJiYgZnVuY3Rpb25DYWxsLmFyZ3NbJ2FjY291bnRfaWQnXVxuICAgICAgICAgICAgICA/IChmdW5jdGlvbkNhbGwuYXJnc1snYWNjb3VudF9pZCddIGFzIHN0cmluZylcbiAgICAgICAgICAgICAgOiBqc29uLnNpZ25lcklkO1xuICAgICAgICAgIC8vIGluIHN0b3JhZ2UgZGVwb3NpdCwgdGhlIG91dGVyIHJlY2VpdmVyIGlkIHdpbGwgYmUgY29udHJhY3QgYWRkcmVzcyBvZiB0aGUgdG9rZW5cbiAgICAgICAgICBjb25zdCB0b2tlbk5hbWUgPSB1dGlscy5maW5kVG9rZW5OYW1lRnJvbUNvbnRyYWN0QWRkcmVzcyhqc29uLnJlY2VpdmVySWQpO1xuICAgICAgICAgIGNvbnN0IG91dHB1dDogSVRyYW5zYWN0aW9uUmVjaXBpZW50ID0ge1xuICAgICAgICAgICAgYWRkcmVzczogcmVjZWl2ZXJJZCxcbiAgICAgICAgICAgIGFtb3VudDogZnVuY3Rpb25DYWxsLmRlcG9zaXQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBpZiAodG9rZW5OYW1lKSB7XG4gICAgICAgICAgICBvdXRwdXQudG9rZW5OYW1lID0gdG9rZW5OYW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvdXRwdXRzLnB1c2gob3V0cHV0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICAuLi5leHBsYW5hdGlvblJlc3VsdCxcbiAgICAgIG91dHB1dEFtb3VudDogb3V0cHV0QW1vdW50LFxuICAgICAgb3V0cHV0czogb3V0cHV0cyxcbiAgICB9O1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGV4cGxhaW5UcmFuc2FjdGlvbigpOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLnRvSnNvbigpO1xuICAgIGNvbnN0IGRpc3BsYXlPcmRlciA9IFsnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJywgJ3R5cGUnXTtcbiAgICBjb25zdCBvdXRwdXRzOiBUcmFuc2FjdGlvblJlY2lwaWVudFtdID0gW107XG4gICAgY29uc3QgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSB7XG4gICAgICAvLyB0eGhhc2ggdXNlZCB0byBpZGVudGlmeSB0aGUgdHJhbnNhY3Rpb25zXG4gICAgICBpZDogcmVzdWx0LmlkIHx8ICcnLFxuICAgICAgZGlzcGxheU9yZGVyLFxuICAgICAgb3V0cHV0QW1vdW50OiAnMCcsXG4gICAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICAgIGNoYW5nZU91dHB1dHM6IFtdLFxuICAgICAgb3V0cHV0cyxcbiAgICAgIGZlZTogeyBmZWU6ICcnIH0sXG4gICAgICB0eXBlOiB0aGlzLnR5cGUsXG4gICAgfTtcbiAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZDpcbiAgICAgICAgaWYgKHJlc3VsdC5hY3Rpb25zLmxlbmd0aCA+IDEgfHwgcmVzdWx0LmFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZXhwbGFpblRva2VuVHJhbnNmZXJUcmFuc2FjdGlvbihyZXN1bHQsIGV4cGxhbmF0aW9uUmVzdWx0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5leHBsYWluVHJhbnNmZXJUcmFuc2FjdGlvbihyZXN1bHQsIGV4cGxhbmF0aW9uUmVzdWx0KTtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZTpcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwbGFpblN0YWtpbmdBY3RpdmF0ZVRyYW5zYWN0aW9uKHJlc3VsdCwgZXhwbGFuYXRpb25SZXN1bHQpO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlYWN0aXZhdGU6XG4gICAgICAgIHJldHVybiBleHBsYW5hdGlvblJlc3VsdDtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwbGFpblN0YWtpbmdXaXRoZHJhd1RyYW5zYWN0aW9uKHJlc3VsdCwgZXhwbGFuYXRpb25SZXN1bHQpO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3RvcmFnZURlcG9zaXQ6XG4gICAgICAgIHJldHVybiB0aGlzLmV4cGxhaW5TdG9yYWdlRGVwb3NpdFRyYW5zYWN0aW9uKHJlc3VsdCwgZXhwbGFuYXRpb25SZXN1bHQpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdUcmFuc2FjdGlvbiB0eXBlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldFRyYW5zYWN0aW9uSGFzaCgpOiBVaW50OEFycmF5IHtcbiAgICBjb25zdCBzZXJpYWxpemVkVHggPSBuZWFyQVBJLnV0aWxzLnNlcmlhbGl6ZS5zZXJpYWxpemUoXG4gICAgICBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TQ0hFTUEuVHJhbnNhY3Rpb24sXG4gICAgICB0aGlzLl9uZWFyVHJhbnNhY3Rpb25cbiAgICApO1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShzaGEyNTYuYXJyYXkoc2VyaWFsaXplZFR4KSk7XG4gIH1cblxuICBnZXQgc2lnbmFibGVQYXlsb2FkKCk6IEJ1ZmZlciB7XG4gICAgaWYgKCF0aGlzLl9uZWFyVHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignZW1wdHkgdHJhbnNhY3Rpb24nKTtcbiAgICB9XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHRoaXMuZ2V0VHJhbnNhY3Rpb25IYXNoKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSBzaWduZWQgcGF5bG9hZCB1c2luZyBjb25zdHJ1Y3Quc2lnblR4XG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIGR1cmluZyB0aGUgYnVpbGQgc3RlcCBpZiBhIFRTUyBzaWduYXR1cmVcbiAgICogaXMgYWRkZWQgYW5kIHdpbGwgc2V0IHRoZSBzaWduVHJhbnNhY3Rpb24gd2hpY2ggaXMgdGhlIHR4SGV4IHRoYXQgd2lsbCBiZSBicm9hZGNhc3RlZFxuICAgKiBBcyB3ZWxsIGFzIGFkZCB0aGUgc2lnbmF0dXJlIHVzZWQgdG8gc2lnbiB0byB0aGUgc2lnbmF0dXJlIGFycmF5IGluIGhleCBmb3JtYXRcbiAgICpcbiAgICogQHBhcmFtIHtCdWZmZXJ9IHNpZ25hdHVyZSBUaGUgc2lnbmF0dXJlIHRvIGJlIGFkZGVkIHRvIGEgbmVhciB0cmFuc2FjdGlvblxuICAgKi9cbiAgY29uc3RydWN0U2lnbmVkUGF5bG9hZChzaWduYXR1cmU6IEJ1ZmZlcik6IHZvaWQge1xuICAgIHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbiA9IG5ldyBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduZWRUcmFuc2FjdGlvbih7XG4gICAgICB0cmFuc2FjdGlvbjogdGhpcy5fbmVhclRyYW5zYWN0aW9uLFxuICAgICAgc2lnbmF0dXJlOiBuZXcgbmVhckFQSS50cmFuc2FjdGlvbnMuU2lnbmF0dXJlKHtcbiAgICAgICAga2V5VHlwZTogdGhpcy5fbmVhclRyYW5zYWN0aW9uLnB1YmxpY0tleS5rZXlUeXBlLFxuICAgICAgICBkYXRhOiBzaWduYXR1cmUsXG4gICAgICB9KSxcbiAgICB9KTtcbiAgICB0aGlzLmxvYWRJbnB1dHNBbmRPdXRwdXRzKCk7XG4gIH1cbiAgLyoqIEBpbmhlcml0ZG9jICoqL1xuICBnZXQgc2lnbmF0dXJlKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBzaWduYXR1cmVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbiAmJiB0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb24uc2lnbmF0dXJlLmVkMjU1MTlTaWduYXR1cmUpIHtcbiAgICAgIHNpZ25hdHVyZXMucHVzaChiYXNlNTguZW5jb2RlKHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbi5zaWduYXR1cmUuZWQyNTUxOVNpZ25hdHVyZS5kYXRhKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNpZ25hdHVyZXM7XG4gIH1cbn1cbiJdfQ==