@bitgo-beta/abstract-eth 1.2.3-alpha.38 → 1.2.3-alpha.381

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