@bitgo-beta/abstract-eth 1.0.2-beta.48 → 1.0.2-beta.481

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 (57) hide show
  1. package/CHANGELOG.md +1088 -0
  2. package/dist/src/abstractEthLikeCoin.d.ts +7 -5
  3. package/dist/src/abstractEthLikeCoin.d.ts.map +1 -1
  4. package/dist/src/abstractEthLikeCoin.js +10 -10
  5. package/dist/src/abstractEthLikeNewCoins.d.ts +635 -0
  6. package/dist/src/abstractEthLikeNewCoins.d.ts.map +1 -0
  7. package/dist/src/abstractEthLikeNewCoins.js +1839 -0
  8. package/dist/src/ethLikeToken.d.ts +15 -4
  9. package/dist/src/ethLikeToken.d.ts.map +1 -1
  10. package/dist/src/ethLikeToken.js +61 -7
  11. package/dist/src/index.d.ts +2 -0
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/index.js +3 -1
  14. package/dist/src/lib/contractCall.d.ts +8 -0
  15. package/dist/src/lib/contractCall.d.ts.map +1 -0
  16. package/dist/src/lib/contractCall.js +17 -0
  17. package/dist/src/lib/iface.d.ts +130 -0
  18. package/dist/src/lib/iface.d.ts.map +1 -0
  19. package/dist/src/lib/iface.js +8 -0
  20. package/dist/src/lib/index.d.ts +15 -0
  21. package/dist/src/lib/index.d.ts.map +1 -0
  22. package/dist/src/lib/index.js +42 -0
  23. package/dist/src/lib/keyPair.d.ts +26 -0
  24. package/dist/src/lib/keyPair.d.ts.map +1 -0
  25. package/dist/src/lib/keyPair.js +66 -0
  26. package/dist/src/lib/transaction.d.ts +64 -0
  27. package/dist/src/lib/transaction.d.ts.map +1 -0
  28. package/dist/src/lib/transaction.js +137 -0
  29. package/dist/src/lib/transactionBuilder.d.ts +232 -0
  30. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  31. package/dist/src/lib/transactionBuilder.js +689 -0
  32. package/dist/src/lib/transferBuilder.d.ts +66 -0
  33. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  34. package/dist/src/lib/transferBuilder.js +224 -0
  35. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts +52 -0
  36. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts.map +1 -0
  37. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.js +114 -0
  38. package/dist/src/lib/transferBuilders/index.d.ts +4 -0
  39. package/dist/src/lib/transferBuilders/index.d.ts.map +1 -0
  40. package/dist/src/lib/transferBuilders/index.js +16 -0
  41. package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts +16 -0
  42. package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts.map +1 -0
  43. package/dist/src/lib/transferBuilders/transferBuilderERC1155.js +93 -0
  44. package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts +15 -0
  45. package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts.map +1 -0
  46. package/dist/src/lib/transferBuilders/transferBuilderERC721.js +78 -0
  47. package/dist/src/lib/types.d.ts +39 -0
  48. package/dist/src/lib/types.d.ts.map +1 -0
  49. package/dist/src/lib/types.js +137 -0
  50. package/dist/src/lib/utils.d.ts +228 -0
  51. package/dist/src/lib/utils.d.ts.map +1 -0
  52. package/dist/src/lib/utils.js +577 -0
  53. package/dist/src/lib/walletUtil.d.ts +26 -0
  54. package/dist/src/lib/walletUtil.d.ts.map +1 -0
  55. package/dist/src/lib/walletUtil.js +29 -0
  56. package/dist/tsconfig.tsbuildinfo +1 -7896
  57. package/package.json +23 -9
