@bitgo-beta/sdk-coin-ada 2.3.14-beta.1221 → 2.3.14-beta.1223

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 (79) hide show
  1. package/package.json +6 -6
  2. package/dist/src/ada.d.ts +0 -116
  3. package/dist/src/ada.d.ts.map +0 -1
  4. package/dist/src/ada.js +0 -556
  5. package/dist/src/adaToken.d.ts +0 -31
  6. package/dist/src/adaToken.d.ts.map +0 -1
  7. package/dist/src/adaToken.js +0 -72
  8. package/dist/src/index.d.ts +0 -6
  9. package/dist/src/index.d.ts.map +0 -1
  10. package/dist/src/index.js +0 -22
  11. package/dist/src/lib/index.d.ts +0 -15
  12. package/dist/src/lib/index.d.ts.map +0 -1
  13. package/dist/src/lib/index.js +0 -65
  14. package/dist/src/lib/keyPair.d.ts +0 -20
  15. package/dist/src/lib/keyPair.d.ts.map +0 -1
  16. package/dist/src/lib/keyPair.js +0 -91
  17. package/dist/src/lib/messages/cip8/cip8Message.d.ts +0 -25
  18. package/dist/src/lib/messages/cip8/cip8Message.d.ts.map +0 -1
  19. package/dist/src/lib/messages/cip8/cip8Message.js +0 -140
  20. package/dist/src/lib/messages/cip8/cip8MessageBuilder.d.ts +0 -19
  21. package/dist/src/lib/messages/cip8/cip8MessageBuilder.d.ts.map +0 -1
  22. package/dist/src/lib/messages/cip8/cip8MessageBuilder.js +0 -27
  23. package/dist/src/lib/messages/cip8/index.d.ts +0 -3
  24. package/dist/src/lib/messages/cip8/index.d.ts.map +0 -1
  25. package/dist/src/lib/messages/cip8/index.js +0 -19
  26. package/dist/src/lib/messages/cip8/utils.d.ts +0 -24
  27. package/dist/src/lib/messages/cip8/utils.d.ts.map +0 -1
  28. package/dist/src/lib/messages/cip8/utils.js +0 -73
  29. package/dist/src/lib/messages/index.d.ts +0 -3
  30. package/dist/src/lib/messages/index.d.ts.map +0 -1
  31. package/dist/src/lib/messages/index.js +0 -19
  32. package/dist/src/lib/messages/messageBuilderFactory.d.ts +0 -7
  33. package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +0 -1
  34. package/dist/src/lib/messages/messageBuilderFactory.js +0 -20
  35. package/dist/src/lib/stakingActivateBuilder.d.ts +0 -24
  36. package/dist/src/lib/stakingActivateBuilder.d.ts.map +0 -1
  37. package/dist/src/lib/stakingActivateBuilder.js +0 -88
  38. package/dist/src/lib/stakingBaseClaimBuilder.d.ts +0 -20
  39. package/dist/src/lib/stakingBaseClaimBuilder.d.ts.map +0 -1
  40. package/dist/src/lib/stakingBaseClaimBuilder.js +0 -35
  41. package/dist/src/lib/stakingClaimRewardsBuilder.d.ts +0 -10
  42. package/dist/src/lib/stakingClaimRewardsBuilder.d.ts.map +0 -1
  43. package/dist/src/lib/stakingClaimRewardsBuilder.js +0 -22
  44. package/dist/src/lib/stakingDeactivateBuilder.d.ts +0 -22
  45. package/dist/src/lib/stakingDeactivateBuilder.d.ts.map +0 -1
  46. package/dist/src/lib/stakingDeactivateBuilder.js +0 -75
  47. package/dist/src/lib/stakingPledgeBuilder.d.ts +0 -23
  48. package/dist/src/lib/stakingPledgeBuilder.d.ts.map +0 -1
  49. package/dist/src/lib/stakingPledgeBuilder.js +0 -43
  50. package/dist/src/lib/stakingWithdrawBuilder.d.ts +0 -12
  51. package/dist/src/lib/stakingWithdrawBuilder.d.ts.map +0 -1
  52. package/dist/src/lib/stakingWithdrawBuilder.js +0 -22
  53. package/dist/src/lib/transaction.d.ts +0 -134
  54. package/dist/src/lib/transaction.d.ts.map +0 -1
  55. package/dist/src/lib/transaction.js +0 -371
  56. package/dist/src/lib/transactionBuilder.d.ts +0 -137
  57. package/dist/src/lib/transactionBuilder.d.ts.map +0 -1
  58. package/dist/src/lib/transactionBuilder.js +0 -698
  59. package/dist/src/lib/transactionBuilderFactory.d.ts +0 -36
  60. package/dist/src/lib/transactionBuilderFactory.d.ts.map +0 -1
  61. package/dist/src/lib/transactionBuilderFactory.js +0 -92
  62. package/dist/src/lib/transferBuilder.d.ts +0 -14
  63. package/dist/src/lib/transferBuilder.d.ts.map +0 -1
  64. package/dist/src/lib/transferBuilder.js +0 -27
  65. package/dist/src/lib/utils.d.ts +0 -52
  66. package/dist/src/lib/utils.d.ts.map +0 -1
  67. package/dist/src/lib/utils.js +0 -277
  68. package/dist/src/lib/voteDelegationBuilder.d.ts +0 -24
  69. package/dist/src/lib/voteDelegationBuilder.d.ts.map +0 -1
  70. package/dist/src/lib/voteDelegationBuilder.js +0 -84
  71. package/dist/src/lib/walletInitializationBuilder.d.ts +0 -14
  72. package/dist/src/lib/walletInitializationBuilder.d.ts.map +0 -1
  73. package/dist/src/lib/walletInitializationBuilder.js +0 -24
  74. package/dist/src/register.d.ts +0 -3
  75. package/dist/src/register.d.ts.map +0 -1
  76. package/dist/src/register.js +0 -13
  77. package/dist/src/tada.d.ts +0 -21
  78. package/dist/src/tada.d.ts.map +0 -1
  79. package/dist/src/tada.js +0 -26