@@ -0,0 +1,689 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.TransactionBuilder = void 0;
26
+ const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
27
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
28
+ const ethUtil = __importStar(require("ethereumjs-util"));
29
+ const tx_1 = require("@ethereumjs/tx");
30
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
31
+ const keyPair_1 = require("./keyPair");
32
+ const iface_1 = require("./iface");
33
+ const utils_1 = require("./utils");
34
+ const walletUtil_1 = require("./walletUtil");
35
+ const transaction_1 = require("./transaction");
36
+ const DEFAULT_M = 3;
37
+ /**
38
+ * EthereumLike transaction builder.
39
+ */
40
+ class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
41
+ /**
42
+ * Public constructor.
43
+ *
44
+ * @param _coinConfig
45
+ */
46
+ constructor(_coinConfig) {
47
+ super(_coinConfig);
48
+ this._common = utils_1.getCommon(this._coinConfig.network);
49
+ this._type = sdk_core_1.TransactionType.Send;
50
+ this._counter = 0;
51
+ this._value = '0';
52
+ this._walletOwnerAddresses = [];
53
+ this._forwarderVersion = 0;
54
+ this._walletVersion = 0;
55
+ this.transaction = new transaction_1.Transaction(this._coinConfig, this._common);
56
+ this._walletSimpleByteCode = '';
57
+ }
58
+ /** @inheritdoc */
59
+ async buildImplementation() {
60
+ const transactionData = this.getTransactionData();
61
+ if (this._txSignature) {
62
+ Object.assign(transactionData, this._txSignature);
63
+ }
64
+ this.transaction.setTransactionType(this._type);
65
+ transactionData.from = this._sourceKeyPair ? this._sourceKeyPair.getAddress() : undefined;
66
+ this.transaction.setTransactionData(transactionData);
67
+ // Build and sign a new transaction based on the latest changes
68
+ if (this._sourceKeyPair && this._sourceKeyPair.getKeys().prv) {
69
+ await this.transaction.sign(this._sourceKeyPair);
70
+ }
71
+ return this.transaction;
72
+ }
73
+ getTransactionData() {
74
+ switch (this._type) {
75
+ case sdk_core_1.TransactionType.WalletInitialization:
76
+ return this.buildWalletInitializationTransaction(this._walletVersion);
77
+ case sdk_core_1.TransactionType.RecoveryWalletDeployment:
78
+ return this.buildBase(this._data);
79
+ case sdk_core_1.TransactionType.Send:
80
+ case sdk_core_1.TransactionType.SendERC721:
81
+ case sdk_core_1.TransactionType.SendERC1155:
82
+ return this.buildSendTransaction();
83
+ case sdk_core_1.TransactionType.AddressInitialization:
84
+ return this.buildAddressInitializationTransaction();
85
+ case sdk_core_1.TransactionType.FlushTokens:
86
+ return this.buildFlushTokensTransaction();
87
+ case sdk_core_1.TransactionType.FlushCoins:
88
+ return this.buildFlushCoinsTransaction();
89
+ case sdk_core_1.TransactionType.SingleSigSend:
90
+ return this.buildBase('0x');
91
+ case sdk_core_1.TransactionType.ContractCall:
92
+ return this.buildGenericContractCallTransaction();
93
+ default:
94
+ throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
95
+ }
96
+ }
97
+ /** @inheritdoc */
98
+ fromImplementation(rawTransaction) {
99
+ let tx;
100
+ if (/^0x?[0-9a-f]{1,}$/.test(rawTransaction.toLowerCase())) {
101
+ tx = transaction_1.Transaction.fromSerialized(this._coinConfig, this._common, rawTransaction);
102
+ this.loadBuilderInput(tx.toJson());
103
+ }
104
+ else {
105
+ const txData = JSON.parse(rawTransaction);
106
+ tx = new transaction_1.Transaction(this._coinConfig, txData);
107
+ }
108
+ return tx;
109
+ }
110
+ /**
111
+ * Load the builder data using the deserialized transaction
112
+ *
113
+ * @param {TxData} transactionJson the deserialized transaction json
114
+ */
115
+ loadBuilderInput(transactionJson) {
116
+ const decodedType = utils_1.classifyTransaction(transactionJson.data);
117
+ this.type(decodedType);
118
+ this.counter(transactionJson.nonce);
119
+ this.value(transactionJson.value);
120
+ if (transactionJson._type === iface_1.ETHTransactionType.LEGACY) {
121
+ this.fee({
122
+ fee: transactionJson.gasPrice,
123
+ gasPrice: transactionJson.gasPrice,
124
+ gasLimit: transactionJson.gasLimit,
125
+ });
126
+ }
127
+ else {
128
+ this.fee({
129
+ gasLimit: transactionJson.gasLimit,
130
+ fee: transactionJson.maxFeePerGas,
131
+ eip1559: {
132
+ maxFeePerGas: transactionJson.maxFeePerGas,
133
+ maxPriorityFeePerGas: transactionJson.maxPriorityFeePerGas,
134
+ },
135
+ });
136
+ }
137
+ if (utils_1.hasSignature(transactionJson)) {
138
+ this._txSignature = { v: transactionJson.v, r: transactionJson.r, s: transactionJson.s };
139
+ }
140
+ this.setTransactionTypeFields(decodedType, transactionJson);
141
+ }
142
+ setTransactionTypeFields(decodedType, transactionJson) {
143
+ switch (decodedType) {
144
+ case sdk_core_1.TransactionType.WalletInitialization:
145
+ const { owners, salt } = utils_1.decodeWalletCreationData(transactionJson.data);
146
+ owners.forEach((element) => {
147
+ this.owner(element);
148
+ });
149
+ if (salt) {
150
+ this.salt(salt);
151
+ this.walletVersion(1);
152
+ this.setContract(transactionJson.to);
153
+ }
154
+ break;
155
+ case sdk_core_1.TransactionType.RecoveryWalletDeployment:
156
+ this.data(transactionJson.data);
157
+ break;
158
+ case sdk_core_1.TransactionType.FlushTokens:
159
+ this.setContract(transactionJson.to);
160
+ const { forwarderAddress, tokenAddress } = utils_1.decodeFlushTokensData(transactionJson.data);
161
+ this.forwarderAddress(forwarderAddress);
162
+ this.tokenAddress(tokenAddress);
163
+ break;
164
+ case sdk_core_1.TransactionType.FlushCoins:
165
+ this.setContract(transactionJson.to);
166
+ break;
167
+ case sdk_core_1.TransactionType.Send:
168
+ case sdk_core_1.TransactionType.SendERC1155:
169
+ case sdk_core_1.TransactionType.SendERC721:
170
+ this.setContract(transactionJson.to);
171
+ this._transfer = this.transfer(transactionJson.data);
172
+ break;
173
+ case sdk_core_1.TransactionType.AddressInitialization:
174
+ this.setContract(transactionJson.to);
175
+ const { baseAddress, addressCreationSalt } = utils_1.decodeForwarderCreationData(transactionJson.data);
176
+ if (baseAddress && addressCreationSalt) {
177
+ this.forwarderVersion(1);
178
+ this.baseAddress(baseAddress);
179
+ this.salt(addressCreationSalt);
180
+ const forwarderImplementationAddress = this._coinConfig.network
181
+ .forwarderImplementationAddress;
182
+ if (forwarderImplementationAddress) {
183
+ this.initCode(forwarderImplementationAddress);
184
+ }
185
+ }
186
+ break;
187
+ case sdk_core_1.TransactionType.SingleSigSend:
188
+ this.setContract(transactionJson.to);
189
+ break;
190
+ case sdk_core_1.TransactionType.ContractCall:
191
+ this.setContract(transactionJson.to);
192
+ this.data(transactionJson.data);
193
+ break;
194
+ default:
195
+ throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
196
+ // TODO: Add other cases of deserialization
197
+ }
198
+ }
199
+ /** @inheritdoc */
200
+ signImplementation(key) {
201
+ const signer = new keyPair_1.KeyPair({ prv: key.key });
202
+ if (this._type === sdk_core_1.TransactionType.WalletInitialization && this._walletOwnerAddresses.length === 0) {
203
+ throw new sdk_core_1.SigningError('Cannot sign an wallet initialization transaction without owners');
204
+ }
205
+ if (this._sourceKeyPair) {
206
+ throw new sdk_core_1.SigningError('Cannot sign multiple times a non send-type transaction');
207
+ }
208
+ // Signing the transaction is an async operation, so save the source and leave the actual
209
+ // signing for the build step
210
+ this._sourceKeyPair = signer;
211
+ return this.transaction;
212
+ }
213
+ /** @inheritdoc */
214
+ validateAddress(address) {
215
+ if (!utils_1.isValidEthAddress(address.address)) {
216
+ throw new sdk_core_1.BuildTransactionError('Invalid address ' + address.address);
217
+ }
218
+ }
219
+ /** @inheritdoc */
220
+ validateKey(key) {
221
+ if (!(sdk_core_1.isValidXprv(key.key) || sdk_core_1.isValidPrv(key.key))) {
222
+ throw new sdk_core_1.BuildTransactionError('Invalid key');
223
+ }
224
+ }
225
+ /**
226
+ * Validate the raw transaction is either a JSON or
227
+ * a hex encoded transaction
228
+ *
229
+ * @param {any} rawTransaction The raw transaction to be validated
230
+ */
231
+ validateRawTransaction(rawTransaction) {
232
+ if (!rawTransaction) {
233
+ throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
234
+ }
235
+ if (typeof rawTransaction === 'string') {
236
+ if (/^0x?[0-9a-f]{1,}$/.test(rawTransaction.toLowerCase())) {
237
+ const txBytes = ethUtil.toBuffer(ethUtil.addHexPrefix(rawTransaction.toLowerCase()));
238
+ if (!this.isEip1559Txn(txBytes) && !this.isRLPDecodable(txBytes)) {
239
+ throw new sdk_core_1.ParseTransactionError('There was error in decoding the hex string');
240
+ }
241
+ }
242
+ else {
243
+ try {
244
+ JSON.parse(rawTransaction);
245
+ }
246
+ catch (e) {
247
+ throw new sdk_core_1.ParseTransactionError('There was error in parsing the JSON string');
248
+ }
249
+ }
250
+ }
251
+ else {
252
+ throw new sdk_core_1.InvalidTransactionError('Transaction is not a hex string or stringified json');
253
+ }
254
+ }
255
+ isEip1559Txn(txn) {
256
+ try {
257
+ tx_1.FeeMarketEIP1559Transaction.fromSerializedTx(txn);
258
+ return true;
259
+ }
260
+ catch (_) {
261
+ return false;
262
+ }
263
+ }
264
+ isRLPDecodable(bytes) {
265
+ try {
266
+ ethUtil.rlp.decode(bytes);
267
+ return true;
268
+ }
269
+ catch (_) {
270
+ return false;
271
+ }
272
+ }
273
+ validateBaseTransactionFields() {
274
+ if (this._fee === undefined || (!this._fee.fee && !this._fee.gasPrice && !this._fee.eip1559)) {
275
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing fee');
276
+ }
277
+ if (this._common === undefined) {
278
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: network common');
279
+ }
280
+ if (this._counter === undefined) {
281
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing address counter');
282
+ }
283
+ }
284
+ /** @inheritdoc */
285
+ validateTransaction(transaction) {
286
+ this.validateBaseTransactionFields();
287
+ switch (this._type) {
288
+ case sdk_core_1.TransactionType.WalletInitialization:
289
+ this.validateWalletInitializationFields();
290
+ break;
291
+ case sdk_core_1.TransactionType.RecoveryWalletDeployment:
292
+ this.validateDataField();
293
+ break;
294
+ case sdk_core_1.TransactionType.Send:
295
+ case sdk_core_1.TransactionType.SendERC721:
296
+ case sdk_core_1.TransactionType.SendERC1155:
297
+ this.validateContractAddress();
298
+ break;
299
+ case sdk_core_1.TransactionType.AddressInitialization:
300
+ this.validateContractAddress();
301
+ break;
302
+ case sdk_core_1.TransactionType.FlushCoins:
303
+ this.validateContractAddress();
304
+ break;
305
+ case sdk_core_1.TransactionType.FlushTokens:
306
+ this.validateContractAddress();
307
+ this.validateForwarderAddress();
308
+ this.validateTokenAddress();
309
+ break;
310
+ case sdk_core_1.TransactionType.SingleSigSend:
311
+ // for single sig sends, the contract address is actually the recipient
312
+ this.validateContractAddress();
313
+ break;
314
+ case sdk_core_1.TransactionType.StakingLock:
315
+ case sdk_core_1.TransactionType.StakingUnlock:
316
+ case sdk_core_1.TransactionType.StakingVote:
317
+ case sdk_core_1.TransactionType.StakingUnvote:
318
+ case sdk_core_1.TransactionType.StakingActivate:
319
+ case sdk_core_1.TransactionType.StakingWithdraw:
320
+ break;
321
+ case sdk_core_1.TransactionType.ContractCall:
322
+ this.validateContractAddress();
323
+ this.validateDataField();
324
+ break;
325
+ default:
326
+ throw new sdk_core_1.BuildTransactionError('Unsupported transaction type');
327
+ }
328
+ }
329
+ /**
330
+ * Check wallet owner addresses for wallet initialization transactions are valid or throw.
331
+ */
332
+ validateWalletInitializationFields() {
333
+ if (this._walletOwnerAddresses === undefined) {
334
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing wallet owners');
335
+ }
336
+ if (this._walletOwnerAddresses.length !== 3) {
337
+ throw new sdk_core_1.BuildTransactionError(`Invalid transaction: wrong number of owners -- required: 3, found: ${this._walletOwnerAddresses.length}`);
338
+ }
339
+ }
340
+ /**
341
+ * Check if a token address for the tx was defined or throw.
342
+ */
343
+ validateTokenAddress() {
344
+ if (this._tokenAddress === undefined) {
345
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing token address');
346
+ }
347
+ }
348
+ /**
349
+ * Check if a forwarder address for the tx was defined or throw.
350
+ */
351
+ validateForwarderAddress() {
352
+ if (this._forwarderAddress === undefined) {
353
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing forwarder address');
354
+ }
355
+ }
356
+ /**
357
+ * Check if a contract address for the wallet was defined or throw.
358
+ */
359
+ validateContractAddress() {
360
+ if (this._contractAddress === undefined) {
361
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing contract address');
362
+ }
363
+ }
364
+ /**
365
+ * Checks if a contract call data field was defined or throws otherwise
366
+ */
367
+ validateDataField() {
368
+ if (!this._data) {
369
+ throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing contract call data field');
370
+ }
371
+ }
372
+ setContract(address) {
373
+ if (address === undefined) {
374
+ throw new sdk_core_1.BuildTransactionError('Undefined recipient address');
375
+ }
376
+ this.contract(address);
377
+ }
378
+ validateValue(value) {
379
+ if (value.isLessThan(0)) {
380
+ throw new sdk_core_1.BuildTransactionError('Value cannot be below less than zero');
381
+ }
382
+ // TODO: validate the amount is not bigger than the max amount in each Eth family coin
383
+ }
384
+ // region Common builder methods
385
+ /**
386
+ * The type of transaction being built.
387
+ *
388
+ * @param {TransactionType} type
389
+ */
390
+ type(type) {
391
+ this._type = type;
392
+ }
393
+ /**
394
+ * Set the transaction fees. Low fees may get a transaction rejected or never picked up by bakers.
395
+ *
396
+ * @param {Fee} fee Baker fees. May also include the maximum gas to pay
397
+ */
398
+ fee(fee) {
399
+ this.validateValue(new bignumber_js_1.default(fee.fee));
400
+ if (fee.gasLimit) {
401
+ this.validateValue(new bignumber_js_1.default(fee.gasLimit));
402
+ }
403
+ if (fee.eip1559) {
404
+ this.validateValue(new bignumber_js_1.default(fee.eip1559.maxFeePerGas));
405
+ this.validateValue(new bignumber_js_1.default(fee.eip1559.maxPriorityFeePerGas));
406
+ }
407
+ if (fee.gasPrice) {
408
+ this.validateValue(new bignumber_js_1.default(fee.gasPrice));
409
+ }
410
+ this._fee = fee;
411
+ }
412
+ /**
413
+ * Set the transaction counter to prevent submitting repeated transactions.
414
+ *
415
+ * @param {number} counter The counter to use
416
+ */
417
+ counter(counter) {
418
+ if (counter < 0) {
419
+ throw new sdk_core_1.BuildTransactionError(`Invalid counter: ${counter}`);
420
+ }
421
+ this._counter = counter;
422
+ }
423
+ /**
424
+ * The value to send along with this transaction. 0 by default
425
+ *
426
+ * @param {string} value The value to send along with this transaction
427
+ */
428
+ value(value) {
429
+ this._value = value;
430
+ }
431
+ // set args that are required for all types of eth transactions
432
+ buildBase(data) {
433
+ var _a, _b;
434
+ const baseParams = {
435
+ gasLimit: this._fee.gasLimit,
436
+ nonce: this._counter,
437
+ data: data,
438
+ chainId: this._common.chainIdBN().toString(),
439
+ value: this._value,
440
+ to: this._contractAddress,
441
+ };
442
+ if (this._fee.eip1559) {
443
+ return {
444
+ ...baseParams,
445
+ _type: iface_1.ETHTransactionType.EIP1559,
446
+ maxFeePerGas: this._fee.eip1559.maxFeePerGas,
447
+ maxPriorityFeePerGas: this._fee.eip1559.maxPriorityFeePerGas,
448
+ };
449
+ }
450
+ else {
451
+ return {
452
+ ...baseParams,
453
+ _type: iface_1.ETHTransactionType.LEGACY,
454
+ gasPrice: (_b = (_a = this._fee) === null || _a === void 0 ? void 0 : _a.gasPrice) !== null && _b !== void 0 ? _b : this._fee.fee,
455
+ v: this.getFinalV(),
456
+ };
457
+ }
458
+ }
459
+ // endregion
460
+ // region WalletInitialization builder methods
461
+ /**
462
+ * Set one of the owners of the multisig wallet.
463
+ *
464
+ * @param {string} address An Ethereum address
465
+ */
466
+ owner(address) {
467
+ if (this._type !== sdk_core_1.TransactionType.WalletInitialization) {
468
+ throw new sdk_core_1.BuildTransactionError('Multisig wallet owner can only be set for initialization transactions');
469
+ }
470
+ if (this._walletOwnerAddresses.length >= DEFAULT_M) {
471
+ throw new sdk_core_1.BuildTransactionError('A maximum of ' + DEFAULT_M + ' owners can be set for a multisig wallet');
472
+ }
473
+ if (!utils_1.isValidEthAddress(address)) {
474
+ throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
475
+ }
476
+ if (this._walletOwnerAddresses.includes(address)) {
477
+ throw new sdk_core_1.BuildTransactionError('Repeated owner address: ' + address);
478
+ }
479
+ this._walletOwnerAddresses.push(address);
480
+ }
481
+ /**
482
+ * Build a transaction for a generic multisig contract.
483
+ *
484
+ * @returns {TxData} The Ethereum transaction data
485
+ */
486
+ buildWalletInitializationTransaction(walletVersion) {
487
+ const walletInitData = walletVersion === walletUtil_1.defaultWalletVersion
488
+ ? this.getContractData(this._walletOwnerAddresses)
489
+ : utils_1.getV1WalletInitializationData(this._walletOwnerAddresses, this._salt);
490
+ return this.buildBase(walletInitData);
491
+ }
492
+ /**
493
+ * Returns the smart contract encoded data
494
+ *
495
+ * @param {string[]} addresses - the contract signers
496
+ * @returns {string} - the smart contract encoded data
497
+ */
498
+ getContractData(addresses) {
499
+ const params = [addresses];
500
+ const resultEncodedParameters = ethereumjs_abi_1.default.rawEncode(walletUtil_1.walletSimpleConstructor, params)
501
+ .toString('hex')
502
+ .replace('0x', '');
503
+ return this._walletSimpleByteCode + resultEncodedParameters;
504
+ }
505
+ // endregion
506
+ // region Send builder methods
507
+ contract(address) {
508
+ if (!utils_1.isValidEthAddress(address)) {
509
+ throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
510
+ }
511
+ this._contractAddress = address;
512
+ }
513
+ /**
514
+ * Returns the serialized sendMultiSig contract method data
515
+ *
516
+ * @returns {string} serialized sendMultiSig data
517
+ */
518
+ getSendData() {
519
+ if (!this._transfer) {
520
+ throw new sdk_core_1.BuildTransactionError('Missing transfer information');
521
+ }
522
+ const chainId = this._common.chainIdBN().toString();
523
+ return this._transfer.signAndBuild(chainId);
524
+ }
525
+ buildSendTransaction() {
526
+ const sendData = this.getSendData();
527
+ const tx = this.buildBase(sendData);
528
+ tx.to = this._contractAddress;
529
+ return tx;
530
+ }
531
+ // endregion
532
+ // region AddressInitialization builder methods
533
+ /**
534
+ * Set the contract transaction nonce to calculate the forwarder address.
535
+ *
536
+ * @param {number} contractCounter The counter to use
537
+ */
538
+ contractCounter(contractCounter) {
539
+ if (contractCounter < 0) {
540
+ throw new sdk_core_1.BuildTransactionError(`Invalid contract counter: ${contractCounter}`);
541
+ }
542
+ this._contractCounter = contractCounter;
543
+ }
544
+ /**
545
+ * Build a transaction to create a forwarder.
546
+ *
547
+ * @returns {TxData} The Ethereum transaction data
548
+ */
549
+ buildAddressInitializationTransaction() {
550
+ const addressInitData = this._forwarderVersion === walletUtil_1.defaultForwarderVersion
551
+ ? utils_1.getAddressInitializationData()
552
+ : utils_1.getV1AddressInitializationData(this._baseAddress, this._salt);
553
+ const tx = this.buildBase(addressInitData);
554
+ tx.to = this._contractAddress;
555
+ if (this._contractCounter) {
556
+ tx.deployedAddress = utils_1.calculateForwarderAddress(this._contractAddress, this._contractCounter);
557
+ }
558
+ if (this._salt && this._initCode) {
559
+ const saltBuffer = ethUtil.setLengthLeft(ethUtil.toBuffer(this._salt), 32);
560
+ // Hash the wallet base address with the given salt, so the address directly relies on the base address
561
+ const calculationSalt = ethUtil.bufferToHex(ethereumjs_abi_1.default.soliditySHA3(['address', 'bytes32'], [this._baseAddress, saltBuffer]));
562
+ tx.deployedAddress = utils_1.calculateForwarderV1Address(this._contractAddress, calculationSalt, this._initCode);
563
+ }
564
+ return tx;
565
+ }
566
+ // endregion
567
+ // region flush methods
568
+ /**
569
+ * Set the forwarder address to flush
570
+ *
571
+ * @param {string} address The address to flush
572
+ */
573
+ forwarderAddress(address) {
574
+ if (!utils_1.isValidEthAddress(address)) {
575
+ throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
576
+ }
577
+ this._forwarderAddress = address;
578
+ }
579
+ /**
580
+ * Set the address of the ERC20 token contract that we are flushing tokens for
581
+ *
582
+ * @param {string} address the contract address of the token to flush
583
+ */
584
+ tokenAddress(address) {
585
+ if (!utils_1.isValidEthAddress(address)) {
586
+ throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
587
+ }
588
+ this._tokenAddress = address;
589
+ }
590
+ /**
591
+ * Build a transaction to flush tokens from a forwarder.
592
+ *
593
+ * @returns {TxData} The Ethereum transaction data
594
+ */
595
+ buildFlushTokensTransaction() {
596
+ return this.buildBase(utils_1.flushTokensData(this._forwarderAddress, this._tokenAddress));
597
+ }
598
+ /**
599
+ * Build a transaction to flush tokens from a forwarder.
600
+ *
601
+ * @returns {TxData} The Ethereum transaction data
602
+ */
603
+ buildFlushCoinsTransaction() {
604
+ return this.buildBase(utils_1.flushCoinsData());
605
+ }
606
+ // endregion
607
+ // region generic contract call
608
+ data(encodedCall) {
609
+ const supportedTransactionTypes = [sdk_core_1.TransactionType.ContractCall, sdk_core_1.TransactionType.RecoveryWalletDeployment];
610
+ if (!supportedTransactionTypes.includes(this._type)) {
611
+ throw new sdk_core_1.BuildTransactionError('data can only be set for contract call transaction types');
612
+ }
613
+ this._data = encodedCall;
614
+ }
615
+ buildGenericContractCallTransaction() {
616
+ return this.buildBase(this._data);
617
+ }
618
+ // endregion
619
+ /** @inheritdoc */
620
+ get transaction() {
621
+ return this._transaction;
622
+ }
623
+ /** @inheritdoc */
624
+ set transaction(transaction) {
625
+ this._transaction = transaction;
626
+ }
627
+ /**
628
+ * Get the final v value. Final v is described in EIP-155.
629
+ *
630
+ * @protected for internal use when the enableFinalVField flag is true.
631
+ */
632
+ getFinalV() {
633
+ return ethUtil.addHexPrefix(this._common.chainIdBN().muln(2).addn(35).toString(16));
634
+ }
635
+ /**
636
+ * Set the forwarder version for address to be initialized
637
+ *
638
+ * @param {number} version forwarder version
639
+ */
640
+ forwarderVersion(version) {
641
+ if (version < 0 || version > 2) {
642
+ throw new sdk_core_1.BuildTransactionError(`Invalid forwarder version: ${version}`);
643
+ }
644
+ this._forwarderVersion = version;
645
+ }
646
+ /**
647
+ * Set the salt to create the address using create2
648
+ *
649
+ * @param {string} salt The salt to create the address using create2, hex string
650
+ */
651
+ salt(salt) {
652
+ this._salt = salt;
653
+ }
654
+ /**
655
+ * Take the implementation address for the proxy contract, and get the binary initcode for the associated proxy
656
+ *
657
+ * @param {string} implementationAddress The address of the implementation contract
658
+ */
659
+ initCode(implementationAddress) {
660
+ if (!utils_1.isValidEthAddress(implementationAddress)) {
661
+ throw new sdk_core_1.BuildTransactionError('Invalid address: ' + implementationAddress);
662
+ }
663
+ this._initCode = utils_1.getProxyInitcode(implementationAddress);
664
+ }
665
+ /**
666
+ * Set the wallet version for wallet to be initialized
667
+ *
668
+ * @param {number} version wallet version
669
+ */
670
+ walletVersion(version) {
671
+ if (version < 0 || version > 3) {
672
+ throw new sdk_core_1.BuildTransactionError(`Invalid wallet version: ${version}`);
673
+ }
674
+ this._walletVersion = version;
675
+ }
676
+ /**
677
+ * Set the base address of the wallet
678
+ *
679
+ * @param {string} address The wallet contract address
680
+ */
681
+ baseAddress(address) {
682
+ if (!utils_1.isValidEthAddress(address)) {
683
+ throw new sdk_core_1.BuildTransactionError('Invalid address: ' + address);
684
+ }
685
+ this._baseAddress = address;
686
+ }
687
+ }
688
+ exports.TransactionBuilder = TransactionBuilder;
689
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLG9FQUF5QztBQUN6QyxnRUFBcUM7QUFDckMseURBQTJDO0FBQzNDLHVDQUE2RDtBQUU3RCxtREFZOEI7QUFFOUIsdUNBQW9DO0FBQ3BDLG1DQUEwRTtBQUMxRSxtQ0FnQmlCO0FBQ2pCLDZDQUFzRztBQUd0RywrQ0FBNEM7QUFHNUMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDO0FBRXBCOztHQUVHO0FBQ0gsTUFBc0Isa0JBQW1CLFNBQVEsaUNBQXNCO0lBdUNyRTs7OztPQUlHO0lBQ0gsWUFBWSxXQUFpQztRQUMzQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLE9BQU8sR0FBRyxpQkFBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBMEIsQ0FBQyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxLQUFLLEdBQUcsMEJBQWUsQ0FBQyxJQUFJLENBQUM7UUFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7UUFDbEIsSUFBSSxDQUFDLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSx5QkFBVyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ25FLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxFQUFFLENBQUM7SUFDbEMsQ0FBQztJQUVELGtCQUFrQjtJQUNSLEtBQUssQ0FBQyxtQkFBbUI7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R0FBRyxPQUFPLENBQUM7SUFDaEMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxXQUFXLENBQUMsT0FBZTtRQUN6QixJQUFJLENBQUMseUJBQWlCLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDL0IsTUFBTSxJQUFJLGdDQUFxQixDQUFDLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxDQUFDO1NBQ2hFO1FBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxPQUFPLENBQUM7SUFDOUIsQ0FBQztDQUNGO0FBcHZCRCxnREFvdkJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzZUNvaW4gYXMgQ29pbkNvbmZpZywgRXRoZXJldW1OZXR3b3JrIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgRXRoZXJldW1Db21tb24gZnJvbSAnQGV0aGVyZXVtanMvY29tbW9uJztcbmltcG9ydCBFdGhlcmV1bUFiaSBmcm9tICdldGhlcmV1bWpzLWFiaSc7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5pbXBvcnQgKiBhcyBldGhVdGlsIGZyb20gJ2V0aGVyZXVtanMtdXRpbCc7XG5pbXBvcnQgeyBGZWVNYXJrZXRFSVAxNTU5VHJhbnNhY3Rpb24gfSBmcm9tICdAZXRoZXJldW1qcy90eCc7XG5cbmltcG9ydCB7XG4gIEJhc2VBZGRyZXNzLFxuICBCYXNlS2V5LFxuICBCYXNlVHJhbnNhY3Rpb24sXG4gIEJhc2VUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gIEJ1aWxkVHJhbnNhY3Rpb25FcnJvcixcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIGlzVmFsaWRQcnYsXG4gIGlzVmFsaWRYcHJ2LFxuICBQYXJzZVRyYW5zYWN0aW9uRXJyb3IsXG4gIFNpZ25pbmdFcnJvcixcbiAgVHJhbnNhY3Rpb25UeXBlLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5cbmltcG9ydCB7IEtleVBhaXIgfSBmcm9tICcuL2tleVBhaXInO1xuaW1wb3J0IHsgRVRIVHJhbnNhY3Rpb25UeXBlLCBGZWUsIFNpZ25hdHVyZVBhcnRzLCBUeERhdGEgfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCB7XG4gIGNhbGN1bGF0ZUZvcndhcmRlckFkZHJlc3MsXG4gIGNhbGN1bGF0ZUZvcndhcmRlclYxQWRkcmVzcyxcbiAgY2xhc3NpZnlUcmFuc2FjdGlvbixcbiAgZGVjb2RlRm9yd2FyZGVyQ3JlYXRpb25EYXRhLFxuICBkZWNvZGVGbHVzaFRva2Vuc0RhdGEsXG4gIGRlY29kZVdhbGxldENyZWF0aW9uRGF0YSxcbiAgZmx1c2hDb2luc0RhdGEsXG4gIGZsdXNoVG9rZW5zRGF0YSxcbiAgZ2V0QWRkcmVzc0luaXRpYWxpemF0aW9uRGF0YSxcbiAgZ2V0VjFBZGRyZXNzSW5pdGlhbGl6YXRpb25EYXRhLFxuICBnZXRDb21tb24sXG4gIGdldFByb3h5SW5pdGNvZGUsXG4gIGhhc1NpZ25hdHVyZSxcbiAgaXNWYWxpZEV0aEFkZHJlc3MsXG4gIGdldFYxV2FsbGV0SW5pdGlhbGl6YXRpb25EYXRhLFxufSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IGRlZmF1bHRXYWxsZXRWZXJzaW9uLCBkZWZhdWx0Rm9yd2FyZGVyVmVyc2lvbiwgd2FsbGV0U2ltcGxlQ29uc3RydWN0b3IgfSBmcm9tICcuL3dhbGxldFV0aWwnO1xuaW1wb3J0IHsgRVJDMTE1NVRyYW5zZmVyQnVpbGRlciB9IGZyb20gJy4vdHJhbnNmZXJCdWlsZGVycy90cmFuc2ZlckJ1aWxkZXJFUkMxMTU1JztcbmltcG9ydCB7IEVSQzcyMVRyYW5zZmVyQnVpbGRlciB9IGZyb20gJy4vdHJhbnNmZXJCdWlsZGVycy90cmFuc2ZlckJ1aWxkZXJFUkM3MjEnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb24gfSBmcm9tICcuL3RyYW5zYWN0aW9uJztcbmltcG9ydCB7IFRyYW5zZmVyQnVpbGRlciB9IGZyb20gJy4vdHJhbnNmZXJCdWlsZGVyJztcblxuY29uc3QgREVGQVVMVF9NID0gMztcblxuLyoqXG4gKiBFdGhlcmV1bUxpa2UgdHJhbnNhY3Rpb24gYnVpbGRlci5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRyYW5zYWN0aW9uQnVpbGRlciBleHRlbmRzIEJhc2VUcmFuc2FjdGlvbkJ1aWxkZXIge1xuICBwcm90ZWN0ZWQgX3R5cGU6IFRyYW5zYWN0aW9uVHlwZTtcbiAgLy8gU3BlY2lmaWVzIGNvbW1vbiBjaGFpbiBhbmQgaGFyZGZvcmsgcGFyYW1ldGVycy5cbiAgcHJvdGVjdGVkIF9jb21tb246IEV0aGVyZXVtQ29tbW9uO1xuICBwcm90ZWN0ZWQgX3NvdXJjZUtleVBhaXI6IEtleVBhaXI7XG4gIHByaXZhdGUgX3RyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbjtcbiAgcHJpdmF0ZSBfY291bnRlcjogbnVtYmVyO1xuICBwcml2YXRlIF9mZWU6IEZlZTtcbiAgcHJvdGVjdGVkIF92YWx1ZTogc3RyaW5nO1xuXG4gIC8vIHRoZSBzaWduYXR1cmUgb24gdGhlIGV4dGVybmFsIEVUSCB0cmFuc2FjdGlvblxuICBwcml2YXRlIF90eFNpZ25hdHVyZTogU2lnbmF0dXJlUGFydHM7XG5cbiAgLy8gV2FsbGV0IGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uIHBhcmFtZXRlcnNcbiAgcHJpdmF0ZSBfd2FsbGV0T3duZXJBZGRyZXNzZXM6IHN0cmluZ1tdO1xuICBwcml2YXRlIF93YWxsZXRWZXJzaW9uOiBudW1iZXI7XG5cbiAgLy8gZmx1c2ggdG9rZW5zIHBhcmFtZXRlcnNcbiAgcHJpdmF0ZSBfZm9yd2FyZGVyQWRkcmVzczogc3RyaW5nO1xuICBwcml2YXRlIF90b2tlbkFkZHJlc3M6IHN0cmluZztcblxuICAvLyBTZW5kIGFuZCBBZGRyZXNzSW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb24gc3BlY2lmaWMgcGFyYW1ldGVyc1xuICBwcm90ZWN0ZWQgX3RyYW5zZmVyOiBUcmFuc2ZlckJ1aWxkZXIgfCBFUkM3MjFUcmFuc2ZlckJ1aWxkZXIgfCBFUkMxMTU1VHJhbnNmZXJCdWlsZGVyO1xuICBwcml2YXRlIF9jb250cmFjdEFkZHJlc3M6IHN0cmluZztcbiAgcHJpdmF0ZSBfY29udHJhY3RDb3VudGVyOiBudW1iZXI7XG4gIHByaXZhdGUgX2ZvcndhcmRlclZlcnNpb246IG51bWJlcjtcbiAgcHJpdmF0ZSBfaW5pdENvZGU6IHN0cmluZztcbiAgcHJpdmF0ZSBfYmFzZUFkZHJlc3M6IHN0cmluZztcblxuICAvLyBnZW5lcmljIGNvbnRyYWN0IGNhbGwgYnVpbGRlclxuICAvLyBlbmNvZGVkIGNvbnRyYWN0IGNhbGwgaGV4XG4gIHByaXZhdGUgX2RhdGE6IHN0cmluZztcblxuICAvLyBDb21tb24gcGFyYW1ldGVyIGZvciB3YWxsZXQgaW5pdGlhbGl6YXRpb24gYW5kIGFkZHJlc3MgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25cbiAgcHJpdmF0ZSBfc2FsdDogc3RyaW5nO1xuXG4gIC8vIHdhbGxldHNpbXBsZWJ5dGVjb2RlXG4gIHByb3RlY3RlZCBfd2FsbGV0U2ltcGxlQnl0ZUNvZGU6IHN0cmluZztcblxuICAvKipcbiAgICogUHVibGljIGNvbnN0cnVjdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gX2NvaW5Db25maWdcbiAgICovXG4gIGNvbnN0cnVjdG9yKF9jb2luQ29uZmlnOiBSZWFkb25seTxDb2luQ29uZmlnPikge1xuICAgIHN1cGVyKF9jb2luQ29uZmlnKTtcbiAgICB0aGlzLl9jb21tb24gPSBnZXRDb21tb24odGhpcy5fY29pbkNvbmZpZy5uZXR3b3JrIGFzIEV0aGVyZXVtTmV0d29yayk7XG4gICAgdGhpcy5fdHlwZSA9IFRyYW5zYWN0aW9uVHlwZS5TZW5kO1xuICAgIHRoaXMuX2NvdW50ZXIgPSAwO1xuICAgIHRoaXMuX3ZhbHVlID0gJzAnO1xuICAgIHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzID0gW107XG4gICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA9IDA7XG4gICAgdGhpcy5fd2FsbGV0VmVyc2lvbiA9IDA7XG4gICAgdGhpcy50cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0aGlzLl9jb21tb24pO1xuICAgIHRoaXMuX3dhbGxldFNpbXBsZUJ5dGVDb2RlID0gJyc7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGJ1aWxkSW1wbGVtZW50YXRpb24oKTogUHJvbWlzZTxCYXNlVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB0cmFuc2FjdGlvbkRhdGEgPSB0aGlzLmdldFRyYW5zYWN0aW9uRGF0YSgpO1xuXG4gICAgaWYgKHRoaXMuX3R4U2lnbmF0dXJlKSB7XG4gICAgICBPYmplY3QuYXNzaWduKHRyYW5zYWN0aW9uRGF0YSwgdGhpcy5fdHhTaWduYXR1cmUpO1xuICAgIH1cblxuICAgIHRoaXMudHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKHRoaXMuX3R5cGUpO1xuICAgIHRyYW5zYWN0aW9uRGF0YS5mcm9tID0gdGhpcy5fc291cmNlS2V5UGFpciA/IHRoaXMuX3NvdXJjZUtleVBhaXIuZ2V0QWRkcmVzcygpIDogdW5kZWZpbmVkO1xuICAgIHRoaXMudHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25EYXRhKHRyYW5zYWN0aW9uRGF0YSk7XG5cbiAgICAvLyBCdWlsZCBhbmQgc2lnbiBhIG5ldyB0cmFuc2FjdGlvbiBiYXNlZCBvbiB0aGUgbGF0ZXN0IGNoYW5nZXNcbiAgICBpZiAodGhpcy5fc291cmNlS2V5UGFpciAmJiB0aGlzLl9zb3VyY2VLZXlQYWlyLmdldEtleXMoKS5wcnYpIHtcbiAgICAgIGF3YWl0IHRoaXMudHJhbnNhY3Rpb24uc2lnbih0aGlzLl9zb3VyY2VLZXlQYWlyKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudHJhbnNhY3Rpb247XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VHJhbnNhY3Rpb25EYXRhKCk6IFR4RGF0YSB7XG4gICAgc3dpdGNoICh0aGlzLl90eXBlKSB7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5XYWxsZXRJbml0aWFsaXphdGlvbjpcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRXYWxsZXRJbml0aWFsaXphdGlvblRyYW5zYWN0aW9uKHRoaXMuX3dhbGxldFZlcnNpb24pO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuUmVjb3ZlcnlXYWxsZXREZXBsb3ltZW50OlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEJhc2UodGhpcy5fZGF0YSk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzcyMTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmRFUkMxMTU1OlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZFNlbmRUcmFuc2FjdGlvbigpO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQWRkcmVzc0luaXRpYWxpemF0aW9uOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEFkZHJlc3NJbml0aWFsaXphdGlvblRyYW5zYWN0aW9uKCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaFRva2VuczpcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRGbHVzaFRva2Vuc1RyYW5zYWN0aW9uKCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaENvaW5zOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEZsdXNoQ29pbnNUcmFuc2FjdGlvbigpO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2luZ2xlU2lnU2VuZDpcbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRCYXNlKCcweCcpO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICByZXR1cm4gdGhpcy5idWlsZEdlbmVyaWNDb250cmFjdENhbGxUcmFuc2FjdGlvbigpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5zdXBwb3J0ZWQgdHJhbnNhY3Rpb24gdHlwZScpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZnJvbUltcGxlbWVudGF0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiBUcmFuc2FjdGlvbiB7XG4gICAgbGV0IHR4OiBUcmFuc2FjdGlvbjtcbiAgICBpZiAoL14weD9bMC05YS1mXXsxLH0kLy50ZXN0KHJhd1RyYW5zYWN0aW9uLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICB0eCA9IFRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkKHRoaXMuX2NvaW5Db25maWcsIHRoaXMuX2NvbW1vbiwgcmF3VHJhbnNhY3Rpb24pO1xuICAgICAgdGhpcy5sb2FkQnVpbGRlcklucHV0KHR4LnRvSnNvbigpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdHhEYXRhID0gSlNPTi5wYXJzZShyYXdUcmFuc2FjdGlvbik7XG4gICAgICB0eCA9IG5ldyBUcmFuc2FjdGlvbih0aGlzLl9jb2luQ29uZmlnLCB0eERhdGEpO1xuICAgIH1cbiAgICByZXR1cm4gdHg7XG4gIH1cblxuICAvKipcbiAgICogTG9hZCB0aGUgYnVpbGRlciBkYXRhIHVzaW5nIHRoZSBkZXNlcmlhbGl6ZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtUeERhdGF9IHRyYW5zYWN0aW9uSnNvbiB0aGUgZGVzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGpzb25cbiAgICovXG4gIHByb3RlY3RlZCBsb2FkQnVpbGRlcklucHV0KHRyYW5zYWN0aW9uSnNvbjogVHhEYXRhKTogdm9pZCB7XG4gICAgY29uc3QgZGVjb2RlZFR5cGUgPSBjbGFzc2lmeVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICB0aGlzLnR5cGUoZGVjb2RlZFR5cGUpO1xuICAgIHRoaXMuY291bnRlcih0cmFuc2FjdGlvbkpzb24ubm9uY2UpO1xuICAgIHRoaXMudmFsdWUodHJhbnNhY3Rpb25Kc29uLnZhbHVlKTtcblxuICAgIGlmICh0cmFuc2FjdGlvbkpzb24uX3R5cGUgPT09IEVUSFRyYW5zYWN0aW9uVHlwZS5MRUdBQ1kpIHtcbiAgICAgIHRoaXMuZmVlKHtcbiAgICAgICAgZmVlOiB0cmFuc2FjdGlvbkpzb24uZ2FzUHJpY2UsXG4gICAgICAgIGdhc1ByaWNlOiB0cmFuc2FjdGlvbkpzb24uZ2FzUHJpY2UsXG4gICAgICAgIGdhc0xpbWl0OiB0cmFuc2FjdGlvbkpzb24uZ2FzTGltaXQsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5mZWUoe1xuICAgICAgICBnYXNMaW1pdDogdHJhbnNhY3Rpb25Kc29uLmdhc0xpbWl0LFxuICAgICAgICBmZWU6IHRyYW5zYWN0aW9uSnNvbi5tYXhGZWVQZXJHYXMsXG4gICAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgICBtYXhGZWVQZXJHYXM6IHRyYW5zYWN0aW9uSnNvbi5tYXhGZWVQZXJHYXMsXG4gICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IHRyYW5zYWN0aW9uSnNvbi5tYXhQcmlvcml0eUZlZVBlckdhcyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChoYXNTaWduYXR1cmUodHJhbnNhY3Rpb25Kc29uKSkge1xuICAgICAgdGhpcy5fdHhTaWduYXR1cmUgPSB7IHY6IHRyYW5zYWN0aW9uSnNvbi52ISwgcjogdHJhbnNhY3Rpb25Kc29uLnIhLCBzOiB0cmFuc2FjdGlvbkpzb24ucyEgfTtcbiAgICB9XG4gICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGVGaWVsZHMoZGVjb2RlZFR5cGUsIHRyYW5zYWN0aW9uSnNvbik7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0VHJhbnNhY3Rpb25UeXBlRmllbGRzKGRlY29kZWRUeXBlOiBUcmFuc2FjdGlvblR5cGUsIHRyYW5zYWN0aW9uSnNvbjogVHhEYXRhKTogdm9pZCB7XG4gICAgc3dpdGNoIChkZWNvZGVkVHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICAgIGNvbnN0IHsgb3duZXJzLCBzYWx0IH0gPSBkZWNvZGVXYWxsZXRDcmVhdGlvbkRhdGEodHJhbnNhY3Rpb25Kc29uLmRhdGEpO1xuICAgICAgICBvd25lcnMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgICAgIHRoaXMub3duZXIoZWxlbWVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoc2FsdCkge1xuICAgICAgICAgIHRoaXMuc2FsdChzYWx0IGFzIHN0cmluZyk7XG4gICAgICAgICAgdGhpcy53YWxsZXRWZXJzaW9uKDEpO1xuICAgICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudDpcbiAgICAgICAgdGhpcy5kYXRhKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaFRva2VuczpcbiAgICAgICAgdGhpcy5zZXRDb250cmFjdCh0cmFuc2FjdGlvbkpzb24udG8pO1xuICAgICAgICBjb25zdCB7IGZvcndhcmRlckFkZHJlc3MsIHRva2VuQWRkcmVzcyB9ID0gZGVjb2RlRmx1c2hUb2tlbnNEYXRhKHRyYW5zYWN0aW9uSnNvbi5kYXRhKTtcbiAgICAgICAgdGhpcy5mb3J3YXJkZXJBZGRyZXNzKGZvcndhcmRlckFkZHJlc3MpO1xuICAgICAgICB0aGlzLnRva2VuQWRkcmVzcyh0b2tlbkFkZHJlc3MpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkZsdXNoQ29pbnM6XG4gICAgICAgIHRoaXMuc2V0Q29udHJhY3QodHJhbnNhY3Rpb25Kc29uLnRvKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzExNTU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDNzIxOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIHRoaXMuX3RyYW5zZmVyID0gdGhpcy50cmFuc2Zlcih0cmFuc2FjdGlvbkpzb24uZGF0YSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQWRkcmVzc0luaXRpYWxpemF0aW9uOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIGNvbnN0IHsgYmFzZUFkZHJlc3MsIGFkZHJlc3NDcmVhdGlvblNhbHQgfSA9IGRlY29kZUZvcndhcmRlckNyZWF0aW9uRGF0YSh0cmFuc2FjdGlvbkpzb24uZGF0YSk7XG4gICAgICAgIGlmIChiYXNlQWRkcmVzcyAmJiBhZGRyZXNzQ3JlYXRpb25TYWx0KSB7XG4gICAgICAgICAgdGhpcy5mb3J3YXJkZXJWZXJzaW9uKDEpO1xuICAgICAgICAgIHRoaXMuYmFzZUFkZHJlc3MoYmFzZUFkZHJlc3MpO1xuICAgICAgICAgIHRoaXMuc2FsdChhZGRyZXNzQ3JlYXRpb25TYWx0KTtcbiAgICAgICAgICBjb25zdCBmb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MgPSAodGhpcy5fY29pbkNvbmZpZy5uZXR3b3JrIGFzIEV0aGVyZXVtTmV0d29yaylcbiAgICAgICAgICAgIC5mb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MgYXMgc3RyaW5nO1xuICAgICAgICAgIGlmIChmb3J3YXJkZXJJbXBsZW1lbnRhdGlvbkFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdENvZGUoZm9yd2FyZGVySW1wbGVtZW50YXRpb25BZGRyZXNzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICB0aGlzLnNldENvbnRyYWN0KHRyYW5zYWN0aW9uSnNvbi50byk7XG4gICAgICAgIHRoaXMuZGF0YSh0cmFuc2FjdGlvbkpzb24uZGF0YSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5zdXBwb3J0ZWQgdHJhbnNhY3Rpb24gdHlwZScpO1xuICAgICAgLy8gVE9ETzogQWRkIG90aGVyIGNhc2VzIG9mIGRlc2VyaWFsaXphdGlvblxuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgc2lnbkltcGxlbWVudGF0aW9uKGtleTogQmFzZUtleSk6IEJhc2VUcmFuc2FjdGlvbiB7XG4gICAgY29uc3Qgc2lnbmVyID0gbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSk7XG4gICAgaWYgKHRoaXMuX3R5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5XYWxsZXRJbml0aWFsaXphdGlvbiAmJiB0aGlzLl93YWxsZXRPd25lckFkZHJlc3Nlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ0Nhbm5vdCBzaWduIGFuIHdhbGxldCBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbiB3aXRob3V0IG93bmVycycpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fc291cmNlS2V5UGFpcikge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignQ2Fubm90IHNpZ24gbXVsdGlwbGUgdGltZXMgYSBub24gc2VuZC10eXBlIHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICAgIC8vIFNpZ25pbmcgdGhlIHRyYW5zYWN0aW9uIGlzIGFuIGFzeW5jIG9wZXJhdGlvbiwgc28gc2F2ZSB0aGUgc291cmNlIGFuZCBsZWF2ZSB0aGUgYWN0dWFsXG4gICAgLy8gc2lnbmluZyBmb3IgdGhlIGJ1aWxkIHN0ZXBcbiAgICB0aGlzLl9zb3VyY2VLZXlQYWlyID0gc2lnbmVyO1xuICAgIHJldHVybiB0aGlzLnRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlQWRkcmVzcyhhZGRyZXNzOiBCYXNlQWRkcmVzcyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcy5hZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBhZGRyZXNzICcgKyBhZGRyZXNzLmFkZHJlc3MpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB2YWxpZGF0ZUtleShrZXk6IEJhc2VLZXkpOiB2b2lkIHtcbiAgICBpZiAoIShpc1ZhbGlkWHBydihrZXkua2V5KSB8fCBpc1ZhbGlkUHJ2KGtleS5rZXkpKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBrZXknKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIHJhdyB0cmFuc2FjdGlvbiBpcyBlaXRoZXIgYSBKU09OIG9yXG4gICAqIGEgaGV4IGVuY29kZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHthbnl9IHJhd1RyYW5zYWN0aW9uIFRoZSByYXcgdHJhbnNhY3Rpb24gdG8gYmUgdmFsaWRhdGVkXG4gICAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoIXJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBlbXB0eScpO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHJhd1RyYW5zYWN0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKC9eMHg/WzAtOWEtZl17MSx9JC8udGVzdChyYXdUcmFuc2FjdGlvbi50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICBjb25zdCB0eEJ5dGVzID0gZXRoVXRpbC50b0J1ZmZlcihldGhVdGlsLmFkZEhleFByZWZpeChyYXdUcmFuc2FjdGlvbi50b0xvd2VyQ2FzZSgpKSk7XG4gICAgICAgIGlmICghdGhpcy5pc0VpcDE1NTlUeG4odHhCeXRlcykgJiYgIXRoaXMuaXNSTFBEZWNvZGFibGUodHhCeXRlcykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdUaGVyZSB3YXMgZXJyb3IgaW4gZGVjb2RpbmcgdGhlIGhleCBzdHJpbmcnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBKU09OLnBhcnNlKHJhd1RyYW5zYWN0aW9uKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1RoZXJlIHdhcyBlcnJvciBpbiBwYXJzaW5nIHRoZSBKU09OIHN0cmluZycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gaXMgbm90IGEgaGV4IHN0cmluZyBvciBzdHJpbmdpZmllZCBqc29uJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc0VpcDE1NTlUeG4odHhuOiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkVHgodHhuKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzUkxQRGVjb2RhYmxlKGJ5dGVzOiBCdWZmZXIpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZXRoVXRpbC5ybHAuZGVjb2RlKGJ5dGVzKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgdmFsaWRhdGVCYXNlVHJhbnNhY3Rpb25GaWVsZHMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2ZlZSA9PT0gdW5kZWZpbmVkIHx8ICghdGhpcy5fZmVlLmZlZSAmJiAhdGhpcy5fZmVlLmdhc1ByaWNlICYmICF0aGlzLl9mZWUuZWlwMTU1OSkpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgZmVlJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9jb21tb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbmV0d29yayBjb21tb24nKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX2NvdW50ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBhZGRyZXNzIGNvdW50ZXInKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbjogQmFzZVRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy52YWxpZGF0ZUJhc2VUcmFuc2FjdGlvbkZpZWxkcygpO1xuICAgIHN3aXRjaCAodGhpcy5fdHlwZSkge1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMudmFsaWRhdGVXYWxsZXRJbml0aWFsaXphdGlvbkZpZWxkcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudDpcbiAgICAgICAgdGhpcy52YWxpZGF0ZURhdGFGaWVsZCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kRVJDNzIxOlxuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU2VuZEVSQzExNTU6XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb246XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5GbHVzaENvaW5zOlxuICAgICAgICB0aGlzLnZhbGlkYXRlQ29udHJhY3RBZGRyZXNzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuRmx1c2hUb2tlbnM6XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZUZvcndhcmRlckFkZHJlc3MoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRva2VuQWRkcmVzcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNpbmdsZVNpZ1NlbmQ6XG4gICAgICAgIC8vIGZvciBzaW5nbGUgc2lnIHNlbmRzLCB0aGUgY29udHJhY3QgYWRkcmVzcyBpcyBhY3R1YWxseSB0aGUgcmVjaXBpZW50XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nTG9jazpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2s6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nVm90ZTpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbnZvdGU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGU6XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsOlxuICAgICAgICB0aGlzLnZhbGlkYXRlQ29udHJhY3RBZGRyZXNzKCk7XG4gICAgICAgIHRoaXMudmFsaWRhdGVEYXRhRmllbGQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdVbnN1cHBvcnRlZCB0cmFuc2FjdGlvbiB0eXBlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdhbGxldCBvd25lciBhZGRyZXNzZXMgZm9yIHdhbGxldCBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbnMgYXJlIHZhbGlkIG9yIHRocm93LlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVdhbGxldEluaXRpYWxpemF0aW9uRmllbGRzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl93YWxsZXRPd25lckFkZHJlc3NlcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIHdhbGxldCBvd25lcnMnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RoICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKFxuICAgICAgICBgSW52YWxpZCB0cmFuc2FjdGlvbjogd3JvbmcgbnVtYmVyIG9mIG93bmVycyAtLSByZXF1aXJlZDogMywgZm91bmQ6ICR7dGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RofWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgdG9rZW4gYWRkcmVzcyBmb3IgdGhlIHR4IHdhcyBkZWZpbmVkIG9yIHRocm93LlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVRva2VuQWRkcmVzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fdG9rZW5BZGRyZXNzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgdG9rZW4gYWRkcmVzcycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhIGZvcndhcmRlciBhZGRyZXNzIGZvciB0aGUgdHggd2FzIGRlZmluZWQgb3IgdGhyb3cuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlRm9yd2FyZGVyQWRkcmVzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZm9yd2FyZGVyQWRkcmVzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGZvcndhcmRlciBhZGRyZXNzJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgY29udHJhY3QgYWRkcmVzcyBmb3IgdGhlIHdhbGxldCB3YXMgZGVmaW5lZCBvciB0aHJvdy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVDb250cmFjdEFkZHJlc3MoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2NvbnRyYWN0QWRkcmVzcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGFkZHJlc3MnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgY29udHJhY3QgY2FsbCBkYXRhIGZpZWxkIHdhcyBkZWZpbmVkIG9yIHRocm93cyBvdGhlcndpc2VcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRhRmllbGQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9kYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIGNvbnRyYWN0IGNhbGwgZGF0YSBmaWVsZCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2V0Q29udHJhY3QoYWRkcmVzczogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgaWYgKGFkZHJlc3MgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVW5kZWZpbmVkIHJlY2lwaWVudCBhZGRyZXNzJyk7XG4gICAgfVxuICAgIHRoaXMuY29udHJhY3QoYWRkcmVzcyk7XG4gIH1cblxuICB2YWxpZGF0ZVZhbHVlKHZhbHVlOiBCaWdOdW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmFsdWUuaXNMZXNzVGhhbigwKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVmFsdWUgY2Fubm90IGJlIGJlbG93IGxlc3MgdGhhbiB6ZXJvJyk7XG4gICAgfVxuICAgIC8vIFRPRE86IHZhbGlkYXRlIHRoZSBhbW91bnQgaXMgbm90IGJpZ2dlciB0aGFuIHRoZSBtYXggYW1vdW50IGluIGVhY2ggRXRoIGZhbWlseSBjb2luXG4gIH1cblxuICAvLyByZWdpb24gQ29tbW9uIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIC8qKlxuICAgKiBUaGUgdHlwZSBvZiB0cmFuc2FjdGlvbiBiZWluZyBidWlsdC5cbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblR5cGV9IHR5cGVcbiAgICovXG4gIHR5cGUodHlwZTogVHJhbnNhY3Rpb25UeXBlKTogdm9pZCB7XG4gICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBmZWVzLiBMb3cgZmVlcyBtYXkgZ2V0IGEgdHJhbnNhY3Rpb24gcmVqZWN0ZWQgb3IgbmV2ZXIgcGlja2VkIHVwIGJ5IGJha2Vycy5cbiAgICpcbiAgICogQHBhcmFtIHtGZWV9IGZlZSBCYWtlciBmZWVzLiBNYXkgYWxzbyBpbmNsdWRlIHRoZSBtYXhpbXVtIGdhcyB0byBwYXlcbiAgICovXG4gIGZlZShmZWU6IEZlZSk6IHZvaWQge1xuICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5mZWUpKTtcbiAgICBpZiAoZmVlLmdhc0xpbWl0KSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZ2FzTGltaXQpKTtcbiAgICB9XG4gICAgaWYgKGZlZS5laXAxNTU5KSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZWlwMTU1OS5tYXhGZWVQZXJHYXMpKTtcbiAgICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5laXAxNTU5Lm1heFByaW9yaXR5RmVlUGVyR2FzKSk7XG4gICAgfVxuICAgIGlmIChmZWUuZ2FzUHJpY2UpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVWYWx1ZShuZXcgQmlnTnVtYmVyKGZlZS5nYXNQcmljZSkpO1xuICAgIH1cbiAgICB0aGlzLl9mZWUgPSBmZWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBjb3VudGVyIHRvIHByZXZlbnQgc3VibWl0dGluZyByZXBlYXRlZCB0cmFuc2FjdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb3VudGVyIFRoZSBjb3VudGVyIHRvIHVzZVxuICAgKi9cbiAgY291bnRlcihjb3VudGVyOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoY291bnRlciA8IDApIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgY291bnRlcjogJHtjb3VudGVyfWApO1xuICAgIH1cblxuICAgIHRoaXMuX2NvdW50ZXIgPSBjb3VudGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB2YWx1ZSB0byBzZW5kIGFsb25nIHdpdGggdGhpcyB0cmFuc2FjdGlvbi4gMCBieSBkZWZhdWx0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VuZCBhbG9uZyB3aXRoIHRoaXMgdHJhbnNhY3Rpb25cbiAgICovXG4gIHZhbHVlKHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICB9XG5cbiAgLy8gc2V0IGFyZ3MgdGhhdCBhcmUgcmVxdWlyZWQgZm9yIGFsbCB0eXBlcyBvZiBldGggdHJhbnNhY3Rpb25zXG4gIHByb3RlY3RlZCBidWlsZEJhc2UoZGF0YTogc3RyaW5nKTogVHhEYXRhIHtcbiAgICBjb25zdCBiYXNlUGFyYW1zID0ge1xuICAgICAgZ2FzTGltaXQ6IHRoaXMuX2ZlZS5nYXNMaW1pdCxcbiAgICAgIG5vbmNlOiB0aGlzLl9jb3VudGVyLFxuICAgICAgZGF0YTogZGF0YSxcbiAgICAgIGNoYWluSWQ6IHRoaXMuX2NvbW1vbi5jaGFpbklkQk4oKS50b1N0cmluZygpLFxuICAgICAgdmFsdWU6IHRoaXMuX3ZhbHVlLFxuICAgICAgdG86IHRoaXMuX2NvbnRyYWN0QWRkcmVzcyxcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuX2ZlZS5laXAxNTU5KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICBfdHlwZTogRVRIVHJhbnNhY3Rpb25UeXBlLkVJUDE1NTksXG4gICAgICAgIG1heEZlZVBlckdhczogdGhpcy5fZmVlLmVpcDE1NTkubWF4RmVlUGVyR2FzLFxuICAgICAgICBtYXhQcmlvcml0eUZlZVBlckdhczogdGhpcy5fZmVlLmVpcDE1NTkubWF4UHJpb3JpdHlGZWVQZXJHYXMsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICBfdHlwZTogRVRIVHJhbnNhY3Rpb25UeXBlLkxFR0FDWSxcbiAgICAgICAgZ2FzUHJpY2U6IHRoaXMuX2ZlZT8uZ2FzUHJpY2UgPz8gdGhpcy5fZmVlLmZlZSxcbiAgICAgICAgdjogdGhpcy5nZXRGaW5hbFYoKSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIFdhbGxldEluaXRpYWxpemF0aW9uIGJ1aWxkZXIgbWV0aG9kc1xuICAvKipcbiAgICogU2V0IG9uZSBvZiB0aGUgb3duZXJzIG9mIHRoZSBtdWx0aXNpZyB3YWxsZXQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIEFuIEV0aGVyZXVtIGFkZHJlc3NcbiAgICovXG4gIG93bmVyKGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLl90eXBlICE9PSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb24pIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ011bHRpc2lnIHdhbGxldCBvd25lciBjYW4gb25seSBiZSBzZXQgZm9yIGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9ucycpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fd2FsbGV0T3duZXJBZGRyZXNzZXMubGVuZ3RoID49IERFRkFVTFRfTSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignQSBtYXhpbXVtIG9mICcgKyBERUZBVUxUX00gKyAnIG93bmVycyBjYW4gYmUgc2V0IGZvciBhIG11bHRpc2lnIHdhbGxldCcpO1xuICAgIH1cbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLmluY2x1ZGVzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdSZXBlYXRlZCBvd25lciBhZGRyZXNzOiAnICsgYWRkcmVzcyk7XG4gICAgfVxuICAgIHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLnB1c2goYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSB0cmFuc2FjdGlvbiBmb3IgYSBnZW5lcmljIG11bHRpc2lnIGNvbnRyYWN0LlxuICAgKlxuICAgKiBAcmV0dXJucyB7VHhEYXRhfSBUaGUgRXRoZXJldW0gdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgcHJvdGVjdGVkIGJ1aWxkV2FsbGV0SW5pdGlhbGl6YXRpb25UcmFuc2FjdGlvbih3YWxsZXRWZXJzaW9uPzogbnVtYmVyKTogVHhEYXRhIHtcbiAgICBjb25zdCB3YWxsZXRJbml0RGF0YSA9XG4gICAgICB3YWxsZXRWZXJzaW9uID09PSBkZWZhdWx0V2FsbGV0VmVyc2lvblxuICAgICAgICA/IHRoaXMuZ2V0Q29udHJhY3REYXRhKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzKVxuICAgICAgICA6IGdldFYxV2FsbGV0SW5pdGlhbGl6YXRpb25EYXRhKHRoaXMuX3dhbGxldE93bmVyQWRkcmVzc2VzLCB0aGlzLl9zYWx0KTtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJhc2Uod2FsbGV0SW5pdERhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNtYXJ0IGNvbnRyYWN0IGVuY29kZWQgZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBhZGRyZXNzZXMgLSB0aGUgY29udHJhY3Qgc2lnbmVyc1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIHRoZSBzbWFydCBjb250cmFjdCBlbmNvZGVkIGRhdGFcbiAgICovXG4gIHByb3RlY3RlZCBnZXRDb250cmFjdERhdGEoYWRkcmVzc2VzOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFyYW1zID0gW2FkZHJlc3Nlc107XG4gICAgY29uc3QgcmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUod2FsbGV0U2ltcGxlQ29uc3RydWN0b3IsIHBhcmFtcylcbiAgICAgIC50b1N0cmluZygnaGV4JylcbiAgICAgIC5yZXBsYWNlKCcweCcsICcnKTtcbiAgICByZXR1cm4gdGhpcy5fd2FsbGV0U2ltcGxlQnl0ZUNvZGUgKyByZXN1bHRFbmNvZGVkUGFyYW1ldGVycztcbiAgfVxuXG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8vIHJlZ2lvbiBTZW5kIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIGNvbnRyYWN0KGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIGFkZHJlc3MpO1xuICAgIH1cbiAgICB0aGlzLl9jb250cmFjdEFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHRyYW5zZmVyIGZ1bmRzIGJ1aWxkZXIgaWYgZXhpc3QsIG9yIGNyZWF0ZXMgYSBuZXcgb25lIGZvciB0aGlzIHRyYW5zYWN0aW9uIGFuZCByZXR1cm5zIGl0XG4gICAqXG4gICAqIEBwYXJhbSBbZGF0YV0gdHJhbnNmZXIgZGF0YSB0byBpbml0aWFsaXplIHRoZSB0cmFuc2ZlciBidWlsZGVyIHdpdGgsIGVtcHR5IGlmIG5vbmUgZ2l2ZW5cbiAgICogQHJldHVybnMge1RyYW5zZmVyQnVpbGRlciB8IEVSQzcyMVRyYW5zZmVyQnVpbGRlciB8IEVSQzExNTVUcmFuc2ZlckJ1aWxkZXJ9IHRoZSB0cmFuc2ZlciBidWlsZGVyXG4gICAqL1xuICBhYnN0cmFjdCB0cmFuc2ZlcihkYXRhPzogc3RyaW5nKTogVHJhbnNmZXJCdWlsZGVyIHwgRVJDNzIxVHJhbnNmZXJCdWlsZGVyIHwgRVJDMTE1NVRyYW5zZmVyQnVpbGRlcjtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2VyaWFsaXplZCBzZW5kTXVsdGlTaWcgY29udHJhY3QgbWV0aG9kIGRhdGFcbiAgICpcbiAgICogQHJldHVybnMge3N0cmluZ30gc2VyaWFsaXplZCBzZW5kTXVsdGlTaWcgZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTZW5kRGF0YSgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fdHJhbnNmZXIpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ01pc3NpbmcgdHJhbnNmZXIgaW5mb3JtYXRpb24nKTtcbiAgICB9XG4gICAgY29uc3QgY2hhaW5JZCA9IHRoaXMuX2NvbW1vbi5jaGFpbklkQk4oKS50b1N0cmluZygpO1xuICAgIHJldHVybiB0aGlzLl90cmFuc2Zlci5zaWduQW5kQnVpbGQoY2hhaW5JZCk7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkU2VuZFRyYW5zYWN0aW9uKCk6IFR4RGF0YSB7XG4gICAgY29uc3Qgc2VuZERhdGEgPSB0aGlzLmdldFNlbmREYXRhKCk7XG4gICAgY29uc3QgdHg6IFR4RGF0YSA9IHRoaXMuYnVpbGRCYXNlKHNlbmREYXRhKTtcbiAgICB0eC50byA9IHRoaXMuX2NvbnRyYWN0QWRkcmVzcztcbiAgICByZXR1cm4gdHg7XG4gIH1cblxuICAvLyBlbmRyZWdpb25cblxuICAvLyByZWdpb24gQWRkcmVzc0luaXRpYWxpemF0aW9uIGJ1aWxkZXIgbWV0aG9kc1xuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGNvbnRyYWN0IHRyYW5zYWN0aW9uIG5vbmNlIHRvIGNhbGN1bGF0ZSB0aGUgZm9yd2FyZGVyIGFkZHJlc3MuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb250cmFjdENvdW50ZXIgVGhlIGNvdW50ZXIgdG8gdXNlXG4gICAqL1xuICBjb250cmFjdENvdW50ZXIoY29udHJhY3RDb3VudGVyOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoY29udHJhY3RDb3VudGVyIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBjb250cmFjdCBjb3VudGVyOiAke2NvbnRyYWN0Q291bnRlcn1gKTtcbiAgICB9XG5cbiAgICB0aGlzLl9jb250cmFjdENvdW50ZXIgPSBjb250cmFjdENvdW50ZXI7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSB0cmFuc2FjdGlvbiB0byBjcmVhdGUgYSBmb3J3YXJkZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIHtUeERhdGF9IFRoZSBFdGhlcmV1bSB0cmFuc2FjdGlvbiBkYXRhXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkQWRkcmVzc0luaXRpYWxpemF0aW9uVHJhbnNhY3Rpb24oKTogVHhEYXRhIHtcbiAgICBjb25zdCBhZGRyZXNzSW5pdERhdGEgPVxuICAgICAgdGhpcy5fZm9yd2FyZGVyVmVyc2lvbiA9PT0gZGVmYXVsdEZvcndhcmRlclZlcnNpb25cbiAgICAgICAgPyBnZXRBZGRyZXNzSW5pdGlhbGl6YXRpb25EYXRhKClcbiAgICAgICAgOiBnZXRWMUFkZHJlc3NJbml0aWFsaXphdGlvbkRhdGEodGhpcy5fYmFzZUFkZHJlc3MsIHRoaXMuX3NhbHQpO1xuICAgIGNvbnN0IHR4OiBUeERhdGEgPSB0aGlzLmJ1aWxkQmFzZShhZGRyZXNzSW5pdERhdGEpO1xuICAgIHR4LnRvID0gdGhpcy5fY29udHJhY3RBZGRyZXNzO1xuXG4gICAgaWYgKHRoaXMuX2NvbnRyYWN0Q291bnRlcikge1xuICAgICAgdHguZGVwbG95ZWRBZGRyZXNzID0gY2FsY3VsYXRlRm9yd2FyZGVyQWRkcmVzcyh0aGlzLl9jb250cmFjdEFkZHJlc3MsIHRoaXMuX2NvbnRyYWN0Q291bnRlcik7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3NhbHQgJiYgdGhpcy5faW5pdENvZGUpIHtcbiAgICAgIGNvbnN0IHNhbHRCdWZmZXIgPSBldGhVdGlsLnNldExlbmd0aExlZnQoZXRoVXRpbC50b0J1ZmZlcih0aGlzLl9zYWx0KSwgMzIpO1xuICAgICAgLy8gSGFzaCB0aGUgd2FsbGV0IGJhc2UgYWRkcmVzcyB3aXRoIHRoZSBnaXZlbiBzYWx0LCBzbyB0aGUgYWRkcmVzcyBkaXJlY3RseSByZWxpZXMgb24gdGhlIGJhc2UgYWRkcmVzc1xuICAgICAgY29uc3QgY2FsY3VsYXRpb25TYWx0ID0gZXRoVXRpbC5idWZmZXJUb0hleChcbiAgICAgICAgRXRoZXJldW1BYmkuc29saWRpdHlTSEEzKFsnYWRkcmVzcycsICdieXRlczMyJ10sIFt0aGlzLl9iYXNlQWRkcmVzcywgc2FsdEJ1ZmZlcl0pXG4gICAgICApO1xuICAgICAgdHguZGVwbG95ZWRBZGRyZXNzID0gY2FsY3VsYXRlRm9yd2FyZGVyVjFBZGRyZXNzKHRoaXMuX2NvbnRyYWN0QWRkcmVzcywgY2FsY3VsYXRpb25TYWx0LCB0aGlzLl9pbml0Q29kZSk7XG4gICAgfVxuICAgIHJldHVybiB0eDtcbiAgfVxuICAvLyBlbmRyZWdpb25cblxuICAvLyByZWdpb24gZmx1c2ggbWV0aG9kc1xuICAvKipcbiAgICogU2V0IHRoZSBmb3J3YXJkZXIgYWRkcmVzcyB0byBmbHVzaFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyBUaGUgYWRkcmVzcyB0byBmbHVzaFxuICAgKi9cbiAgZm9yd2FyZGVyQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fZm9yd2FyZGVyQWRkcmVzcyA9IGFkZHJlc3M7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBhZGRyZXNzIG9mIHRoZSBFUkMyMCB0b2tlbiBjb250cmFjdCB0aGF0IHdlIGFyZSBmbHVzaGluZyB0b2tlbnMgZm9yXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIHRoZSBjb250cmFjdCBhZGRyZXNzIG9mIHRoZSB0b2tlbiB0byBmbHVzaFxuICAgKi9cbiAgdG9rZW5BZGRyZXNzKGFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIGFkZHJlc3MpO1xuICAgIH1cbiAgICB0aGlzLl90b2tlbkFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgdHJhbnNhY3Rpb24gdG8gZmx1c2ggdG9rZW5zIGZyb20gYSBmb3J3YXJkZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIHtUeERhdGF9IFRoZSBFdGhlcmV1bSB0cmFuc2FjdGlvbiBkYXRhXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkRmx1c2hUb2tlbnNUcmFuc2FjdGlvbigpOiBUeERhdGEge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQmFzZShmbHVzaFRva2Vuc0RhdGEodGhpcy5fZm9yd2FyZGVyQWRkcmVzcywgdGhpcy5fdG9rZW5BZGRyZXNzKSk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSB0cmFuc2FjdGlvbiB0byBmbHVzaCB0b2tlbnMgZnJvbSBhIGZvcndhcmRlci5cbiAgICpcbiAgICogQHJldHVybnMge1R4RGF0YX0gVGhlIEV0aGVyZXVtIHRyYW5zYWN0aW9uIGRhdGFcbiAgICovXG4gIHByaXZhdGUgYnVpbGRGbHVzaENvaW5zVHJhbnNhY3Rpb24oKTogVHhEYXRhIHtcbiAgICByZXR1cm4gdGhpcy5idWlsZEJhc2UoZmx1c2hDb2luc0RhdGEoKSk7XG4gIH1cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIGdlbmVyaWMgY29udHJhY3QgY2FsbFxuICBkYXRhKGVuY29kZWRDYWxsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBzdXBwb3J0ZWRUcmFuc2FjdGlvblR5cGVzID0gW1RyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwsIFRyYW5zYWN0aW9uVHlwZS5SZWNvdmVyeVdhbGxldERlcGxveW1lbnRdO1xuICAgIGlmICghc3VwcG9ydGVkVHJhbnNhY3Rpb25UeXBlcy5pbmNsdWRlcyh0aGlzLl90eXBlKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignZGF0YSBjYW4gb25seSBiZSBzZXQgZm9yIGNvbnRyYWN0IGNhbGwgdHJhbnNhY3Rpb24gdHlwZXMnKTtcbiAgICB9XG4gICAgdGhpcy5fZGF0YSA9IGVuY29kZWRDYWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZEdlbmVyaWNDb250cmFjdENhbGxUcmFuc2FjdGlvbigpOiBUeERhdGEge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkQmFzZSh0aGlzLl9kYXRhKTtcbiAgfVxuICAvLyBlbmRyZWdpb25cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIGdldCB0cmFuc2FjdGlvbigpOiBUcmFuc2FjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX3RyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHByb3RlY3RlZCBzZXQgdHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKSB7XG4gICAgdGhpcy5fdHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGZpbmFsIHYgdmFsdWUuIEZpbmFsIHYgaXMgZGVzY3JpYmVkIGluIEVJUC0xNTUuXG4gICAqXG4gICAqIEBwcm90ZWN0ZWQgZm9yIGludGVybmFsIHVzZSB3aGVuIHRoZSBlbmFibGVGaW5hbFZGaWVsZCBmbGFnIGlzIHRydWUuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0RmluYWxWKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGV0aFV0aWwuYWRkSGV4UHJlZml4KHRoaXMuX2NvbW1vbi5jaGFpbklkQk4oKS5tdWxuKDIpLmFkZG4oMzUpLnRvU3RyaW5nKDE2KSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBmb3J3YXJkZXIgdmVyc2lvbiBmb3IgYWRkcmVzcyB0byBiZSBpbml0aWFsaXplZFxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gdmVyc2lvbiBmb3J3YXJkZXIgdmVyc2lvblxuICAgKi9cbiAgZm9yd2FyZGVyVmVyc2lvbih2ZXJzaW9uOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodmVyc2lvbiA8IDAgfHwgdmVyc2lvbiA+IDIpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgZm9yd2FyZGVyIHZlcnNpb246ICR7dmVyc2lvbn1gKTtcbiAgICB9XG5cbiAgICB0aGlzLl9mb3J3YXJkZXJWZXJzaW9uID0gdmVyc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIHNhbHQgdG8gY3JlYXRlIHRoZSBhZGRyZXNzIHVzaW5nIGNyZWF0ZTJcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHNhbHQgVGhlIHNhbHQgdG8gY3JlYXRlIHRoZSBhZGRyZXNzIHVzaW5nIGNyZWF0ZTIsIGhleCBzdHJpbmdcbiAgICovXG4gIHNhbHQoc2FsdDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5fc2FsdCA9IHNhbHQ7XG4gIH1cblxuICAvKipcbiAgICogVGFrZSB0aGUgaW1wbGVtZW50YXRpb24gYWRkcmVzcyBmb3IgdGhlIHByb3h5IGNvbnRyYWN0LCBhbmQgZ2V0IHRoZSBiaW5hcnkgaW5pdGNvZGUgZm9yIHRoZSBhc3NvY2lhdGVkIHByb3h5XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpbXBsZW1lbnRhdGlvbkFkZHJlc3MgVGhlIGFkZHJlc3Mgb2YgdGhlIGltcGxlbWVudGF0aW9uIGNvbnRyYWN0XG4gICAqL1xuICBpbml0Q29kZShpbXBsZW1lbnRhdGlvbkFkZHJlc3M6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghaXNWYWxpZEV0aEFkZHJlc3MoaW1wbGVtZW50YXRpb25BZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBhZGRyZXNzOiAnICsgaW1wbGVtZW50YXRpb25BZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5faW5pdENvZGUgPSBnZXRQcm94eUluaXRjb2RlKGltcGxlbWVudGF0aW9uQWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB3YWxsZXQgdmVyc2lvbiBmb3Igd2FsbGV0IHRvIGJlIGluaXRpYWxpemVkXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB2ZXJzaW9uIHdhbGxldCB2ZXJzaW9uXG4gICAqL1xuICB3YWxsZXRWZXJzaW9uKHZlcnNpb246IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh2ZXJzaW9uIDwgMCB8fCB2ZXJzaW9uID4gMykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB3YWxsZXQgdmVyc2lvbjogJHt2ZXJzaW9ufWApO1xuICAgIH1cblxuICAgIHRoaXMuX3dhbGxldFZlcnNpb24gPSB2ZXJzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgYmFzZSBhZGRyZXNzIG9mIHRoZSB3YWxsZXRcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgVGhlIHdhbGxldCBjb250cmFjdCBhZGRyZXNzXG4gICAqL1xuICBiYXNlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWlzVmFsaWRFdGhBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3M6ICcgKyBhZGRyZXNzKTtcbiAgICB9XG4gICAgdGhpcy5fYmFzZUFkZHJlc3MgPSBhZGRyZXNzO1xuICB9XG59XG4iXX0=