@@ -1,698 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.TransactionBuilder = void 0;
37
- const sdk_core_1 = require("@bitgo-beta/sdk-core");
38
- const transaction_1 = require("./transaction");
39
- const keyPair_1 = require("./keyPair");
40
- const utils_1 = __importStar(require("./utils"));
41
- const CardanoWasm = __importStar(require("@emurgo/cardano-serialization-lib-nodejs"));
42
- const cardano_serialization_lib_nodejs_1 = require("@emurgo/cardano-serialization-lib-nodejs");
43
- /**
44
- * Constants for transaction building
45
- */
46
- const FEE_COEFFICIENTS = {
47
- /** Linear fee parameter a */
48
- A_COEFFICIENT: '44',
49
- /** Linear fee parameter b */
50
- B_COEFFICIENT: '155381',
51
- /** Additional safety margin for the fee */
52
- SAFETY_MARGIN: '440',
53
- };
54
- class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
55
- constructor(_coinConfig) {
56
- super(_coinConfig);
57
- this._signers = [];
58
- this._transactionInputs = [];
59
- this._transactionOutputs = [];
60
- this._initSignatures = [];
61
- this._signatures = [];
62
- this._ttl = 0;
63
- this._certs = [];
64
- this._withdrawals = [];
65
- this._multiAssets = [];
66
- /** Map of sender's assets by asset name */
67
- this._senderAssetList = {};
68
- /** Flag indicating if this is a token transaction */
69
- this._isTokenTransaction = false;
70
- /** Deep clone of _senderAssetList - for manipulating during two iterations
71
- * - one for calculating the fee
72
- * - one for the actual transaction build with the calculated fee
73
- * */
74
- this._mutableSenderAssetList = {};
75
- this.transaction = new transaction_1.Transaction(_coinConfig);
76
- this._fee = cardano_serialization_lib_nodejs_1.BigNum.zero();
77
- }
78
- input(i) {
79
- this._transactionInputs.push(i);
80
- return this;
81
- }
82
- output(o) {
83
- this._transactionOutputs.push(o);
84
- return this;
85
- }
86
- assets(a) {
87
- this._multiAssets.push(a);
88
- return this;
89
- }
90
- ttl(t) {
91
- this._ttl = t;
92
- return this;
93
- }
94
- /**
95
- * Sets the change address and input balances for the transaction
96
- * @param addr - The address where change will be sent
97
- * @param totalInputBalance - The total ADA input balance in Lovelace
98
- * @param inputAssetList - Optional map of token assets in the input
99
- */
100
- changeAddress(addr, totalInputBalance, inputAssetList) {
101
- this._changeAddress = addr;
102
- this._senderBalance = totalInputBalance;
103
- this._senderAssetList = inputAssetList ?? {};
104
- this.setMutableSenderAssetList();
105
- return this;
106
- }
107
- setMutableSenderAssetList() {
108
- this._mutableSenderAssetList = JSON.parse(JSON.stringify(this._senderAssetList));
109
- }
110
- fee(fee) {
111
- this._fee = cardano_serialization_lib_nodejs_1.BigNum.from_str(fee);
112
- return this;
113
- }
114
- /**
115
- * Marks this transaction as a token transaction
116
- * Enables special handling for token transfers
117
- */
118
- isTokenTransaction() {
119
- this._isTokenTransaction = true;
120
- return this;
121
- }
122
- /**
123
- * Initialize the transaction builder fields using the decoded transaction data
124
- *
125
- * @param {Transaction} tx the transaction data
126
- */
127
- initBuilder(tx) {
128
- this._transaction = tx;
129
- const txnBody = tx.transaction.body();
130
- for (let i = 0; i < txnBody.inputs().len(); i++) {
131
- const input = txnBody.inputs().get(i);
132
- this.input({
133
- transaction_id: Buffer.from(input.transaction_id().to_bytes()).toString('hex'),
134
- transaction_index: input.index(),
135
- });
136
- }
137
- for (let i = 0; i < txnBody.outputs().len(); i++) {
138
- const output = txnBody.outputs().get(i);
139
- this.output({
140
- address: output.address().to_bech32(),
141
- amount: output.amount().coin().to_str(),
142
- multiAssets: output.amount().multiasset() || undefined,
143
- });
144
- }
145
- if (txnBody.certs() !== undefined) {
146
- const certs = txnBody.certs();
147
- for (let i = 0; i < certs.len(); i++) {
148
- this._certs.push(certs.get(i));
149
- }
150
- }
151
- if (txnBody.withdrawals() !== undefined) {
152
- const withdrawals = txnBody.withdrawals();
153
- const keys = withdrawals.keys();
154
- for (let i = 0; i < keys.len(); i++) {
155
- const rewardAddress = keys.get(i);
156
- const reward = withdrawals.get(rewardAddress);
157
- this._withdrawals.push({ stakeAddress: rewardAddress.to_address().to_bech32(), value: reward.to_str() });
158
- }
159
- }
160
- this._ttl = tx.transaction.body().ttl();
161
- this._fee = tx.transaction.body().fee();
162
- if (tx.transaction.witness_set().vkeys()) {
163
- const vkeys = tx.transaction.witness_set().vkeys();
164
- for (let i = 0; i < vkeys.len(); i++) {
165
- const vkey = vkeys.get(i);
166
- this._initSignatures.push({
167
- publicKey: { pub: vkey.vkey().public_key().to_hex() },
168
- signature: Buffer.from(vkey.signature().to_hex(), 'hex'),
169
- });
170
- }
171
- }
172
- }
173
- /** @inheritdoc */
174
- fromImplementation(rawTransaction) {
175
- this.validateRawTransaction(rawTransaction);
176
- this.buildImplementation();
177
- return this.transaction;
178
- }
179
- /**
180
- * Builds a transaction that includes token assets
181
- * @returns The built transaction
182
- */
183
- processTokenBuild() {
184
- const inputs = CardanoWasm.TransactionInputs.new();
185
- let outputs = CardanoWasm.TransactionOutputs.new();
186
- this.addInputs(inputs);
187
- // Fee is never set so far from IMS
188
- if (this._fee.is_zero()) {
189
- this.addOutputs(outputs);
190
- const txDraft = this.prepareAdaTransactionDraft(inputs, outputs, false);
191
- this.calculateFee(txDraft);
192
- this.setFeeInTransaction();
193
- }
194
- // Reset outputs to add them back with the correct change
195
- outputs = CardanoWasm.TransactionOutputs.new();
196
- this.setMutableSenderAssetList();
197
- this.addOutputs(outputs);
198
- this._transaction.transaction = this.prepareAdaTransactionDraft(inputs, outputs, true);
199
- return this.transaction;
200
- }
201
- /**
202
- * Adds transaction inputs to the transaction
203
- * @param inputs - The inputs collection to add to
204
- */
205
- addInputs(inputs) {
206
- this._transactionInputs.forEach((input) => {
207
- inputs.add(CardanoWasm.TransactionInput.new(CardanoWasm.TransactionHash.from_bytes(Buffer.from(input.transaction_id, 'hex')), input.transaction_index));
208
- });
209
- }
210
- /**
211
- * Adds outputs to the transaction including token outputs and change
212
- * @param outputs - The outputs collection to add to
213
- */
214
- addOutputs(outputs) {
215
- const utxoBalance = CardanoWasm.BigNum.from_str(this._senderBalance); // Total UTXO balance
216
- const change = utxoBalance.checked_sub(this._fee);
217
- const changeAfterReceiverDeductions = this.addReceiverOutputs(outputs, change);
218
- this.addChangeOutput(changeAfterReceiverDeductions, outputs);
219
- }
220
- /**
221
- * Adds receiver outputs to the transaction and calculates the remaining change
222
- * @param outputs - Transaction outputs collection
223
- * @param change - Current change amount in ADA
224
- * @returns Remaining change after adding receiver outputs
225
- */
226
- addReceiverOutputs(outputs, change) {
227
- this._transactionOutputs.forEach((output) => {
228
- if (!output.address) {
229
- throw new sdk_core_1.BuildTransactionError('Invalid output: missing address');
230
- }
231
- const receiverAddress = output.address;
232
- const receiverAmount = output.amount;
233
- try {
234
- const receiverAmountBN = CardanoWasm.BigNum.from_str(receiverAmount);
235
- change = change.checked_sub(receiverAmountBN);
236
- if (change.less_than(CardanoWasm.BigNum.zero())) {
237
- throw new sdk_core_1.BuildTransactionError('Insufficient funds: not enough ADA to cover receiver output amounts and fees');
238
- }
239
- const multiAssets = output.multiAssets;
240
- if (multiAssets) {
241
- const policyId = multiAssets.policy_id;
242
- const assetName = multiAssets.asset_name;
243
- const quantity = multiAssets.quantity;
244
- const fingerprint = multiAssets.fingerprint;
245
- const currentQty = this._mutableSenderAssetList[fingerprint].quantity;
246
- const remainingQty = BigInt(currentQty) - BigInt(quantity);
247
- this._mutableSenderAssetList[fingerprint].quantity = (remainingQty > 0n ? remainingQty : 0n).toString();
248
- if (CardanoWasm.BigNum.from_str(this._mutableSenderAssetList[fingerprint].quantity).is_zero()) {
249
- throw new sdk_core_1.BuildTransactionError('Insufficient qty: not enough token qty to cover receiver output');
250
- }
251
- const minAmountNeededForAssetOutput = this.addTokensToOutput(change, outputs, receiverAddress, {
252
- policy_id: policyId,
253
- asset_name: assetName,
254
- quantity,
255
- fingerprint,
256
- });
257
- change = change.checked_sub(minAmountNeededForAssetOutput);
258
- }
259
- }
260
- catch (e) {
261
- if (e instanceof sdk_core_1.BuildTransactionError) {
262
- throw e;
263
- }
264
- throw new sdk_core_1.BuildTransactionError(`Error processing output: ${e.message}`);
265
- }
266
- });
267
- return change;
268
- }
269
- /**
270
- * Adds tokens to a transaction output
271
- * @param change - The current change amount in Lovelace
272
- * @param outputs - The outputs collection to add to
273
- * @param address - The recipient address
274
- * @param asset - The asset to add
275
- * @returns The minimum ADA amount needed for this asset output
276
- */
277
- addTokensToOutput(change, outputs, address, asset) {
278
- const minAmountNeededForOneAssetOutput = CardanoWasm.BigNum.from_str(utils_1.MIN_ADA_FOR_ONE_ASSET);
279
- if (change.less_than(minAmountNeededForOneAssetOutput)) {
280
- throw new sdk_core_1.BuildTransactionError(`Insufficient funds: need a minimum of ${utils_1.MIN_ADA_FOR_ONE_ASSET} lovelace per output to construct token transactions`);
281
- }
282
- this.buildTokens(asset, minAmountNeededForOneAssetOutput, outputs, address);
283
- return minAmountNeededForOneAssetOutput;
284
- }
285
- /**
286
- * Builds token outputs for a transaction
287
- * @param asset - The asset to include in the output
288
- * @param minAmountNeededForOneAssetOutput - Minimum ADA required for this asset output
289
- * @param outputs - Transaction outputs collection
290
- * @param address - Recipient address
291
- */
292
- buildTokens(asset, minAmountNeededForOneAssetOutput, outputs, address) {
293
- let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
294
- const toAddress = utils_1.default.getWalletAddress(address);
295
- txOutputBuilder = txOutputBuilder.with_address(toAddress);
296
- let txOutputAmountBuilder = txOutputBuilder.next();
297
- const assetName = CardanoWasm.AssetName.new(Buffer.from(asset.asset_name, 'hex'));
298
- const policyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(asset.policy_id, 'hex'));
299
- const multiAsset = CardanoWasm.MultiAsset.new();
300
- const assets = CardanoWasm.Assets.new();
301
- assets.insert(assetName, CardanoWasm.BigNum.from_str(asset.quantity));
302
- multiAsset.insert(policyId, assets);
303
- txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(minAmountNeededForOneAssetOutput, multiAsset);
304
- const txOutput = txOutputAmountBuilder.build();
305
- outputs.add(txOutput);
306
- }
307
- /**
308
- * Adds a change output to the transaction
309
- * @param change - The change amount in Lovelace
310
- * @param outputs - The outputs collection to add to
311
- */
312
- addChangeOutput(change, outputs) {
313
- const changeAddress = utils_1.default.getWalletAddress(this._changeAddress);
314
- Object.keys(this._mutableSenderAssetList).forEach((fingerprint) => {
315
- const asset = this._mutableSenderAssetList[fingerprint];
316
- const changeQty = asset.quantity;
317
- const policyId = asset.policy_id;
318
- const assetName = asset.asset_name;
319
- if (CardanoWasm.BigNum.from_str(changeQty).is_zero()) {
320
- return;
321
- }
322
- const minAmountNeededForAssetOutput = this.addTokensToOutput(change, outputs, this._changeAddress, {
323
- policy_id: policyId,
324
- asset_name: assetName,
325
- quantity: changeQty,
326
- fingerprint,
327
- });
328
- change = change.checked_sub(minAmountNeededForAssetOutput);
329
- });
330
- if (!change.is_zero()) {
331
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
332
- outputs.add(changeOutput);
333
- }
334
- }
335
- /**
336
- * Sets the calculated fee in the transaction
337
- */
338
- setFeeInTransaction() {
339
- this._transaction.fee(this._fee.to_str());
340
- }
341
- /**
342
- * Calculates the transaction fee based on transaction size
343
- * @param txDraft - Draft transaction to calculate fee for
344
- */
345
- calculateFee(txDraft) {
346
- const linearFee = CardanoWasm.LinearFee.new(CardanoWasm.BigNum.from_str(FEE_COEFFICIENTS.A_COEFFICIENT), CardanoWasm.BigNum.from_str(FEE_COEFFICIENTS.B_COEFFICIENT));
347
- // Calculate the fee based off our dummy transaction
348
- const fee = CardanoWasm.min_fee(txDraft, linearFee).checked_add(cardano_serialization_lib_nodejs_1.BigNum.from_str(FEE_COEFFICIENTS.SAFETY_MARGIN));
349
- this._fee = fee;
350
- }
351
- prepareAdaTransactionDraft(inputs, outputs, refreshSignatures = false) {
352
- const txBody = CardanoWasm.TransactionBody.new_tx_body(inputs, outputs, this._fee);
353
- txBody.set_ttl(CardanoWasm.BigNum.from_str(this._ttl.toString()));
354
- const txHash = CardanoWasm.hash_transaction(txBody);
355
- // we add witnesses once so that we can get the appropriate amount of signers for calculating the fee
356
- const witnessSet = CardanoWasm.TransactionWitnessSet.new();
357
- const vkeyWitnesses = CardanoWasm.Vkeywitnesses.new();
358
- this._signers.forEach((keyPair) => {
359
- const prv = keyPair.getKeys().prv;
360
- const vkeyWitness = CardanoWasm.make_vkey_witness(txHash, CardanoWasm.PrivateKey.from_normal_bytes(Buffer.from(prv, 'hex')));
361
- vkeyWitnesses.add(vkeyWitness);
362
- });
363
- if (refreshSignatures) {
364
- this._transaction.signature.length = 0;
365
- }
366
- this.getAllSignatures().forEach((signature) => {
367
- const vkey = CardanoWasm.Vkey.new(CardanoWasm.PublicKey.from_bytes(Buffer.from(signature.publicKey.pub, 'hex')));
368
- const ed255Sig = CardanoWasm.Ed25519Signature.from_bytes(signature.signature);
369
- vkeyWitnesses.add(CardanoWasm.Vkeywitness.new(vkey, ed255Sig));
370
- });
371
- if (vkeyWitnesses.len() === 0) {
372
- const prv = CardanoWasm.PrivateKey.generate_ed25519();
373
- const vkeyWitness = CardanoWasm.make_vkey_witness(txHash, prv);
374
- vkeyWitnesses.add(vkeyWitness);
375
- if (this._type !== sdk_core_1.TransactionType.Send) {
376
- vkeyWitnesses.add(vkeyWitness);
377
- }
378
- }
379
- witnessSet.set_vkeys(vkeyWitnesses);
380
- // add in certificates to get mock size
381
- const draftCerts = CardanoWasm.Certificates.new();
382
- for (const cert of this._certs) {
383
- draftCerts.add(cert);
384
- }
385
- txBody.set_certs(draftCerts);
386
- const txDraft = CardanoWasm.Transaction.new(txBody, witnessSet);
387
- return txDraft;
388
- }
389
- /** @inheritdoc */
390
- async buildImplementation() {
391
- if (this._isTokenTransaction) {
392
- return this.processTokenBuild();
393
- }
394
- const inputs = CardanoWasm.TransactionInputs.new();
395
- this._transactionInputs.forEach((input) => {
396
- inputs.add(CardanoWasm.TransactionInput.new(CardanoWasm.TransactionHash.from_bytes(Buffer.from(input.transaction_id, 'hex')), input.transaction_index));
397
- });
398
- let outputs = CardanoWasm.TransactionOutputs.new();
399
- let totalAmountToSend = CardanoWasm.BigNum.zero();
400
- this._transactionOutputs.forEach((output) => {
401
- const amount = CardanoWasm.BigNum.from_str(output.amount);
402
- outputs.add(CardanoWasm.TransactionOutput.new(utils_1.default.getWalletAddress(output.address), CardanoWasm.Value.new(amount)));
403
- totalAmountToSend = totalAmountToSend.checked_add(amount);
404
- });
405
- if (this._fee.is_zero()) {
406
- // estimate fee
407
- // add extra output for the change
408
- if (this._changeAddress && this._senderBalance) {
409
- const changeAddress = utils_1.default.getWalletAddress(this._changeAddress);
410
- const utxoBalance = CardanoWasm.BigNum.from_str(this._senderBalance);
411
- const adjustment = cardano_serialization_lib_nodejs_1.BigNum.from_str('2000000');
412
- let change = utxoBalance.checked_sub(this._fee).checked_sub(totalAmountToSend);
413
- if (this._type === sdk_core_1.TransactionType.StakingActivate) {
414
- change = change.checked_sub(adjustment);
415
- }
416
- else if (this._type === sdk_core_1.TransactionType.StakingDeactivate) {
417
- change = change.checked_add(adjustment);
418
- }
419
- else if (this._type === sdk_core_1.TransactionType.StakingWithdraw || this._type === sdk_core_1.TransactionType.StakingClaim) {
420
- this._withdrawals.forEach((withdrawal) => {
421
- change = change.checked_add(CardanoWasm.BigNum.from_str(withdrawal.value));
422
- });
423
- }
424
- // If totalAmountToSend is 0, its consolidation
425
- if (totalAmountToSend.to_str() == '0') {
426
- // support for multi-asset consolidation
427
- if (this._multiAssets !== undefined) {
428
- const totalNumberOfAssets = CardanoWasm.BigNum.from_str(this._multiAssets.length.toString());
429
- const minAmountNeededForOneAssetOutput = CardanoWasm.BigNum.from_str(utils_1.MIN_ADA_FOR_ONE_ASSET);
430
- const minAmountNeededForTotalAssetOutputs = minAmountNeededForOneAssetOutput.checked_mul(totalNumberOfAssets);
431
- if (!change.less_than(minAmountNeededForTotalAssetOutputs)) {
432
- this._multiAssets.forEach((asset) => {
433
- let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
434
- // changeAddress is the root address, which is where we want the tokens assets to be sent to
435
- const toAddress = utils_1.default.getWalletAddress(this._changeAddress);
436
- txOutputBuilder = txOutputBuilder.with_address(toAddress);
437
- let txOutputAmountBuilder = txOutputBuilder.next();
438
- const assetName = CardanoWasm.AssetName.new(Buffer.from(asset.asset_name, 'hex'));
439
- const policyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(asset.policy_id, 'hex'));
440
- const multiAsset = CardanoWasm.MultiAsset.new();
441
- const assets = CardanoWasm.Assets.new();
442
- assets.insert(assetName, CardanoWasm.BigNum.from_str(asset.quantity));
443
- multiAsset.insert(policyId, assets);
444
- txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(minAmountNeededForOneAssetOutput, multiAsset);
445
- const txOutput = txOutputAmountBuilder.build();
446
- outputs.add(txOutput);
447
- });
448
- // finally send the remaining ADA in its own output
449
- const remainingOutputAmount = change.checked_sub(minAmountNeededForTotalAssetOutputs);
450
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(remainingOutputAmount));
451
- outputs.add(changeOutput);
452
- }
453
- }
454
- else {
455
- // If there are no tokens to consolidate, you only have 1 output which is ADA alone
456
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
457
- outputs.add(changeOutput);
458
- }
459
- }
460
- else {
461
- // If this isn't a consolidate request, whatever change that needs to be sent back to the rootaddress is added as a separate output here
462
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
463
- outputs.add(changeOutput);
464
- }
465
- }
466
- const txBody = CardanoWasm.TransactionBody.new_tx_body(inputs, outputs, this._fee);
467
- txBody.set_ttl(CardanoWasm.BigNum.from_str(this._ttl.toString()));
468
- const txHash = CardanoWasm.hash_transaction(txBody);
469
- // we add witnesses once so that we can get the appropriate amount of signers for calculating the fee
470
- const witnessSet = CardanoWasm.TransactionWitnessSet.new();
471
- const vkeyWitnesses = CardanoWasm.Vkeywitnesses.new();
472
- this._signers.forEach((keyPair) => {
473
- const prv = keyPair.getKeys().prv;
474
- const vkeyWitness = CardanoWasm.make_vkey_witness(txHash, CardanoWasm.PrivateKey.from_normal_bytes(Buffer.from(prv, 'hex')));
475
- vkeyWitnesses.add(vkeyWitness);
476
- });
477
- this.getAllSignatures().forEach((signature) => {
478
- const vkey = CardanoWasm.Vkey.new(CardanoWasm.PublicKey.from_bytes(Buffer.from(signature.publicKey.pub, 'hex')));
479
- const ed255Sig = CardanoWasm.Ed25519Signature.from_bytes(signature.signature);
480
- vkeyWitnesses.add(CardanoWasm.Vkeywitness.new(vkey, ed255Sig));
481
- });
482
- if (vkeyWitnesses.len() === 0) {
483
- const prv = CardanoWasm.PrivateKey.generate_ed25519();
484
- const vkeyWitness = CardanoWasm.make_vkey_witness(txHash, prv);
485
- vkeyWitnesses.add(vkeyWitness);
486
- if (this._type !== sdk_core_1.TransactionType.Send) {
487
- vkeyWitnesses.add(vkeyWitness);
488
- }
489
- }
490
- witnessSet.set_vkeys(vkeyWitnesses);
491
- // add in withdrawal if this is a withdrawal tx
492
- if (this._withdrawals.length > 0) {
493
- const withdrawals = CardanoWasm.Withdrawals.new();
494
- this._withdrawals.forEach((withdrawal) => {
495
- const rewardAddress = CardanoWasm.RewardAddress.from_address(CardanoWasm.Address.from_bech32(withdrawal.stakeAddress));
496
- withdrawals.insert(rewardAddress, CardanoWasm.BigNum.from_str(withdrawal.value));
497
- });
498
- txBody.set_withdrawals(withdrawals);
499
- }
500
- // add in certificates to get mock size
501
- const draftCerts = CardanoWasm.Certificates.new();
502
- for (const cert of this._certs) {
503
- draftCerts.add(cert);
504
- }
505
- txBody.set_certs(draftCerts);
506
- const txDraft = CardanoWasm.Transaction.new(txBody, witnessSet);
507
- const linearFee = CardanoWasm.LinearFee.new(CardanoWasm.BigNum.from_str('44'), CardanoWasm.BigNum.from_str('155381'));
508
- // calculate the fee based off our dummy transaction
509
- const fee = CardanoWasm.min_fee(txDraft, linearFee).checked_add(cardano_serialization_lib_nodejs_1.BigNum.from_str('440'));
510
- this._fee = fee;
511
- }
512
- this._transaction.fee(this._fee.to_str());
513
- // now calculate the change based off of <utxoBalance> - <fee> - <amountToSend>
514
- // reset the outputs collection because now our last output has changed
515
- outputs = CardanoWasm.TransactionOutputs.new();
516
- this._transactionOutputs.forEach((output) => {
517
- const multiAssets = output.multiAssets;
518
- if (multiAssets) {
519
- const policyId = multiAssets.keys().get(0);
520
- const assets = multiAssets.get(policyId);
521
- const assetName = assets.keys().get(0);
522
- const quantity = assets.get(assetName);
523
- let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
524
- const outputAmount = CardanoWasm.BigNum.from_str(output.amount);
525
- const toAddress = utils_1.default.getWalletAddress(output.address);
526
- txOutputBuilder = txOutputBuilder.with_address(toAddress);
527
- let txOutputAmountBuilder = txOutputBuilder.next();
528
- const multiAsset = CardanoWasm.MultiAsset.new();
529
- const asset = CardanoWasm.Assets.new();
530
- asset.insert(assetName, quantity);
531
- multiAsset.insert(policyId, asset);
532
- txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(outputAmount, multiAsset);
533
- const txOutput = txOutputAmountBuilder.build();
534
- outputs.add(txOutput);
535
- }
536
- else {
537
- outputs.add(CardanoWasm.TransactionOutput.new(utils_1.default.getWalletAddress(output.address), CardanoWasm.Value.new(CardanoWasm.BigNum.from_str(output.amount))));
538
- }
539
- });
540
- if (this._changeAddress && this._senderBalance) {
541
- const changeAddress = utils_1.default.getWalletAddress(this._changeAddress);
542
- const utxoBalance = CardanoWasm.BigNum.from_str(this._senderBalance);
543
- const adjustment = cardano_serialization_lib_nodejs_1.BigNum.from_str('2000000');
544
- let change = utxoBalance.checked_sub(this._fee).checked_sub(totalAmountToSend);
545
- if (this._type === sdk_core_1.TransactionType.StakingActivate) {
546
- change = change.checked_sub(adjustment);
547
- }
548
- else if (this._type === sdk_core_1.TransactionType.StakingDeactivate) {
549
- change = change.checked_add(adjustment);
550
- }
551
- else if (this._type === sdk_core_1.TransactionType.StakingWithdraw || this._type === sdk_core_1.TransactionType.StakingClaim) {
552
- this._withdrawals.forEach((withdrawal) => {
553
- change = change.checked_add(CardanoWasm.BigNum.from_str(withdrawal.value));
554
- });
555
- }
556
- // If totalAmountToSend is 0, its consolidation
557
- if (totalAmountToSend.to_str() == '0') {
558
- // support for multi-asset consolidation
559
- if (this._multiAssets !== undefined) {
560
- const totalNumberOfAssets = CardanoWasm.BigNum.from_str(this._multiAssets.length.toString());
561
- const minAmountNeededForOneAssetOutput = CardanoWasm.BigNum.from_str('1500000');
562
- const minAmountNeededForTotalAssetOutputs = minAmountNeededForOneAssetOutput.checked_mul(totalNumberOfAssets);
563
- if (!change.less_than(minAmountNeededForTotalAssetOutputs)) {
564
- this._multiAssets.forEach((asset) => {
565
- let txOutputBuilder = CardanoWasm.TransactionOutputBuilder.new();
566
- // changeAddress is the root address, which is where we want the tokens assets to be sent to
567
- const toAddress = utils_1.default.getWalletAddress(this._changeAddress);
568
- txOutputBuilder = txOutputBuilder.with_address(toAddress);
569
- let txOutputAmountBuilder = txOutputBuilder.next();
570
- const assetName = CardanoWasm.AssetName.new(Buffer.from(asset.asset_name, 'hex'));
571
- const policyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(asset.policy_id, 'hex'));
572
- const multiAsset = CardanoWasm.MultiAsset.new();
573
- const assets = CardanoWasm.Assets.new();
574
- assets.insert(assetName, CardanoWasm.BigNum.from_str(asset.quantity));
575
- multiAsset.insert(policyId, assets);
576
- txOutputAmountBuilder = txOutputAmountBuilder.with_coin_and_asset(minAmountNeededForOneAssetOutput, multiAsset);
577
- const txOutput = txOutputAmountBuilder.build();
578
- outputs.add(txOutput);
579
- });
580
- // finally send the remaining ADA in its own output
581
- const remainingOutputAmount = change.checked_sub(minAmountNeededForTotalAssetOutputs);
582
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(remainingOutputAmount));
583
- outputs.add(changeOutput);
584
- }
585
- else {
586
- throw new sdk_core_1.BuildTransactionError('Insufficient funds: need a minimum of 1.5 ADA per output to construct token consolidation');
587
- }
588
- }
589
- else {
590
- // If there are no tokens to consolidate, you only have 1 output which is ADA alone
591
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
592
- outputs.add(changeOutput);
593
- }
594
- }
595
- else {
596
- // If this isn't a consolidate request, whatever change that needs to be sent back to the rootaddress is added as a separate output here
597
- const changeOutput = CardanoWasm.TransactionOutput.new(changeAddress, CardanoWasm.Value.new(change));
598
- outputs.add(changeOutput);
599
- }
600
- }
601
- const txRaw = CardanoWasm.TransactionBody.new_tx_body(inputs, outputs, this._fee);
602
- const certs = CardanoWasm.Certificates.new();
603
- for (const cert of this._certs) {
604
- certs.add(cert);
605
- }
606
- txRaw.set_certs(certs);
607
- // add in withdrawal if this is a withdrawal tx
608
- if (this._withdrawals.length > 0) {
609
- const withdrawals = CardanoWasm.Withdrawals.new();
610
- this._withdrawals.forEach((withdrawal) => {
611
- const rewardAddress = CardanoWasm.RewardAddress.from_address(CardanoWasm.Address.from_bech32(withdrawal.stakeAddress));
612
- withdrawals.insert(rewardAddress, CardanoWasm.BigNum.from_str(withdrawal.value));
613
- });
614
- txRaw.set_withdrawals(withdrawals);
615
- }
616
- txRaw.set_ttl(CardanoWasm.BigNum.from_str(this._ttl.toString()));
617
- const txRawHash = CardanoWasm.hash_transaction(txRaw);
618
- // now add the witnesses again this time for real. We need to do this again
619
- // because now that we've added our real fee and change output, we have a difference transaction hash
620
- const witnessSet = CardanoWasm.TransactionWitnessSet.new();
621
- const vkeyWitnesses = CardanoWasm.Vkeywitnesses.new();
622
- this._signers.forEach((keyPair) => {
623
- const prv = keyPair.getKeys().prv;
624
- const vkeyWitness = CardanoWasm.make_vkey_witness(txRawHash, CardanoWasm.PrivateKey.from_normal_bytes(Buffer.from(prv, 'hex')));
625
- vkeyWitnesses.add(vkeyWitness);
626
- });
627
- // Clear the cosmetic signature array in native txn wrapper to prevent duplicate when builder is inited from a partially witnessed txn
628
- this._transaction.signature.length = 0;
629
- this.getAllSignatures().forEach((signature) => {
630
- const vkey = CardanoWasm.Vkey.new(CardanoWasm.PublicKey.from_bytes(Buffer.from(signature.publicKey.pub, 'hex')));
631
- const ed255Sig = CardanoWasm.Ed25519Signature.from_bytes(signature.signature);
632
- vkeyWitnesses.add(CardanoWasm.Vkeywitness.new(vkey, ed255Sig));
633
- this._transaction.signature.push(signature.signature.toString('hex'));
634
- });
635
- witnessSet.set_vkeys(vkeyWitnesses);
636
- this._transaction.transaction = CardanoWasm.Transaction.new(txRaw, witnessSet);
637
- return this.transaction;
638
- }
639
- /** @inheritdoc */
640
- signImplementation(key) {
641
- this._signers.push(new keyPair_1.KeyPair({ prv: key.key }));
642
- return this._transaction;
643
- }
644
- /** @inheritdoc */
645
- get transaction() {
646
- return this._transaction;
647
- }
648
- /** @inheritdoc */
649
- set transaction(transaction) {
650
- this._transaction = transaction;
651
- }
652
- /** @inheritdoc */
653
- validateAddress(address, addressFormat) {
654
- if (!utils_1.default.isValidAddress(address.address)) {
655
- throw new sdk_core_1.UtilsError('invalid address ' + address.address);
656
- }
657
- }
658
- /** @inheritdoc */
659
- validateKey(key) {
660
- try {
661
- new keyPair_1.KeyPair({ prv: key.key });
662
- }
663
- catch {
664
- throw new sdk_core_1.BuildTransactionError(`Key validation failed`);
665
- }
666
- }
667
- /** @inheritdoc */
668
- validateRawTransaction(rawTransaction) {
669
- try {
670
- CardanoWasm.Transaction.from_bytes(rawTransaction);
671
- }
672
- catch {
673
- throw new sdk_core_1.BuildTransactionError('invalid raw transaction');
674
- }
675
- }
676
- /** @inheritdoc */
677
- validateTransaction(transaction) {
678
- if (!transaction.transaction) {
679
- return;
680
- }
681
- }
682
- /** @inheritdoc */
683
- validateValue(value) {
684
- if (value.isLessThan(0)) {
685
- throw new sdk_core_1.BuildTransactionError('Value cannot be less than zero');
686
- }
687
- }
688
- // endregion
689
- /** @inheritDoc */
690
- addSignature(publicKey, signature) {
691
- this._signatures.push({ publicKey, signature });
692
- }
693
- getAllSignatures() {
694
- return this._initSignatures.concat(this._signatures);
695
- }
696
- }
697
- exports.TransactionBuilder = TransactionBuilder;
698
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsbURBUzhCO0FBQzlCLCtDQUFvRztBQUNwRyx1Q0FBb0M7QUFDcEMsaURBQXNEO0FBQ3RELHNGQUF3RTtBQUN4RSwrRkFBa0U7QUFFbEU7O0dBRUc7QUFDSCxNQUFNLGdCQUFnQixHQUFHO0lBQ3ZCLDZCQUE2QjtJQUM3QixhQUFhLEVBQUUsSUFBSTtJQUNuQiw2QkFBNkI7SUFDN0IsYUFBYSxFQUFFLFFBQVE7SUFDdkIsMkNBQTJDO0lBQzNDLGFBQWEsRUFBRSxLQUFLO0NBQ3JCLENBQUM7QUFFRixNQUFzQixrQkFBbUIsU0FBUSxpQ0FBc0I7SUEyQnJFLFlBQVksV0FBaUM7UUFDM0MsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBMUJYLGFBQVEsR0FBYyxFQUFFLENBQUM7UUFDekIsdUJBQWtCLEdBQXVCLEVBQUUsQ0FBQztRQUM1Qyx3QkFBbUIsR0FBd0IsRUFBRSxDQUFDO1FBQzlDLG9CQUFlLEdBQWdCLEVBQUUsQ0FBQztRQUNsQyxnQkFBVyxHQUFnQixFQUFFLENBQUM7UUFHOUIsU0FBSSxHQUFHLENBQUMsQ0FBQztRQUNULFdBQU0sR0FBOEIsRUFBRSxDQUFDO1FBQ3ZDLGlCQUFZLEdBQWlCLEVBQUUsQ0FBQztRQUVoQyxpQkFBWSxHQUFZLEVBQUUsQ0FBQztRQUdyQywyQ0FBMkM7UUFDakMscUJBQWdCLEdBQXdCLEVBQUUsQ0FBQztRQUVyRCxxREFBcUQ7UUFDN0Msd0JBQW1CLEdBQUcsS0FBSyxDQUFDO1FBQ3BDOzs7YUFHSztRQUNHLDRCQUF1QixHQUF3QixFQUFFLENBQUM7UUFJeEQsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsV0FBVyxDQUFDLENB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QUFDO1lBQ0gsV0FBVyxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDckQsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQzdELENBQUM7SUFDSCxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLG1CQUFtQixDQUFDLFdBQXdCO1FBQzFDLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDN0IsT0FBTztRQUNULENBQUM7SUFDSCxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGFBQWEsQ0FBQyxLQUFnQjtRQUM1QixJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksZ0NBQXFCLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztRQUNwRSxDQUFDO0lBQ0gsQ0FBQztJQUNELFlBQVk7SUFFWixrQkFBa0I7SUFDbEIsWUFBWSxDQUFDLFNBQXdCLEVBQUUsU0FBaUI7UUFDdEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7Q0FDRjtBQXB3QkQsZ0RBb3dCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IEJhc2VDb2luIGFzIENvaW5Db25maWcgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7XG4gIEJhc2VBZGRyZXNzLFxuICBCYXNlS2V5LFxuICBCYXNlVHJhbnNhY3Rpb25CdWlsZGVyLFxuICBCdWlsZFRyYW5zYWN0aW9uRXJyb3IsXG4gIFB1YmxpY0tleSBhcyBCYXNlUHVibGljS2V5LFxuICBTaWduYXR1cmUsXG4gIFRyYW5zYWN0aW9uVHlwZSxcbiAgVXRpbHNFcnJvcixcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgQXNzZXQsIFRyYW5zYWN0aW9uLCBUcmFuc2FjdGlvbklucHV0LCBUcmFuc2FjdGlvbk91dHB1dCwgV2l0aGRyYXdhbCB9IGZyb20gJy4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgS2V5UGFpciB9IGZyb20gJy4va2V5UGFpcic7XG5pbXBvcnQgdXRpbCwgeyBNSU5fQURBX0ZPUl9PTkVfQVNTRVQgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCAqIGFzIENhcmRhbm9XYXNtIGZyb20gJ0BlbXVyZ28vY2FyZGFuby1zZXJpYWxpemF0aW9uLWxpYi1ub2RlanMnO1xuaW1wb3J0IHsgQmlnTnVtIH0gZnJvbSAnQGVtdXJnby9jYXJkYW5vLXNlcmlhbGl6YXRpb24tbGliLW5vZGVqcyc7XG5cbi8qKlxuICogQ29uc3RhbnRzIGZvciB0cmFuc2FjdGlvbiBidWlsZGluZ1xuICovXG5jb25zdCBGRUVfQ09FRkZJQ0lFTlRTID0ge1xuICAvKiogTGluZWFyIGZlZSBwYXJhbWV0ZXIgYSAqL1xuICBBX0NPRUZGSUNJRU5UOiAnNDQnLFxuICAvKiogTGluZWFyIGZlZSBwYXJhbWV0ZXIgYiAqL1xuICBCX0NPRUZGSUNJRU5UOiAnMTU1MzgxJyxcbiAgLyoqIEFkZGl0aW9uYWwgc2FmZXR5IG1hcmdpbiBmb3IgdGhlIGZlZSAqL1xuICBTQUZFVFlfTUFSR0lOOiAnNDQwJyxcbn07XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBUcmFuc2FjdGlvbkJ1aWxkZXIgZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb25CdWlsZGVyIHtcbiAgcHJvdGVjdGVkIF90cmFuc2FjdGlvbiE6IFRyYW5zYWN0aW9uO1xuICBwcm90ZWN0ZWQgX3NpZ25lcnM6IEtleVBhaXJbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX3RyYW5zYWN0aW9uSW5wdXRzOiBUcmFuc2FjdGlvbklucHV0W10gPSBbXTtcbiAgcHJvdGVjdGVkIF90cmFuc2FjdGlvbk91dHB1dHM6IFRyYW5zYWN0aW9uT3V0cHV0W10gPSBbXTtcbiAgcHJvdGVjdGVkIF9pbml0U2lnbmF0dXJlczogU2lnbmF0dXJlW10gPSBbXTtcbiAgcHJvdGVjdGVkIF9zaWduYXR1cmVzOiBTaWduYXR1cmVbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX2NoYW5nZUFkZHJlc3M6IHN0cmluZztcbiAgcHJvdGVjdGVkIF9zZW5kZXJCYWxhbmNlOiBzdHJpbmc7XG4gIHByb3RlY3RlZCBfdHRsID0gMDtcbiAgcHJvdGVjdGVkIF9jZXJ0czogQ2FyZGFub1dhc20uQ2VydGlmaWNhdGVbXSA9IFtdO1xuICBwcm90ZWN0ZWQgX3dpdGhkcmF3YWxzOiBXaXRoZHJhd2FsW10gPSBbXTtcbiAgcHJvdGVjdGVkIF90eXBlOiBUcmFuc2FjdGlvblR5cGU7XG4gIHByb3RlY3RlZCBfbXVsdGlBc3NldHM6IEFzc2V0W10gPSBbXTtcbiAgLyoqIEFkZHJlc3Mgb2YgdGhlIHRyYW5zYWN0aW9uIHJlY2lwaWVudCAqL1xuICBwcm90ZWN0ZWQgX3JlY2lwaWVudEFkZHJlc3M6IHN0cmluZztcbiAgLyoqIE1hcCBvZiBzZW5kZXIncyBhc3NldHMgYnkgYXNzZXQgbmFtZSAqL1xuICBwcm90ZWN0ZWQgX3NlbmRlckFzc2V0TGlzdDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICBwcml2YXRlIF9mZWU6IEJpZ051bTtcbiAgLyoqIEZsYWcgaW5kaWNhdGluZyBpZiB0aGlzIGlzIGEgdG9rZW4gdHJhbnNhY3Rpb24gKi9cbiAgcHJpdmF0ZSBfaXNUb2tlblRyYW5zYWN0aW9uID0gZmFsc2U7XG4gIC8qKiBEZWVwIGNsb25lIG9mIF9zZW5kZXJBc3NldExpc3QgLSBmb3IgbWFuaXB1bGF0aW5nIGR1cmluZyB0d28gaXRlcmF0aW9uc1xuICAgKiAgIC0gb25lIGZvciBjYWxjdWxhdGluZyB0aGUgZmVlXG4gICAqICAgLSBvbmUgZm9yIHRoZSBhY3R1YWwgdHJhbnNhY3Rpb24gYnVpbGQgd2l0aCB0aGUgY2FsY3VsYXRlZCBmZWVcbiAgICogKi9cbiAgcHJpdmF0ZSBfbXV0YWJsZVNlbmRlckFzc2V0TGlzdDogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKF9jb2luQ29uZmlnOiBSZWFkb25seTxDb2luQ29uZmlnPikge1xuICAgIHN1cGVyKF9jb2luQ29uZmlnKTtcbiAgICB0aGlzLnRyYW5zYWN0aW9uID0gbmV3IFRyYW5zYWN0aW9uKF9jb2luQ29uZmlnKTtcbiAgICB0aGlzLl9mZWUgPSBCaWdOdW0uemVybygpO1xuICB9XG5cbiAgaW5wdXQoaTogVHJhbnNhY3Rpb25JbnB1dCk6IHRoaXMge1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uSW5wdXRzLnB1c2goaSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBvdXRwdXQobzogVHJhbnNhY3Rpb25PdXRwdXQpOiB0aGlzIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbk91dHB1dHMucHVzaChvKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGFzc2V0cyhhOiBBc3NldCk6IHRoaXMge1xuICAgIHRoaXMuX211bHRpQXNzZXRzLnB1c2goYSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICB0dGwodDogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5fdHRsID0gdDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBjaGFuZ2UgYWRkcmVzcyBhbmQgaW5wdXQgYmFsYW5jZXMgZm9yIHRoZSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gYWRkciAtIFRoZSBhZGRyZXNzIHdoZXJlIGNoYW5nZSB3aWxsIGJlIHNlbnRcbiAgICogQHBhcmFtIHRvdGFsSW5wdXRCYWxhbmNlIC0gVGhlIHRvdGFsIEFEQSBpbnB1dCBiYWxhbmNlIGluIExvdmVsYWNlXG4gICAqIEBwYXJhbSBpbnB1dEFzc2V0TGlzdCAtIE9wdGlvbmFsIG1hcCBvZiB0b2tlbiBhc3NldHMgaW4gdGhlIGlucHV0XG4gICAqL1xuICBjaGFuZ2VBZGRyZXNzKGFkZHI6IHN0cmluZywgdG90YWxJbnB1dEJhbGFuY2U6IHN0cmluZywgaW5wdXRBc3NldExpc3Q/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdGhpcyB7XG4gICAgdGhpcy5fY2hhbmdlQWRkcmVzcyA9IGFkZHI7XG4gICAgdGhpcy5fc2VuZGVyQmFsYW5jZSA9IHRvdGFsSW5wdXRCYWxhbmNlO1xuICAgIHRoaXMuX3NlbmRlckFzc2V0TGlzdCA9IGlucHV0QXNzZXRMaXN0ID8/IHt9O1xuICAgIHRoaXMuc2V0TXV0YWJsZVNlbmRlckFzc2V0TGlzdCgpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgc2V0TXV0YWJsZVNlbmRlckFzc2V0TGlzdCgpIHtcbiAgICB0aGlzLl9tdXRhYmxlU2VuZGVyQXNzZXRMaXN0ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLl9zZW5kZXJBc3NldExpc3QpKTtcbiAgfVxuXG4gIGZlZShmZWU6IHN0cmluZyk6IHRoaXMge1xuICAgIHRoaXMuX2ZlZSA9IEJpZ051bS5mcm9tX3N0cihmZWUpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcmtzIHRoaXMgdHJhbnNhY3Rpb24gYXMgYSB0b2tlbiB0cmFuc2FjdGlvblxuICAgKiBFbmFibGVzIHNwZWNpYWwgaGFuZGxpbmcgZm9yIHRva2VuIHRyYW5zZmVyc1xuICAgKi9cbiAgaXNUb2tlblRyYW5zYWN0aW9uKCkge1xuICAgIHRoaXMuX2lzVG9rZW5UcmFuc2FjdGlvbiA9IHRydWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgdHJhbnNhY3Rpb24gYnVpbGRlciBmaWVsZHMgdXNpbmcgdGhlIGRlY29kZWQgdHJhbnNhY3Rpb24gZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9ufSB0eCB0aGUgdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgaW5pdEJ1aWxkZXIodHg6IFRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb24gPSB0eDtcbiAgICBjb25zdCB0eG5Cb2R5ID0gdHgudHJhbnNhY3Rpb24uYm9keSgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdHhuQm9keS5pbnB1dHMoKS5sZW4oKTsgaSsrKSB7XG4gICAgICBjb25zdCBpbnB1dCA9IHR4bkJvZHkuaW5wdXRzKCkuZ2V0KGkpO1xuICAgICAgdGhpcy5pbnB1dCh7XG4gICAgICAgIHRyYW5zYWN0aW9uX2lkOiBCdWZmZXIuZnJvbShpbnB1dC50cmFuc2FjdGlvbl9pZCgpLnRvX2J5dGVzKCkpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgdHJhbnNhY3Rpb25faW5kZXg6IGlucHV0LmluZGV4KCksXG4gICAgICB9KTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0eG5Cb2R5Lm91dHB1dHMoKS5sZW4oKTsgaSsrKSB7XG4gICAgICBjb25zdCBvdXRwdXQgPSB0eG5Cb2R5Lm91dHB1dHMoKS5nZXQoaSk7XG4gICAgICB0aGlzLm91dHB1dCh7XG4gICAgICAgIGFkZHJlc3M6IG91dHB1dC5hZGRyZXNzKCkudG9fYmVjaDMyKCksXG4gICAgICAgIGFtb3VudDogb3V0cHV0LmFtb3VudCgpLmNvaW4oKS50b19zdHIoKSxcbiAgICAgICAgbXVsdGlBc3NldHM6IG91dHB1dC5hbW91bnQoKS5tdWx0aWFzc2V0KCkgfHwgdW5kZWZpbmVkLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHR4bkJvZHkuY2VydHMoKSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBjZXJ0cyA9IHR4bkJvZHkuY2VydHMoKSBhcyBDYXJkYW5vV2FzbS5DZXJ0aWZpY2F0ZXM7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNlcnRzLmxlbigpOyBpKyspIHtcbiAgICAgICAgdGhpcy5fY2VydHMucHVzaChjZXJ0cy5nZXQoaSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eG5Cb2R5LndpdGhkcmF3YWxzKCkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3Qgd2l0aGRyYXdhbHMgPSB0eG5Cb2R5LndpdGhkcmF3YWxzKCkgYXMgQ2FyZGFub1dhc20uV2l0aGRyYXdhbHM7XG4gICAgICBjb25zdCBrZXlzID0gd2l0aGRyYXdhbHMua2V5cygpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlzLmxlbigpOyBpKyspIHtcbiAgICAgICAgY29uc3QgcmV3YXJkQWRkcmVzcyA9IGtleXMuZ2V0KGkpIGFzIENhcmRhbm9XYXNtLlJld2FyZEFkZHJlc3M7XG4gICAgICAgIGNvbnN0IHJld2FyZCA9IHdpdGhkcmF3YWxzLmdldChyZXdhcmRBZGRyZXNzKSBhcyBDYXJkYW5vV2FzbS5CaWdOdW07XG4gICAgICAgIHRoaXMuX3dpdGhkcmF3YWxzLnB1c2goeyBzdGFrZUFkZHJlc3M6IHJld2FyZEFkZHJlc3MudG9fYWRkcmVzcygpLnRvX2JlY2gzMigpLCB2YWx1ZTogcmV3YXJkLnRvX3N0cigpIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3R0bCA9IHR4LnRyYW5zYWN0aW9uLmJvZHkoKS50dGwoKSBhcyBudW1iZXI7XG4gICAgdGhpcy5fZmVlID0gdHgudHJhbnNhY3Rpb24uYm9keSgpLmZlZSgpO1xuXG4gICAgaWYgKHR4LnRyYW5zYWN0aW9uLndpdG5lc3Nfc2V0KCkudmtleXMoKSkge1xuICAgICAgY29uc3QgdmtleXMgPSB0eC50cmFuc2FjdGlvbi53aXRuZXNzX3NldCgpLnZrZXlzKCkhIGFzIENhcmRhbm9XYXNtLlZrZXl3aXRuZXNzZXM7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZrZXlzLmxlbigpOyBpKyspIHtcbiAgICAgICAgY29uc3QgdmtleSA9IHZrZXlzLmdldChpKTtcbiAgICAgICAgdGhpcy5faW5pdFNpZ25hdHVyZXMucHVzaCh7XG4gICAgICAgICAgcHVibGljS2V5OiB7IHB1YjogdmtleS52a2V5KCkucHVibGljX2tleSgpLnRvX2hleCgpIH0sXG4gICAgICAgICAgc2lnbmF0dXJlOiBCdWZmZXIuZnJvbSh2a2V5LnNpZ25hdHVyZSgpLnRvX2hleCgpLCAnaGV4JyksXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZnJvbUltcGxlbWVudGF0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiBUcmFuc2FjdGlvbiB7XG4gICAgdGhpcy52YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uKTtcbiAgICB0aGlzLmJ1aWxkSW1wbGVtZW50YXRpb24oKTtcbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSB0cmFuc2FjdGlvbiB0aGF0IGluY2x1ZGVzIHRva2VuIGFzc2V0c1xuICAgKiBAcmV0dXJucyBUaGUgYnVpbHQgdHJhbnNhY3Rpb25cbiAgICovXG4gIHByaXZhdGUgcHJvY2Vzc1Rva2VuQnVpbGQoKTogVHJhbnNhY3Rpb24ge1xuICAgIGNvbnN0IGlucHV0cyA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uSW5wdXRzLm5ldygpO1xuICAgIGxldCBvdXRwdXRzID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRzLm5ldygpO1xuICAgIHRoaXMuYWRkSW5wdXRzKGlucHV0cyk7XG4gICAgLy8gRmVlIGlzIG5ldmVyIHNldCBzbyBmYXIgZnJvbSBJTVNcbiAgICBpZiAodGhpcy5fZmVlLmlzX3plcm8oKSkge1xuICAgICAgdGhpcy5hZGRPdXRwdXRzKG91dHB1dHMpO1xuICAgICAgY29uc3QgdHhEcmFmdCA9IHRoaXMucHJlcGFyZUFkYVRyYW5zYWN0aW9uRHJhZnQoaW5wdXRzLCBvdXRwdXRzLCBmYWxzZSk7XG4gICAgICB0aGlzLmNhbGN1bGF0ZUZlZSh0eERyYWZ0KTtcbiAgICAgIHRoaXMuc2V0RmVlSW5UcmFuc2FjdGlvbigpO1xuICAgIH1cbiAgICAvLyBSZXNldCBvdXRwdXRzIHRvIGFkZCB0aGVtIGJhY2sgd2l0aCB0aGUgY29ycmVjdCBjaGFuZ2VcbiAgICBvdXRwdXRzID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRzLm5ldygpO1xuICAgIHRoaXMuc2V0TXV0YWJsZVNlbmRlckFzc2V0TGlzdCgpO1xuICAgIHRoaXMuYWRkT3V0cHV0cyhvdXRwdXRzKTtcbiAgICB0aGlzLl90cmFuc2FjdGlvbi50cmFuc2FjdGlvbiA9IHRoaXMucHJlcGFyZUFkYVRyYW5zYWN0aW9uRHJhZnQoaW5wdXRzLCBvdXRwdXRzLCB0cnVlKTtcbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIHRyYW5zYWN0aW9uIGlucHV0cyB0byB0aGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGlucHV0cyAtIFRoZSBpbnB1dHMgY29sbGVjdGlvbiB0byBhZGQgdG9cbiAgICovXG4gIHByaXZhdGUgYWRkSW5wdXRzKGlucHV0cykge1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uSW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICBpbnB1dHMuYWRkKFxuICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbklucHV0Lm5ldyhcbiAgICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbkhhc2guZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShpbnB1dC50cmFuc2FjdGlvbl9pZCwgJ2hleCcpKSxcbiAgICAgICAgICBpbnB1dC50cmFuc2FjdGlvbl9pbmRleFxuICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgb3V0cHV0cyB0byB0aGUgdHJhbnNhY3Rpb24gaW5jbHVkaW5nIHRva2VuIG91dHB1dHMgYW5kIGNoYW5nZVxuICAgKiBAcGFyYW0gb3V0cHV0cyAtIFRoZSBvdXRwdXRzIGNvbGxlY3Rpb24gdG8gYWRkIHRvXG4gICAqL1xuICBwcml2YXRlIGFkZE91dHB1dHMob3V0cHV0cykge1xuICAgIGNvbnN0IHV0eG9CYWxhbmNlID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX3NlbmRlckJhbGFuY2UpOyAvLyBUb3RhbCBVVFhPIGJhbGFuY2VcbiAgICBjb25zdCBjaGFuZ2UgPSB1dHhvQmFsYW5jZS5jaGVja2VkX3N1Yih0aGlzLl9mZWUpO1xuICAgIGNvbnN0IGNoYW5nZUFmdGVyUmVjZWl2ZXJEZWR1Y3Rpb25zID0gdGhpcy5hZGRSZWNlaXZlck91dHB1dHMob3V0cHV0cywgY2hhbmdlKTtcbiAgICB0aGlzLmFkZENoYW5nZU91dHB1dChjaGFuZ2VBZnRlclJlY2VpdmVyRGVkdWN0aW9ucywgb3V0cHV0cyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyByZWNlaXZlciBvdXRwdXRzIHRvIHRoZSB0cmFuc2FjdGlvbiBhbmQgY2FsY3VsYXRlcyB0aGUgcmVtYWluaW5nIGNoYW5nZVxuICAgKiBAcGFyYW0gb3V0cHV0cyAtIFRyYW5zYWN0aW9uIG91dHB1dHMgY29sbGVjdGlvblxuICAgKiBAcGFyYW0gY2hhbmdlIC0gQ3VycmVudCBjaGFuZ2UgYW1vdW50IGluIEFEQVxuICAgKiBAcmV0dXJucyBSZW1haW5pbmcgY2hhbmdlIGFmdGVyIGFkZGluZyByZWNlaXZlciBvdXRwdXRzXG4gICAqL1xuICBwcml2YXRlIGFkZFJlY2VpdmVyT3V0cHV0cyhvdXRwdXRzLCBjaGFuZ2UpIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbk91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiB7XG4gICAgICBpZiAoIW91dHB1dC5hZGRyZXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgb3V0cHV0OiBtaXNzaW5nIGFkZHJlc3MnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVjZWl2ZXJBZGRyZXNzID0gb3V0cHV0LmFkZHJlc3M7XG4gICAgICBjb25zdCByZWNlaXZlckFtb3VudCA9IG91dHB1dC5hbW91bnQ7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlY2VpdmVyQW1vdW50Qk4gPSBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIocmVjZWl2ZXJBbW91bnQpO1xuICAgICAgICBjaGFuZ2UgPSBjaGFuZ2UuY2hlY2tlZF9zdWIocmVjZWl2ZXJBbW91bnRCTik7XG5cbiAgICAgICAgaWYgKGNoYW5nZS5sZXNzX3RoYW4oQ2FyZGFub1dhc20uQmlnTnVtLnplcm8oKSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICAgICAgJ0luc3VmZmljaWVudCBmdW5kczogbm90IGVub3VnaCBBREEgdG8gY292ZXIgcmVjZWl2ZXIgb3V0cHV0IGFtb3VudHMgYW5kIGZlZXMnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG11bHRpQXNzZXRzID0gb3V0cHV0Lm11bHRpQXNzZXRzIGFzIEFzc2V0O1xuICAgICAgICBpZiAobXVsdGlBc3NldHMpIHtcbiAgICAgICAgICBjb25zdCBwb2xpY3lJZCA9IG11bHRpQXNzZXRzLnBvbGljeV9pZDtcbiAgICAgICAgICBjb25zdCBhc3NldE5hbWUgPSBtdWx0aUFzc2V0cy5hc3NldF9uYW1lO1xuICAgICAgICAgIGNvbnN0IHF1YW50aXR5ID0gbXVsdGlBc3NldHMucXVhbnRpdHk7XG4gICAgICAgICAgY29uc3QgZmluZ2VycHJpbnQgPSBtdWx0aUFzc2V0cy5maW5nZXJwcmludCBhcyBzdHJpbmc7XG5cbiAgICAgICAgICBjb25zdCBjdXJyZW50UXR5ID0gdGhpcy5fbXV0YWJsZVNlbmRlckFzc2V0TGlzdFtmaW5nZXJwcmludF0ucXVhbnRpdHk7XG4gICAgICAgICAgY29uc3QgcmVtYWluaW5nUXR5ID0gQmlnSW50KGN1cnJlbnRRdHkpIC0gQmlnSW50KHF1YW50aXR5KTtcbiAgICAgICAgICB0aGlzLl9tdXRhYmxlU2VuZGVyQXNzZXRMaXN0W2ZpbmdlcnByaW50XS5xdWFudGl0eSA9IChyZW1haW5pbmdRdHkgPiAwbiA/IHJlbWFpbmluZ1F0eSA6IDBuKS50b1N0cmluZygpO1xuXG4gICAgICAgICAgaWYgKENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih0aGlzLl9tdXRhYmxlU2VuZGVyQXNzZXRMaXN0W2ZpbmdlcnByaW50XS5xdWFudGl0eSkuaXNfemVybygpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnN1ZmZpY2llbnQgcXR5OiBub3QgZW5vdWdoIHRva2VuIHF0eSB0byBjb3ZlciByZWNlaXZlciBvdXRwdXQnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBtaW5BbW91bnROZWVkZWRGb3JBc3NldE91dHB1dCA9IHRoaXMuYWRkVG9rZW5zVG9PdXRwdXQoY2hhbmdlLCBvdXRwdXRzLCByZWNlaXZlckFkZHJlc3MsIHtcbiAgICAgICAgICAgIHBvbGljeV9pZDogcG9saWN5SWQsXG4gICAgICAgICAgICBhc3NldF9uYW1lOiBhc3NldE5hbWUsXG4gICAgICAgICAgICBxdWFudGl0eSxcbiAgICAgICAgICAgIGZpbmdlcnByaW50LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgY2hhbmdlID0gY2hhbmdlLmNoZWNrZWRfc3ViKG1pbkFtb3VudE5lZWRlZEZvckFzc2V0T3V0cHV0KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIEJ1aWxkVHJhbnNhY3Rpb25FcnJvcikge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgRXJyb3IgcHJvY2Vzc2luZyBvdXRwdXQ6ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBjaGFuZ2U7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyB0b2tlbnMgdG8gYSB0cmFuc2FjdGlvbiBvdXRwdXRcbiAgICogQHBhcmFtIGNoYW5nZSAtIFRoZSBjdXJyZW50IGNoYW5nZSBhbW91bnQgaW4gTG92ZWxhY2VcbiAgICogQHBhcmFtIG91dHB1dHMgLSBUaGUgb3V0cHV0cyBjb2xsZWN0aW9uIHRvIGFkZCB0b1xuICAgKiBAcGFyYW0gYWRkcmVzcyAtIFRoZSByZWNpcGllbnQgYWRkcmVzc1xuICAgKiBAcGFyYW0gYXNzZXQgLSBUaGUgYXNzZXQgdG8gYWRkXG4gICAqIEByZXR1cm5zIFRoZSBtaW5pbXVtIEFEQSBhbW91bnQgbmVlZGVkIGZvciB0aGlzIGFzc2V0IG91dHB1dFxuICAgKi9cbiAgcHJpdmF0ZSBhZGRUb2tlbnNUb091dHB1dChjaGFuZ2U6IEJpZ051bSwgb3V0cHV0czogQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRzLCBhZGRyZXNzLCBhc3NldDogQXNzZXQpOiBCaWdOdW0ge1xuICAgIGNvbnN0IG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0ID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKE1JTl9BREFfRk9SX09ORV9BU1NFVCk7XG4gICAgaWYgKGNoYW5nZS5sZXNzX3RoYW4obWluQW1vdW50TmVlZGVkRm9yT25lQXNzZXRPdXRwdXQpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW5zdWZmaWNpZW50IGZ1bmRzOiBuZWVkIGEgbWluaW11bSBvZiAke01JTl9BREFfRk9SX09ORV9BU1NFVH0gbG92ZWxhY2UgcGVyIG91dHB1dCB0byBjb25zdHJ1Y3QgdG9rZW4gdHJhbnNhY3Rpb25zYFxuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy5idWlsZFRva2Vucyhhc3NldCwgbWluQW1vdW50TmVlZGVkRm9yT25lQXNzZXRPdXRwdXQsIG91dHB1dHMsIGFkZHJlc3MpO1xuICAgIHJldHVybiBtaW5BbW91bnROZWVkZWRGb3JPbmVBc3NldE91dHB1dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdG9rZW4gb3V0cHV0cyBmb3IgYSB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0gYXNzZXQgLSBUaGUgYXNzZXQgdG8gaW5jbHVkZSBpbiB0aGUgb3V0cHV0XG4gICAqIEBwYXJhbSBtaW5BbW91bnROZWVkZWRGb3JPbmVBc3NldE91dHB1dCAtIE1pbmltdW0gQURBIHJlcXVpcmVkIGZvciB0aGlzIGFzc2V0IG91dHB1dFxuICAgKiBAcGFyYW0gb3V0cHV0cyAtIFRyYW5zYWN0aW9uIG91dHB1dHMgY29sbGVjdGlvblxuICAgKiBAcGFyYW0gYWRkcmVzcyAtIFJlY2lwaWVudCBhZGRyZXNzXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkVG9rZW5zKGFzc2V0OiBBc3NldCwgbWluQW1vdW50TmVlZGVkRm9yT25lQXNzZXRPdXRwdXQsIG91dHB1dHMsIGFkZHJlc3MpIHtcbiAgICBsZXQgdHhPdXRwdXRCdWlsZGVyID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRCdWlsZGVyLm5ldygpO1xuICAgIGNvbnN0IHRvQWRkcmVzcyA9IHV0aWwuZ2V0V2FsbGV0QWRkcmVzcyhhZGRyZXNzKTtcbiAgICB0eE91dHB1dEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIud2l0aF9hZGRyZXNzKHRvQWRkcmVzcyk7XG4gICAgbGV0IHR4T3V0cHV0QW1vdW50QnVpbGRlciA9IHR4T3V0cHV0QnVpbGRlci5uZXh0KCk7XG4gICAgY29uc3QgYXNzZXROYW1lID0gQ2FyZGFub1dhc20uQXNzZXROYW1lLm5ldyhCdWZmZXIuZnJvbShhc3NldC5hc3NldF9uYW1lLCAnaGV4JykpO1xuICAgIGNvbnN0IHBvbGljeUlkID0gQ2FyZGFub1dhc20uU2NyaXB0SGFzaC5mcm9tX2J5dGVzKEJ1ZmZlci5mcm9tKGFzc2V0LnBvbGljeV9pZCwgJ2hleCcpKTtcbiAgICBjb25zdCBtdWx0aUFzc2V0ID0gQ2FyZGFub1dhc20uTXVsdGlBc3NldC5uZXcoKTtcbiAgICBjb25zdCBhc3NldHMgPSBDYXJkYW5vV2FzbS5Bc3NldHMubmV3KCk7XG4gICAgYXNzZXRzLmluc2VydChhc3NldE5hbWUsIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihhc3NldC5xdWFudGl0eSkpO1xuICAgIG11bHRpQXNzZXQuaW5zZXJ0KHBvbGljeUlkLCBhc3NldHMpO1xuXG4gICAgdHhPdXRwdXRBbW91bnRCdWlsZGVyID0gdHhPdXRwdXRBbW91bnRCdWlsZGVyLndpdGhfY29pbl9hbmRfYXNzZXQobWluQW1vdW50TmVlZGVkRm9yT25lQXNzZXRPdXRwdXQsIG11bHRpQXNzZXQpO1xuXG4gICAgY29uc3QgdHhPdXRwdXQgPSB0eE91dHB1dEFtb3VudEJ1aWxkZXIuYnVpbGQoKTtcbiAgICBvdXRwdXRzLmFkZCh0eE91dHB1dCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGNoYW5nZSBvdXRwdXQgdG8gdGhlIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBjaGFuZ2UgLSBUaGUgY2hhbmdlIGFtb3VudCBpbiBMb3ZlbGFjZVxuICAgKiBAcGFyYW0gb3V0cHV0cyAtIFRoZSBvdXRwdXRzIGNvbGxlY3Rpb24gdG8gYWRkIHRvXG4gICAqL1xuICBwcml2YXRlIGFkZENoYW5nZU91dHB1dChjaGFuZ2UsIG91dHB1dHMpIHtcbiAgICBjb25zdCBjaGFuZ2VBZGRyZXNzID0gdXRpbC5nZXRXYWxsZXRBZGRyZXNzKHRoaXMuX2NoYW5nZUFkZHJlc3MpO1xuICAgIE9iamVjdC5rZXlzKHRoaXMuX211dGFibGVTZW5kZXJBc3NldExpc3QpLmZvckVhY2goKGZpbmdlcnByaW50KSA9PiB7XG4gICAgICBjb25zdCBhc3NldCA9IHRoaXMuX211dGFibGVTZW5kZXJBc3NldExpc3RbZmluZ2VycHJpbnRdO1xuICAgICAgY29uc3QgY2hhbmdlUXR5ID0gYXNzZXQucXVhbnRpdHk7XG4gICAgICBjb25zdCBwb2xpY3lJZCA9IGFzc2V0LnBvbGljeV9pZDtcbiAgICAgIGNvbnN0IGFzc2V0TmFtZSA9IGFzc2V0LmFzc2V0X25hbWU7XG5cbiAgICAgIGlmIChDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIoY2hhbmdlUXR5KS5pc196ZXJvKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtaW5BbW91bnROZWVkZWRGb3JBc3NldE91dHB1dCA9IHRoaXMuYWRkVG9rZW5zVG9PdXRwdXQoY2hhbmdlLCBvdXRwdXRzLCB0aGlzLl9jaGFuZ2VBZGRyZXNzLCB7XG4gICAgICAgIHBvbGljeV9pZDogcG9saWN5SWQsXG4gICAgICAgIGFzc2V0X25hbWU6IGFzc2V0TmFtZSxcbiAgICAgICAgcXVhbnRpdHk6IGNoYW5nZVF0eSxcbiAgICAgICAgZmluZ2VycHJpbnQsXG4gICAgICB9KTtcbiAgICAgIGNoYW5nZSA9IGNoYW5nZS5jaGVja2VkX3N1YihtaW5BbW91bnROZWVkZWRGb3JBc3NldE91dHB1dCk7XG4gICAgfSk7XG4gICAgaWYgKCFjaGFuZ2UuaXNfemVybygpKSB7XG4gICAgICBjb25zdCBjaGFuZ2VPdXRwdXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoY2hhbmdlQWRkcmVzcywgQ2FyZGFub1dhc20uVmFsdWUubmV3KGNoYW5nZSkpO1xuICAgICAgb3V0cHV0cy5hZGQoY2hhbmdlT3V0cHV0KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgY2FsY3VsYXRlZCBmZWUgaW4gdGhlIHRyYW5zYWN0aW9uXG4gICAqL1xuICBwcml2YXRlIHNldEZlZUluVHJhbnNhY3Rpb24oKSB7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb24uZmVlKHRoaXMuX2ZlZS50b19zdHIoKSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgdHJhbnNhY3Rpb24gZmVlIGJhc2VkIG9uIHRyYW5zYWN0aW9uIHNpemVcbiAgICogQHBhcmFtIHR4RHJhZnQgLSBEcmFmdCB0cmFuc2FjdGlvbiB0byBjYWxjdWxhdGUgZmVlIGZvclxuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVGZWUodHhEcmFmdCkge1xuICAgIGNvbnN0IGxpbmVhckZlZSA9IENhcmRhbm9XYXNtLkxpbmVhckZlZS5uZXcoXG4gICAgICBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIoRkVFX0NPRUZGSUNJRU5UUy5BX0NPRUZGSUNJRU5UKSxcbiAgICAgIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihGRUVfQ09FRkZJQ0lFTlRTLkJfQ09FRkZJQ0lFTlQpXG4gICAgKTtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgZmVlIGJhc2VkIG9mZiBvdXIgZHVtbXkgdHJhbnNhY3Rpb25cbiAgICBjb25zdCBmZWUgPSBDYXJkYW5vV2FzbS5taW5fZmVlKHR4RHJhZnQsIGxpbmVhckZlZSkuY2hlY2tlZF9hZGQoQmlnTnVtLmZyb21fc3RyKEZFRV9DT0VGRklDSUVOVFMuU0FGRVRZX01BUkdJTikpO1xuICAgIHRoaXMuX2ZlZSA9IGZlZTtcbiAgfVxuXG4gIHByaXZhdGUgcHJlcGFyZUFkYVRyYW5zYWN0aW9uRHJhZnQoaW5wdXRzLCBvdXRwdXRzLCByZWZyZXNoU2lnbmF0dXJlcyA9IGZhbHNlKSB7XG4gICAgY29uc3QgdHhCb2R5ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25Cb2R5Lm5ld190eF9ib2R5KGlucHV0cywgb3V0cHV0cywgdGhpcy5fZmVlKTtcbiAgICB0eEJvZHkuc2V0X3R0bChDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIodGhpcy5fdHRsLnRvU3RyaW5nKCkpKTtcbiAgICBjb25zdCB0eEhhc2ggPSBDYXJkYW5vV2FzbS5oYXNoX3RyYW5zYWN0aW9uKHR4Qm9keSk7XG5cbiAgICAvLyB3ZSBhZGQgd2l0bmVzc2VzIG9uY2Ugc28gdGhhdCB3ZSBjYW4gZ2V0IHRoZSBhcHByb3ByaWF0ZSBhbW91bnQgb2Ygc2lnbmVycyBmb3IgY2FsY3VsYXRpbmcgdGhlIGZlZVxuICAgIGNvbnN0IHdpdG5lc3NTZXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbldpdG5lc3NTZXQubmV3KCk7XG4gICAgY29uc3QgdmtleVdpdG5lc3NlcyA9IENhcmRhbm9XYXNtLlZrZXl3aXRuZXNzZXMubmV3KCk7XG4gICAgdGhpcy5fc2lnbmVycy5mb3JFYWNoKChrZXlQYWlyKSA9PiB7XG4gICAgICBjb25zdCBwcnYgPSBrZXlQYWlyLmdldEtleXMoKS5wcnYgYXMgc3RyaW5nO1xuICAgICAgY29uc3QgdmtleVdpdG5lc3MgPSBDYXJkYW5vV2FzbS5tYWtlX3ZrZXlfd2l0bmVzcyhcbiAgICAgICAgdHhIYXNoLFxuICAgICAgICBDYXJkYW5vV2FzbS5Qcml2YXRlS2V5LmZyb21fbm9ybWFsX2J5dGVzKEJ1ZmZlci5mcm9tKHBydiwgJ2hleCcpKVxuICAgICAgKTtcbiAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKHZrZXlXaXRuZXNzKTtcbiAgICB9KTtcbiAgICBpZiAocmVmcmVzaFNpZ25hdHVyZXMpIHtcbiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uLnNpZ25hdHVyZS5sZW5ndGggPSAwO1xuICAgIH1cbiAgICB0aGlzLmdldEFsbFNpZ25hdHVyZXMoKS5mb3JFYWNoKChzaWduYXR1cmUpID0+IHtcbiAgICAgIGNvbnN0IHZrZXkgPSBDYXJkYW5vV2FzbS5Wa2V5Lm5ldyhDYXJkYW5vV2FzbS5QdWJsaWNLZXkuZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShzaWduYXR1cmUucHVibGljS2V5LnB1YiwgJ2hleCcpKSk7XG4gICAgICBjb25zdCBlZDI1NVNpZyA9IENhcmRhbm9XYXNtLkVkMjU1MTlTaWduYXR1cmUuZnJvbV9ieXRlcyhzaWduYXR1cmUuc2lnbmF0dXJlKTtcbiAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKENhcmRhbm9XYXNtLlZrZXl3aXRuZXNzLm5ldyh2a2V5LCBlZDI1NVNpZykpO1xuICAgIH0pO1xuICAgIGlmICh2a2V5V2l0bmVzc2VzLmxlbigpID09PSAwKSB7XG4gICAgICBjb25zdCBwcnYgPSBDYXJkYW5vV2FzbS5Qcml2YXRlS2V5LmdlbmVyYXRlX2VkMjU1MTkoKTtcbiAgICAgIGNvbnN0IHZrZXlXaXRuZXNzID0gQ2FyZGFub1dhc20ubWFrZV92a2V5X3dpdG5lc3ModHhIYXNoLCBwcnYpO1xuICAgICAgdmtleVdpdG5lc3Nlcy5hZGQodmtleVdpdG5lc3MpO1xuICAgICAgaWYgKHRoaXMuX3R5cGUgIT09IFRyYW5zYWN0aW9uVHlwZS5TZW5kKSB7XG4gICAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKHZrZXlXaXRuZXNzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgd2l0bmVzc1NldC5zZXRfdmtleXModmtleVdpdG5lc3Nlcyk7XG5cbiAgICAvLyBhZGQgaW4gY2VydGlmaWNhdGVzIHRvIGdldCBtb2NrIHNpemVcbiAgICBjb25zdCBkcmFmdENlcnRzID0gQ2FyZGFub1dhc20uQ2VydGlmaWNhdGVzLm5ldygpO1xuICAgIGZvciAoY29uc3QgY2VydCBvZiB0aGlzLl9jZXJ0cykge1xuICAgICAgZHJhZnRDZXJ0cy5hZGQoY2VydCk7XG4gICAgfVxuICAgIHR4Qm9keS5zZXRfY2VydHMoZHJhZnRDZXJ0cyk7XG5cbiAgICBjb25zdCB0eERyYWZ0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb24ubmV3KHR4Qm9keSwgd2l0bmVzc1NldCk7XG4gICAgcmV0dXJuIHR4RHJhZnQ7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGJ1aWxkSW1wbGVtZW50YXRpb24oKTogUHJvbWlzZTxUcmFuc2FjdGlvbj4ge1xuICAgIGlmICh0aGlzLl9pc1Rva2VuVHJhbnNhY3Rpb24pIHtcbiAgICAgIHJldHVybiB0aGlzLnByb2Nlc3NUb2tlbkJ1aWxkKCk7XG4gICAgfVxuICAgIGNvbnN0IGlucHV0cyA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uSW5wdXRzLm5ldygpO1xuICAgIHRoaXMuX3RyYW5zYWN0aW9uSW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgICBpbnB1dHMuYWRkKFxuICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbklucHV0Lm5ldyhcbiAgICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbkhhc2guZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShpbnB1dC50cmFuc2FjdGlvbl9pZCwgJ2hleCcpKSxcbiAgICAgICAgICBpbnB1dC50cmFuc2FjdGlvbl9pbmRleFxuICAgICAgICApXG4gICAgICApO1xuICAgIH0pO1xuICAgIGxldCBvdXRwdXRzID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXRzLm5ldygpO1xuICAgIGxldCB0b3RhbEFtb3VudFRvU2VuZCA9IENhcmRhbm9XYXNtLkJpZ051bS56ZXJvKCk7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb25PdXRwdXRzLmZvckVhY2goKG91dHB1dCkgPT4ge1xuICAgICAgY29uc3QgYW1vdW50ID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKG91dHB1dC5hbW91bnQpO1xuICAgICAgb3V0cHV0cy5hZGQoXG4gICAgICAgIENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0Lm5ldyh1dGlsLmdldFdhbGxldEFkZHJlc3Mob3V0cHV0LmFkZHJlc3MpLCBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcoYW1vdW50KSlcbiAgICAgICk7XG4gICAgICB0b3RhbEFtb3VudFRvU2VuZCA9IHRvdGFsQW1vdW50VG9TZW5kLmNoZWNrZWRfYWRkKGFtb3VudCk7XG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5fZmVlLmlzX3plcm8oKSkge1xuICAgICAgLy8gZXN0aW1hdGUgZmVlXG4gICAgICAvLyBhZGQgZXh0cmEgb3V0cHV0IGZvciB0aGUgY2hhbmdlXG4gICAgICBpZiAodGhpcy5fY2hhbmdlQWRkcmVzcyAmJiB0aGlzLl9zZW5kZXJCYWxhbmNlKSB7XG4gICAgICAgIGNvbnN0IGNoYW5nZUFkZHJlc3MgPSB1dGlsLmdldFdhbGxldEFkZHJlc3ModGhpcy5fY2hhbmdlQWRkcmVzcyk7XG4gICAgICAgIGNvbnN0IHV0eG9CYWxhbmNlID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX3NlbmRlckJhbGFuY2UpO1xuXG4gICAgICAgIGNvbnN0IGFkanVzdG1lbnQgPSBCaWdOdW0uZnJvbV9zdHIoJzIwMDAwMDAnKTtcbiAgICAgICAgbGV0IGNoYW5nZSA9IHV0eG9CYWxhbmNlLmNoZWNrZWRfc3ViKHRoaXMuX2ZlZSkuY2hlY2tlZF9zdWIodG90YWxBbW91bnRUb1NlbmQpO1xuICAgICAgICBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZSkge1xuICAgICAgICAgIGNoYW5nZSA9IGNoYW5nZS5jaGVja2VkX3N1YihhZGp1c3RtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLl90eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlYWN0aXZhdGUpIHtcbiAgICAgICAgICBjaGFuZ2UgPSBjaGFuZ2UuY2hlY2tlZF9hZGQoYWRqdXN0bWVudCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdyB8fCB0aGlzLl90eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0NsYWltKSB7XG4gICAgICAgICAgdGhpcy5fd2l0aGRyYXdhbHMuZm9yRWFjaCgod2l0aGRyYXdhbDogV2l0aGRyYXdhbCkgPT4ge1xuICAgICAgICAgICAgY2hhbmdlID0gY2hhbmdlLmNoZWNrZWRfYWRkKENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih3aXRoZHJhd2FsLnZhbHVlKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0b3RhbEFtb3VudFRvU2VuZCBpcyAwLCBpdHMgY29uc29saWRhdGlvblxuICAgICAgICBpZiAodG90YWxBbW91bnRUb1NlbmQudG9fc3RyKCkgPT0gJzAnKSB7XG4gICAgICAgICAgLy8gc3VwcG9ydCBmb3IgbXVsdGktYXNzZXQgY29uc29saWRhdGlvblxuICAgICAgICAgIGlmICh0aGlzLl9tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zdCB0b3RhbE51bWJlck9mQXNzZXRzID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX211bHRpQXNzZXRzLmxlbmd0aC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGNvbnN0IG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0ID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKE1JTl9BREFfRk9SX09ORV9BU1NFVCk7XG4gICAgICAgICAgICBjb25zdCBtaW5BbW91bnROZWVkZWRGb3JUb3RhbEFzc2V0T3V0cHV0cyA9XG4gICAgICAgICAgICAgIG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0LmNoZWNrZWRfbXVsKHRvdGFsTnVtYmVyT2ZBc3NldHMpO1xuXG4gICAgICAgICAgICBpZiAoIWNoYW5nZS5sZXNzX3RoYW4obWluQW1vdW50TmVlZGVkRm9yVG90YWxBc3NldE91dHB1dHMpKSB7XG4gICAgICAgICAgICAgIHRoaXMuX211bHRpQXNzZXRzLmZvckVhY2goKGFzc2V0KSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHR4T3V0cHV0QnVpbGRlciA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0QnVpbGRlci5uZXcoKTtcbiAgICAgICAgICAgICAgICAvLyBjaGFuZ2VBZGRyZXNzIGlzIHRoZSByb290IGFkZHJlc3MsIHdoaWNoIGlzIHdoZXJlIHdlIHdhbnQgdGhlIHRva2VucyBhc3NldHMgdG8gYmUgc2VudCB0b1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvQWRkcmVzcyA9IHV0aWwuZ2V0V2FsbGV0QWRkcmVzcyh0aGlzLl9jaGFuZ2VBZGRyZXNzKTtcbiAgICAgICAgICAgICAgICB0eE91dHB1dEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIud2l0aF9hZGRyZXNzKHRvQWRkcmVzcyk7XG4gICAgICAgICAgICAgICAgbGV0IHR4T3V0cHV0QW1vdW50QnVpbGRlciA9IHR4T3V0cHV0QnVpbGRlci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYXNzZXROYW1lID0gQ2FyZGFub1dhc20uQXNzZXROYW1lLm5ldyhCdWZmZXIuZnJvbShhc3NldC5hc3NldF9uYW1lLCAnaGV4JykpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBvbGljeUlkID0gQ2FyZGFub1dhc20uU2NyaXB0SGFzaC5mcm9tX2J5dGVzKEJ1ZmZlci5mcm9tKGFzc2V0LnBvbGljeV9pZCwgJ2hleCcpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtdWx0aUFzc2V0ID0gQ2FyZGFub1dhc20uTXVsdGlBc3NldC5uZXcoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBhc3NldHMgPSBDYXJkYW5vV2FzbS5Bc3NldHMubmV3KCk7XG4gICAgICAgICAgICAgICAgYXNzZXRzLmluc2VydChhc3NldE5hbWUsIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihhc3NldC5xdWFudGl0eSkpO1xuICAgICAgICAgICAgICAgIG11bHRpQXNzZXQuaW5zZXJ0KHBvbGljeUlkLCBhc3NldHMpO1xuXG4gICAgICAgICAgICAgICAgdHhPdXRwdXRBbW91bnRCdWlsZGVyID0gdHhPdXRwdXRBbW91bnRCdWlsZGVyLndpdGhfY29pbl9hbmRfYXNzZXQoXG4gICAgICAgICAgICAgICAgICBtaW5BbW91bnROZWVkZWRGb3JPbmVBc3NldE91dHB1dCxcbiAgICAgICAgICAgICAgICAgIG11bHRpQXNzZXRcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgdHhPdXRwdXQgPSB0eE91dHB1dEFtb3VudEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgICAgICAgICBvdXRwdXRzLmFkZCh0eE91dHB1dCk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIC8vIGZpbmFsbHkgc2VuZCB0aGUgcmVtYWluaW5nIEFEQSBpbiBpdHMgb3duIG91dHB1dFxuICAgICAgICAgICAgICBjb25zdCByZW1haW5pbmdPdXRwdXRBbW91bnQgPSBjaGFuZ2UuY2hlY2tlZF9zdWIobWluQW1vdW50TmVlZGVkRm9yVG90YWxBc3NldE91dHB1dHMpO1xuICAgICAgICAgICAgICBjb25zdCBjaGFuZ2VPdXRwdXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoXG4gICAgICAgICAgICAgICAgY2hhbmdlQWRkcmVzcyxcbiAgICAgICAgICAgICAgICBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcocmVtYWluaW5nT3V0cHV0QW1vdW50KVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBvdXRwdXRzLmFkZChjaGFuZ2VPdXRwdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gdG9rZW5zIHRvIGNvbnNvbGlkYXRlLCB5b3Ugb25seSBoYXZlIDEgb3V0cHV0IHdoaWNoIGlzIEFEQSBhbG9uZVxuICAgICAgICAgICAgY29uc3QgY2hhbmdlT3V0cHV0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25PdXRwdXQubmV3KGNoYW5nZUFkZHJlc3MsIENhcmRhbm9XYXNtLlZhbHVlLm5ldyhjaGFuZ2UpKTtcbiAgICAgICAgICAgIG91dHB1dHMuYWRkKGNoYW5nZU91dHB1dCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElmIHRoaXMgaXNuJ3QgYSBjb25zb2xpZGF0ZSByZXF1ZXN0LCB3aGF0ZXZlciBjaGFuZ2UgdGhhdCBuZWVkcyB0byBiZSBzZW50IGJhY2sgdG8gdGhlIHJvb3RhZGRyZXNzIGlzIGFkZGVkIGFzIGEgc2VwYXJhdGUgb3V0cHV0IGhlcmVcbiAgICAgICAgICBjb25zdCBjaGFuZ2VPdXRwdXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoY2hhbmdlQWRkcmVzcywgQ2FyZGFub1dhc20uVmFsdWUubmV3KGNoYW5nZSkpO1xuICAgICAgICAgIG91dHB1dHMuYWRkKGNoYW5nZU91dHB1dCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgdHhCb2R5ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25Cb2R5Lm5ld190eF9ib2R5KGlucHV0cywgb3V0cHV0cywgdGhpcy5fZmVlKTtcbiAgICAgIHR4Qm9keS5zZXRfdHRsKENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih0aGlzLl90dGwudG9TdHJpbmcoKSkpO1xuICAgICAgY29uc3QgdHhIYXNoID0gQ2FyZGFub1dhc20uaGFzaF90cmFuc2FjdGlvbih0eEJvZHkpO1xuXG4gICAgICAvLyB3ZSBhZGQgd2l0bmVzc2VzIG9uY2Ugc28gdGhhdCB3ZSBjYW4gZ2V0IHRoZSBhcHByb3ByaWF0ZSBhbW91bnQgb2Ygc2lnbmVycyBmb3IgY2FsY3VsYXRpbmcgdGhlIGZlZVxuICAgICAgY29uc3Qgd2l0bmVzc1NldCA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uV2l0bmVzc1NldC5uZXcoKTtcbiAgICAgIGNvbnN0IHZrZXlXaXRuZXNzZXMgPSBDYXJkYW5vV2FzbS5Wa2V5d2l0bmVzc2VzLm5ldygpO1xuICAgICAgdGhpcy5fc2lnbmVycy5mb3JFYWNoKChrZXlQYWlyKSA9PiB7XG4gICAgICAgIGNvbnN0IHBydiA9IGtleVBhaXIuZ2V0S2V5cygpLnBydiBhcyBzdHJpbmc7XG4gICAgICAgIGNvbnN0IHZrZXlXaXRuZXNzID0gQ2FyZGFub1dhc20ubWFrZV92a2V5X3dpdG5lc3MoXG4gICAgICAgICAgdHhIYXNoLFxuICAgICAgICAgIENhcmRhbm9XYXNtLlByaXZhdGVLZXkuZnJvbV9ub3JtYWxfYnl0ZXMoQnVmZmVyLmZyb20ocHJ2LCAnaGV4JykpXG4gICAgICAgICk7XG4gICAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKHZrZXlXaXRuZXNzKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5nZXRBbGxTaWduYXR1cmVzKCkuZm9yRWFjaCgoc2lnbmF0dXJlKSA9PiB7XG4gICAgICAgIGNvbnN0IHZrZXkgPSBDYXJkYW5vV2FzbS5Wa2V5Lm5ldyhcbiAgICAgICAgICBDYXJkYW5vV2FzbS5QdWJsaWNLZXkuZnJvbV9ieXRlcyhCdWZmZXIuZnJvbShzaWduYXR1cmUucHVibGljS2V5LnB1YiwgJ2hleCcpKVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBlZDI1NVNpZyA9IENhcmRhbm9XYXNtLkVkMjU1MTlTaWduYXR1cmUuZnJvbV9ieXRlcyhzaWduYXR1cmUuc2lnbmF0dXJlKTtcbiAgICAgICAgdmtleVdpdG5lc3Nlcy5hZGQoQ2FyZGFub1dhc20uVmtleXdpdG5lc3MubmV3KHZrZXksIGVkMjU1U2lnKSk7XG4gICAgICB9KTtcbiAgICAgIGlmICh2a2V5V2l0bmVzc2VzLmxlbigpID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHBydiA9IENhcmRhbm9XYXNtLlByaXZhdGVLZXkuZ2VuZXJhdGVfZWQyNTUxOSgpO1xuICAgICAgICBjb25zdCB2a2V5V2l0bmVzcyA9IENhcmRhbm9XYXNtLm1ha2VfdmtleV93aXRuZXNzKHR4SGFzaCwgcHJ2KTtcbiAgICAgICAgdmtleVdpdG5lc3Nlcy5hZGQodmtleVdpdG5lc3MpO1xuICAgICAgICBpZiAodGhpcy5fdHlwZSAhPT0gVHJhbnNhY3Rpb25UeXBlLlNlbmQpIHtcbiAgICAgICAgICB2a2V5V2l0bmVzc2VzLmFkZCh2a2V5V2l0bmVzcyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdpdG5lc3NTZXQuc2V0X3ZrZXlzKHZrZXlXaXRuZXNzZXMpO1xuXG4gICAgICAvLyBhZGQgaW4gd2l0aGRyYXdhbCBpZiB0aGlzIGlzIGEgd2l0aGRyYXdhbCB0eFxuICAgICAgaWYgKHRoaXMuX3dpdGhkcmF3YWxzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3Qgd2l0aGRyYXdhbHMgPSBDYXJkYW5vV2FzbS5XaXRoZHJhd2Fscy5uZXcoKTtcbiAgICAgICAgdGhpcy5fd2l0aGRyYXdhbHMuZm9yRWFjaCgod2l0aGRyYXdhbDogV2l0aGRyYXdhbCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJld2FyZEFkZHJlc3MgPSBDYXJkYW5vV2FzbS5SZXdhcmRBZGRyZXNzLmZyb21fYWRkcmVzcyhcbiAgICAgICAgICAgIENhcmRhbm9XYXNtLkFkZHJlc3MuZnJvbV9iZWNoMzIod2l0aGRyYXdhbC5zdGFrZUFkZHJlc3MpXG4gICAgICAgICAgKTtcbiAgICAgICAgICB3aXRoZHJhd2Fscy5pbnNlcnQocmV3YXJkQWRkcmVzcyEsIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih3aXRoZHJhd2FsLnZhbHVlKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHR4Qm9keS5zZXRfd2l0aGRyYXdhbHMod2l0aGRyYXdhbHMpO1xuICAgICAgfVxuXG4gICAgICAvLyBhZGQgaW4gY2VydGlmaWNhdGVzIHRvIGdldCBtb2NrIHNpemVcbiAgICAgIGNvbnN0IGRyYWZ0Q2VydHMgPSBDYXJkYW5vV2FzbS5DZXJ0aWZpY2F0ZXMubmV3KCk7XG4gICAgICBmb3IgKGNvbnN0IGNlcnQgb2YgdGhpcy5fY2VydHMpIHtcbiAgICAgICAgZHJhZnRDZXJ0cy5hZGQoY2VydCk7XG4gICAgICB9XG4gICAgICB0eEJvZHkuc2V0X2NlcnRzKGRyYWZ0Q2VydHMpO1xuXG4gICAgICBjb25zdCB0eERyYWZ0ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb24ubmV3KHR4Qm9keSwgd2l0bmVzc1NldCk7XG4gICAgICBjb25zdCBsaW5lYXJGZWUgPSBDYXJkYW5vV2FzbS5MaW5lYXJGZWUubmV3KFxuICAgICAgICBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIoJzQ0JyksXG4gICAgICAgIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cignMTU1MzgxJylcbiAgICAgICk7XG5cbiAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgZmVlIGJhc2VkIG9mZiBvdXIgZHVtbXkgdHJhbnNhY3Rpb25cbiAgICAgIGNvbnN0IGZlZSA9IENhcmRhbm9XYXNtLm1pbl9mZWUodHhEcmFmdCwgbGluZWFyRmVlKS5jaGVja2VkX2FkZChCaWdOdW0uZnJvbV9zdHIoJzQ0MCcpKTtcbiAgICAgIHRoaXMuX2ZlZSA9IGZlZTtcbiAgICB9XG4gICAgdGhpcy5fdHJhbnNhY3Rpb24uZmVlKHRoaXMuX2ZlZS50b19zdHIoKSk7XG4gICAgLy8gbm93IGNhbGN1bGF0ZSB0aGUgY2hhbmdlIGJhc2VkIG9mZiBvZiA8dXR4b0JhbGFuY2U+IC0gPGZlZT4gLSA8YW1vdW50VG9TZW5kPlxuICAgIC8vIHJlc2V0IHRoZSBvdXRwdXRzIGNvbGxlY3Rpb24gYmVjYXVzZSBub3cgb3VyIGxhc3Qgb3V0cHV0IGhhcyBjaGFuZ2VkXG4gICAgb3V0cHV0cyA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0cy5uZXcoKTtcbiAgICB0aGlzLl90cmFuc2FjdGlvbk91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiB7XG4gICAgICBjb25zdCBtdWx0aUFzc2V0cyA9IG91dHB1dC5tdWx0aUFzc2V0cyBhcyBDYXJkYW5vV2FzbS5NdWx0aUFzc2V0O1xuICAgICAgaWYgKG11bHRpQXNzZXRzKSB7XG4gICAgICAgIGNvbnN0IHBvbGljeUlkID0gbXVsdGlBc3NldHMua2V5cygpLmdldCgwKTtcbiAgICAgICAgY29uc3QgYXNzZXRzID0gbXVsdGlBc3NldHMuZ2V0KHBvbGljeUlkKTtcbiAgICAgICAgY29uc3QgYXNzZXROYW1lID0gYXNzZXRzIS5rZXlzKCkuZ2V0KDApO1xuICAgICAgICBjb25zdCBxdWFudGl0eSA9IGFzc2V0cyEuZ2V0KGFzc2V0TmFtZSk7XG4gICAgICAgIGxldCB0eE91dHB1dEJ1aWxkZXIgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dEJ1aWxkZXIubmV3KCk7XG4gICAgICAgIGNvbnN0IG91dHB1dEFtb3VudCA9IENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihvdXRwdXQuYW1vdW50KTtcbiAgICAgICAgY29uc3QgdG9BZGRyZXNzID0gdXRpbC5nZXRXYWxsZXRBZGRyZXNzKG91dHB1dC5hZGRyZXNzKTtcbiAgICAgICAgdHhPdXRwdXRCdWlsZGVyID0gdHhPdXRwdXRCdWlsZGVyLndpdGhfYWRkcmVzcyh0b0FkZHJlc3MpO1xuICAgICAgICBsZXQgdHhPdXRwdXRBbW91bnRCdWlsZGVyID0gdHhPdXRwdXRCdWlsZGVyLm5leHQoKTtcbiAgICAgICAgY29uc3QgbXVsdGlBc3NldCA9IENhcmRhbm9XYXNtLk11bHRpQXNzZXQubmV3KCk7XG4gICAgICAgIGNvbnN0IGFzc2V0ID0gQ2FyZGFub1dhc20uQXNzZXRzLm5ldygpO1xuICAgICAgICBhc3NldC5pbnNlcnQoYXNzZXROYW1lLCBxdWFudGl0eSEpO1xuICAgICAgICBtdWx0aUFzc2V0Lmluc2VydChwb2xpY3lJZCwgYXNzZXQpO1xuICAgICAgICB0eE91dHB1dEFtb3VudEJ1aWxkZXIgPSB0eE91dHB1dEFtb3VudEJ1aWxkZXIud2l0aF9jb2luX2FuZF9hc3NldChvdXRwdXRBbW91bnQsIG11bHRpQXNzZXQpO1xuICAgICAgICBjb25zdCB0eE91dHB1dCA9IHR4T3V0cHV0QW1vdW50QnVpbGRlci5idWlsZCgpO1xuICAgICAgICBvdXRwdXRzLmFkZCh0eE91dHB1dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRwdXRzLmFkZChcbiAgICAgICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoXG4gICAgICAgICAgICB1dGlsLmdldFdhbGxldEFkZHJlc3Mob3V0cHV0LmFkZHJlc3MpLFxuICAgICAgICAgICAgQ2FyZGFub1dhc20uVmFsdWUubmV3KENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihvdXRwdXQuYW1vdW50KSlcbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKHRoaXMuX2NoYW5nZUFkZHJlc3MgJiYgdGhpcy5fc2VuZGVyQmFsYW5jZSkge1xuICAgICAgY29uc3QgY2hhbmdlQWRkcmVzcyA9IHV0aWwuZ2V0V2FsbGV0QWRkcmVzcyh0aGlzLl9jaGFuZ2VBZGRyZXNzKTtcbiAgICAgIGNvbnN0IHV0eG9CYWxhbmNlID0gQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX3NlbmRlckJhbGFuY2UpO1xuXG4gICAgICBjb25zdCBhZGp1c3RtZW50ID0gQmlnTnVtLmZyb21fc3RyKCcyMDAwMDAwJyk7XG4gICAgICBsZXQgY2hhbmdlID0gdXR4b0JhbGFuY2UuY2hlY2tlZF9zdWIodGhpcy5fZmVlKS5jaGVja2VkX3N1Yih0b3RhbEFtb3VudFRvU2VuZCk7XG4gICAgICBpZiAodGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZSkge1xuICAgICAgICBjaGFuZ2UgPSBjaGFuZ2UuY2hlY2tlZF9zdWIoYWRqdXN0bWVudCk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX3R5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nRGVhY3RpdmF0ZSkge1xuICAgICAgICBjaGFuZ2UgPSBjaGFuZ2UuY2hlY2tlZF9hZGQoYWRqdXN0bWVudCk7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX3R5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXcgfHwgdGhpcy5fdHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdDbGFpbSkge1xuICAgICAgICB0aGlzLl93aXRoZHJhd2Fscy5mb3JFYWNoKCh3aXRoZHJhd2FsOiBXaXRoZHJhd2FsKSA9PiB7XG4gICAgICAgICAgY2hhbmdlID0gY2hhbmdlLmNoZWNrZWRfYWRkKENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih3aXRoZHJhd2FsLnZhbHVlKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiB0b3RhbEFtb3VudFRvU2VuZCBpcyAwLCBpdHMgY29uc29saWRhdGlvblxuICAgICAgaWYgKHRvdGFsQW1vdW50VG9TZW5kLnRvX3N0cigpID09ICcwJykge1xuICAgICAgICAvLyBzdXBwb3J0IGZvciBtdWx0aS1hc3NldCBjb25zb2xpZGF0aW9uXG4gICAgICAgIGlmICh0aGlzLl9tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29uc3QgdG90YWxOdW1iZXJPZkFzc2V0cyA9IENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cih0aGlzLl9tdWx0aUFzc2V0cy5sZW5ndGgudG9TdHJpbmcoKSk7XG4gICAgICAgICAgY29uc3QgbWluQW1vdW50TmVlZGVkRm9yT25lQXNzZXRPdXRwdXQgPSBDYXJkYW5vV2FzbS5CaWdOdW0uZnJvbV9zdHIoJzE1MDAwMDAnKTtcbiAgICAgICAgICBjb25zdCBtaW5BbW91bnROZWVkZWRGb3JUb3RhbEFzc2V0T3V0cHV0cyA9IG1pbkFtb3VudE5lZWRlZEZvck9uZUFzc2V0T3V0cHV0LmNoZWNrZWRfbXVsKHRvdGFsTnVtYmVyT2ZBc3NldHMpO1xuXG4gICAgICAgICAgaWYgKCFjaGFuZ2UubGVzc190aGFuKG1pbkFtb3VudE5lZWRlZEZvclRvdGFsQXNzZXRPdXRwdXRzKSkge1xuICAgICAgICAgICAgdGhpcy5fbXVsdGlBc3NldHMuZm9yRWFjaCgoYXNzZXQpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHR4T3V0cHV0QnVpbGRlciA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0QnVpbGRlci5uZXcoKTtcbiAgICAgICAgICAgICAgLy8gY2hhbmdlQWRkcmVzcyBpcyB0aGUgcm9vdCBhZGRyZXNzLCB3aGljaCBpcyB3aGVyZSB3ZSB3YW50IHRoZSB0b2tlbnMgYXNzZXRzIHRvIGJlIHNlbnQgdG9cbiAgICAgICAgICAgICAgY29uc3QgdG9BZGRyZXNzID0gdXRpbC5nZXRXYWxsZXRBZGRyZXNzKHRoaXMuX2NoYW5nZUFkZHJlc3MpO1xuICAgICAgICAgICAgICB0eE91dHB1dEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIud2l0aF9hZGRyZXNzKHRvQWRkcmVzcyk7XG4gICAgICAgICAgICAgIGxldCB0eE91dHB1dEFtb3VudEJ1aWxkZXIgPSB0eE91dHB1dEJ1aWxkZXIubmV4dCgpO1xuICAgICAgICAgICAgICBjb25zdCBhc3NldE5hbWUgPSBDYXJkYW5vV2FzbS5Bc3NldE5hbWUubmV3KEJ1ZmZlci5mcm9tKGFzc2V0LmFzc2V0X25hbWUsICdoZXgnKSk7XG4gICAgICAgICAgICAgIGNvbnN0IHBvbGljeUlkID0gQ2FyZGFub1dhc20uU2NyaXB0SGFzaC5mcm9tX2J5dGVzKEJ1ZmZlci5mcm9tKGFzc2V0LnBvbGljeV9pZCwgJ2hleCcpKTtcbiAgICAgICAgICAgICAgY29uc3QgbXVsdGlBc3NldCA9IENhcmRhbm9XYXNtLk11bHRpQXNzZXQubmV3KCk7XG4gICAgICAgICAgICAgIGNvbnN0IGFzc2V0cyA9IENhcmRhbm9XYXNtLkFzc2V0cy5uZXcoKTtcbiAgICAgICAgICAgICAgYXNzZXRzLmluc2VydChhc3NldE5hbWUsIENhcmRhbm9XYXNtLkJpZ051bS5mcm9tX3N0cihhc3NldC5xdWFudGl0eSkpO1xuICAgICAgICAgICAgICBtdWx0aUFzc2V0Lmluc2VydChwb2xpY3lJZCwgYXNzZXRzKTtcblxuICAgICAgICAgICAgICB0eE91dHB1dEFtb3VudEJ1aWxkZXIgPSB0eE91dHB1dEFtb3VudEJ1aWxkZXIud2l0aF9jb2luX2FuZF9hc3NldChcbiAgICAgICAgICAgICAgICBtaW5BbW91bnROZWVkZWRGb3JPbmVBc3NldE91dHB1dCxcbiAgICAgICAgICAgICAgICBtdWx0aUFzc2V0XG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgY29uc3QgdHhPdXRwdXQgPSB0eE91dHB1dEFtb3VudEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgICAgICAgICAgb3V0cHV0cy5hZGQodHhPdXRwdXQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIGZpbmFsbHkgc2VuZCB0aGUgcmVtYWluaW5nIEFEQSBpbiBpdHMgb3duIG91dHB1dFxuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nT3V0cHV0QW1vdW50ID0gY2hhbmdlLmNoZWNrZWRfc3ViKG1pbkFtb3VudE5lZWRlZEZvclRvdGFsQXNzZXRPdXRwdXRzKTtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZU91dHB1dCA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0Lm5ldyhcbiAgICAgICAgICAgICAgY2hhbmdlQWRkcmVzcyxcbiAgICAgICAgICAgICAgQ2FyZGFub1dhc20uVmFsdWUubmV3KHJlbWFpbmluZ091dHB1dEFtb3VudClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBvdXRwdXRzLmFkZChjaGFuZ2VPdXRwdXQpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICAgICAgICAnSW5zdWZmaWNpZW50IGZ1bmRzOiBuZWVkIGEgbWluaW11bSBvZiAxLjUgQURBIHBlciBvdXRwdXQgdG8gY29uc3RydWN0IHRva2VuIGNvbnNvbGlkYXRpb24nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gdG9rZW5zIHRvIGNvbnNvbGlkYXRlLCB5b3Ugb25seSBoYXZlIDEgb3V0cHV0IHdoaWNoIGlzIEFEQSBhbG9uZVxuICAgICAgICAgIGNvbnN0IGNoYW5nZU91dHB1dCA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uT3V0cHV0Lm5ldyhjaGFuZ2VBZGRyZXNzLCBDYXJkYW5vV2FzbS5WYWx1ZS5uZXcoY2hhbmdlKSk7XG4gICAgICAgICAgb3V0cHV0cy5hZGQoY2hhbmdlT3V0cHV0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgdGhpcyBpc24ndCBhIGNvbnNvbGlkYXRlIHJlcXVlc3QsIHdoYXRldmVyIGNoYW5nZSB0aGF0IG5lZWRzIHRvIGJlIHNlbnQgYmFjayB0byB0aGUgcm9vdGFkZHJlc3MgaXMgYWRkZWQgYXMgYSBzZXBhcmF0ZSBvdXRwdXQgaGVyZVxuICAgICAgICBjb25zdCBjaGFuZ2VPdXRwdXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbk91dHB1dC5uZXcoY2hhbmdlQWRkcmVzcywgQ2FyZGFub1dhc20uVmFsdWUubmV3KGNoYW5nZSkpO1xuICAgICAgICBvdXRwdXRzLmFkZChjaGFuZ2VPdXRwdXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHR4UmF3ID0gQ2FyZGFub1dhc20uVHJhbnNhY3Rpb25Cb2R5Lm5ld190eF9ib2R5KGlucHV0cywgb3V0cHV0cywgdGhpcy5fZmVlKTtcblxuICAgIGNvbnN0IGNlcnRzID0gQ2FyZGFub1dhc20uQ2VydGlmaWNhdGVzLm5ldygpO1xuICAgIGZvciAoY29uc3QgY2VydCBvZiB0aGlzLl9jZXJ0cykge1xuICAgICAgY2VydHMuYWRkKGNlcnQpO1xuICAgIH1cbiAgICB0eFJhdy5zZXRfY2VydHMoY2VydHMpO1xuXG4gICAgLy8gYWRkIGluIHdpdGhkcmF3YWwgaWYgdGhpcyBpcyBhIHdpdGhkcmF3YWwgdHhcbiAgICBpZiAodGhpcy5fd2l0aGRyYXdhbHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgd2l0aGRyYXdhbHMgPSBDYXJkYW5vV2FzbS5XaXRoZHJhd2Fscy5uZXcoKTtcbiAgICAgIHRoaXMuX3dpdGhkcmF3YWxzLmZvckVhY2goKHdpdGhkcmF3YWw6IFdpdGhkcmF3YWwpID0+IHtcbiAgICAgICAgY29uc3QgcmV3YXJkQWRkcmVzcyA9IENhcmRhbm9XYXNtLlJld2FyZEFkZHJlc3MuZnJvbV9hZGRyZXNzKFxuICAgICAgICAgIENhcmRhbm9XYXNtLkFkZHJlc3MuZnJvbV9iZWNoMzIod2l0aGRyYXdhbC5zdGFrZUFkZHJlc3MpXG4gICAgICAgICk7XG4gICAgICAgIHdpdGhkcmF3YWxzLmluc2VydChyZXdhcmRBZGRyZXNzISwgQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHdpdGhkcmF3YWwudmFsdWUpKTtcbiAgICAgIH0pO1xuXG4gICAgICB0eFJhdy5zZXRfd2l0aGRyYXdhbHMod2l0aGRyYXdhbHMpO1xuICAgIH1cblxuICAgIHR4UmF3LnNldF90dGwoQ2FyZGFub1dhc20uQmlnTnVtLmZyb21fc3RyKHRoaXMuX3R0bC50b1N0cmluZygpKSk7XG4gICAgY29uc3QgdHhSYXdIYXNoID0gQ2FyZGFub1dhc20uaGFzaF90cmFuc2FjdGlvbih0eFJhdyk7XG5cbiAgICAvLyBub3cgYWRkIHRoZSB3aXRuZXNzZXMgYWdhaW4gdGhpcyB0aW1lIGZvciByZWFsLiBXZSBuZWVkIHRvIGRvIHRoaXMgYWdhaW5cbiAgICAvLyBiZWNhdXNlIG5vdyB0aGF0IHdlJ3ZlIGFkZGVkIG91ciByZWFsIGZlZSBhbmQgY2hhbmdlIG91dHB1dCwgd2UgaGF2ZSBhIGRpZmZlcmVuY2UgdHJhbnNhY3Rpb24gaGFzaFxuICAgIGNvbnN0IHdpdG5lc3NTZXQgPSBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbldpdG5lc3NTZXQubmV3KCk7XG4gICAgY29uc3QgdmtleVdpdG5lc3NlcyA9IENhcmRhbm9XYXNtLlZrZXl3aXRuZXNzZXMubmV3KCk7XG4gICAgdGhpcy5fc2lnbmVycy5mb3JFYWNoKChrZXlQYWlyKSA9PiB7XG4gICAgICBjb25zdCBwcnYgPSBrZXlQYWlyLmdldEtleXMoKS5wcnYgYXMgc3RyaW5nO1xuICAgICAgY29uc3QgdmtleVdpdG5lc3MgPSBDYXJkYW5vV2FzbS5tYWtlX3ZrZXlfd2l0bmVzcyhcbiAgICAgICAgdHhSYXdIYXNoLFxuICAgICAgICBDYXJkYW5vV2FzbS5Qcml2YXRlS2V5LmZyb21fbm9ybWFsX2J5dGVzKEJ1ZmZlci5mcm9tKHBydiwgJ2hleCcpKVxuICAgICAgKTtcbiAgICAgIHZrZXlXaXRuZXNzZXMuYWRkKHZrZXlXaXRuZXNzKTtcbiAgICB9KTtcblxuICAgIC8vIENsZWFyIHRoZSBjb3NtZXRpYyBzaWduYXR1cmUgYXJyYXkgaW4gbmF0aXZlIHR4biB3cmFwcGVyIHRvIHByZXZlbnQgZHVwbGljYXRlIHdoZW4gYnVpbGRlciBpcyBpbml0ZWQgZnJvbSBhIHBhcnRpYWxseSB3aXRuZXNzZWQgdHhuXG4gICAgdGhpcy5fdHJhbnNhY3Rpb24uc2lnbmF0dXJlLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5nZXRBbGxTaWduYXR1cmVzKCkuZm9yRWFjaCgoc2lnbmF0dXJlKSA9PiB7XG4gICAgICBjb25zdCB2a2V5ID0gQ2FyZGFub1dhc20uVmtleS5uZXcoQ2FyZGFub1dhc20uUHVibGljS2V5LmZyb21fYnl0ZXMoQnVmZmVyLmZyb20oc2lnbmF0dXJlLnB1YmxpY0tleS5wdWIsICdoZXgnKSkpO1xuICAgICAgY29uc3QgZWQyNTVTaWcgPSBDYXJkYW5vV2FzbS5FZDI1NTE5U2lnbmF0dXJlLmZyb21fYnl0ZXMoc2lnbmF0dXJlLnNpZ25hdHVyZSk7XG4gICAgICB2a2V5V2l0bmVzc2VzLmFkZChDYXJkYW5vV2FzbS5Wa2V5d2l0bmVzcy5uZXcodmtleSwgZWQyNTVTaWcpKTtcbiAgICAgIHRoaXMuX3RyYW5zYWN0aW9uLnNpZ25hdHVyZS5wdXNoKHNpZ25hdHVyZS5zaWduYXR1cmUudG9TdHJpbmcoJ2hleCcpKTtcbiAgICB9KTtcbiAgICB3aXRuZXNzU2V0LnNldF92a2V5cyh2a2V5V2l0bmVzc2VzKTtcbiAgICB0aGlzLl90cmFuc2FjdGlvbi50cmFuc2FjdGlvbiA9IENhcmRhbm9XYXNtLlRyYW5zYWN0aW9uLm5ldyh0eFJhdywgd2l0bmVzc1NldCk7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIHNpZ25JbXBsZW1lbnRhdGlvbihrZXk6IEJhc2VLZXkpOiBUcmFuc2FjdGlvbiB7XG4gICAgdGhpcy5fc2lnbmVycy5wdXNoKG5ldyBLZXlQYWlyKHsgcHJ2OiBrZXkua2V5IH0pKTtcbiAgICByZXR1cm4gdGhpcy5fdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGdldCB0cmFuc2FjdGlvbigpOiBUcmFuc2FjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHByb3RlY3RlZCBzZXQgdHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKSB7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZUFkZHJlc3MoYWRkcmVzczogQmFzZUFkZHJlc3MsIGFkZHJlc3NGb3JtYXQ/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXV0aWwuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcy5hZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IFV0aWxzRXJyb3IoJ2ludmFsaWQgYWRkcmVzcyAnICsgYWRkcmVzcy5hZGRyZXNzKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVLZXkoa2V5OiBCYXNlS2V5KTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIG5ldyBLZXlQYWlyKHsgcHJ2OiBrZXkua2V5IH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgS2V5IHZhbGlkYXRpb24gZmFpbGVkYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlUmF3VHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IGFueSk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBDYXJkYW5vV2FzbS5UcmFuc2FjdGlvbi5mcm9tX2J5dGVzKHJhd1RyYW5zYWN0aW9uKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ2ludmFsaWQgcmF3IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlVHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgaWYgKCF0cmFuc2FjdGlvbi50cmFuc2FjdGlvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZVZhbHVlKHZhbHVlOiBCaWdOdW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUuaXNMZXNzVGhhbigwKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVmFsdWUgY2Fubm90IGJlIGxlc3MgdGhhbiB6ZXJvJyk7XG4gICAgfVxuICB9XG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhZGRTaWduYXR1cmUocHVibGljS2V5OiBCYXNlUHVibGljS2V5LCBzaWduYXR1cmU6IEJ1ZmZlcik6IHZvaWQge1xuICAgIHRoaXMuX3NpZ25hdHVyZXMucHVzaCh7IHB1YmxpY0tleSwgc2lnbmF0dXJlIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxTaWduYXR1cmVzKCk6IFNpZ25hdHVyZVtdIHtcbiAgICByZXR1cm4gdGhpcy5faW5pdFNpZ25hdHVyZXMuY29uY2F0KHRoaXMuX3NpZ25hdHVyZXMpO1xuICB9XG59XG4iXX0=