@bitgo-beta/abstract-eth 1.0.2-beta.49 → 1.0.2-beta.490

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 +1150 -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 +131 -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 +239 -0
  30. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  31. package/dist/src/lib/transactionBuilder.js +708 -0
  32. package/dist/src/lib/transferBuilder.d.ts +67 -0
  33. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  34. package/dist/src/lib/transferBuilder.js +242 -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 +252 -0
  51. package/dist/src/lib/utils.d.ts.map +1 -0
  52. package/dist/src/lib/utils.js +628 -0
  53. package/dist/src/lib/walletUtil.d.ts +28 -0
  54. package/dist/src/lib/walletUtil.d.ts.map +1 -0
  55. package/dist/src/lib/walletUtil.js +31 -0
  56. package/dist/tsconfig.tsbuildinfo +1 -7896
  57. package/package.json +23 -9
@@ -0,0 +1,628 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.decodeForwarderCreationData = exports.getCreateForwarderParamsAndTypes = exports.getAddressInitDataAllForwarderVersions = exports.getV1AddressInitializationData = exports.getV1WalletInitializationData = exports.getToken = exports.getBufferedByteCode = exports.getRawDecoded = exports.hasSignature = exports.toStringSig = exports.getProxyInitcode = exports.calculateForwarderV1Address = exports.calculateForwarderAddress = exports.hexStringToNumber = exports.numberToHexString = exports.classifyTransaction = exports.decodeFlushTokensData = exports.decodeNativeTransferData = exports.decodeERC1155TransferData = exports.decodeERC721TransferData = exports.decodeTokenTransferData = exports.decodeTransferData = exports.decodeWalletCreationData = exports.isValidAmount = exports.isValidEthAddress = exports.getAddressInitializationData = exports.flushCoinsData = exports.flushTokensData = exports.sendMultiSigTokenData = exports.sendMultiSigData = exports.sign = exports.signInternal = exports.getCommon = void 0;
7
+ const buffer_1 = require("buffer");
8
+ const assert_1 = __importDefault(require("assert"));
9
+ const ethereumjs_util_1 = require("ethereumjs-util");
10
+ const statics_1 = require("@bitgo-beta/statics");
11
+ const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
12
+ const common_1 = __importDefault(require("@ethereumjs/common"));
13
+ const bn_js_1 = __importDefault(require("bn.js"));
14
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
15
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
16
+ const walletUtil_1 = require("./walletUtil");
17
+ const types_1 = require("./types");
18
+ /**
19
+ * @param network
20
+ */
21
+ function getCommon(network) {
22
+ return common_1.default.forCustomChain(
23
+ // use the mainnet config as a base, override chain ids and network name
24
+ 'mainnet', {
25
+ name: network.type,
26
+ networkId: network.chainId,
27
+ chainId: network.chainId,
28
+ }, 'london');
29
+ }
30
+ exports.getCommon = getCommon;
31
+ /**
32
+ * Signs the transaction using the appropriate algorithm
33
+ * and the provided common for the blockchain
34
+ *
35
+ * @param {TxData} transactionData the transaction data to sign
36
+ * @param {KeyPair} keyPair the signer's keypair
37
+ * @param {EthereumCommon} customCommon the network's custom common
38
+ * @returns {string} the transaction signed and encoded
39
+ */
40
+ async function signInternal(transactionData, keyPair, customCommon) {
41
+ if (!keyPair.getKeys().prv) {
42
+ throw new sdk_core_1.SigningError('Missing private key');
43
+ }
44
+ const ethTx = types_1.EthTransactionData.fromJson(transactionData, customCommon);
45
+ ethTx.sign(keyPair);
46
+ return ethTx.toSerialized();
47
+ }
48
+ exports.signInternal = signInternal;
49
+ /**
50
+ * Signs the transaction using the appropriate algorithm
51
+ *
52
+ * @param {TxData} transactionData the transaction data to sign
53
+ * @param {KeyPair} keyPair the signer's keypair
54
+ * @returns {string} the transaction signed and encoded
55
+ */
56
+ async function sign(transactionData, keyPair) {
57
+ return signInternal(transactionData, keyPair, getCommon(statics_1.coins.get('teth').network));
58
+ }
59
+ exports.sign = sign;
60
+ /**
61
+ * Returns the contract method encoded data
62
+ *
63
+ * @param {string} to destination address
64
+ * @param {number} value Amount to tranfer
65
+ * @param {string} data aditional method call data
66
+ * @param {number} expireTime expiration time for the transaction in seconds
67
+ * @param {number} sequenceId sequence id
68
+ * @param {string} signature signature of the call
69
+ * @returns {string} -- the contract method encoded data
70
+ */
71
+ function sendMultiSigData(to, value, data, expireTime, sequenceId, signature) {
72
+ const params = [to, value, ethereumjs_util_1.toBuffer(data), expireTime, sequenceId, ethereumjs_util_1.toBuffer(signature)];
73
+ const method = ethereumjs_abi_1.default.methodID('sendMultiSig', walletUtil_1.sendMultiSigTypes);
74
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.sendMultiSigTypes, params);
75
+ return ethereumjs_util_1.addHexPrefix(buffer_1.Buffer.concat([method, args]).toString('hex'));
76
+ }
77
+ exports.sendMultiSigData = sendMultiSigData;
78
+ /**
79
+ * Returns the contract method encoded data
80
+ *
81
+ * @param {string} to destination address
82
+ * @param {number} value Amount to tranfer
83
+ * @param {string} tokenContractAddress the address of the erc20 token contract
84
+ * @param {number} expireTime expiration time for the transaction in seconds
85
+ * @param {number} sequenceId sequence id
86
+ * @param {string} signature signature of the call
87
+ * @returns {string} -- the contract method encoded data
88
+ */
89
+ function sendMultiSigTokenData(to, value, tokenContractAddress, expireTime, sequenceId, signature) {
90
+ const params = [to, value, tokenContractAddress, expireTime, sequenceId, ethereumjs_util_1.toBuffer(signature)];
91
+ const method = ethereumjs_abi_1.default.methodID('sendMultiSigToken', walletUtil_1.sendMultiSigTokenTypes);
92
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.sendMultiSigTokenTypes, params);
93
+ return ethereumjs_util_1.addHexPrefix(buffer_1.Buffer.concat([method, args]).toString('hex'));
94
+ }
95
+ exports.sendMultiSigTokenData = sendMultiSigTokenData;
96
+ /**
97
+ * Get the data required to make a flush tokens contract call
98
+ *
99
+ * @param forwarderAddress The forwarder address to flush
100
+ * @param tokenAddress The token address to flush from
101
+ */
102
+ function flushTokensData(forwarderAddress, tokenAddress) {
103
+ const params = [forwarderAddress, tokenAddress];
104
+ const method = ethereumjs_abi_1.default.methodID('flushForwarderTokens', walletUtil_1.flushTokensTypes);
105
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushTokensTypes, params);
106
+ return ethereumjs_util_1.addHexPrefix(buffer_1.Buffer.concat([method, args]).toString('hex'));
107
+ }
108
+ exports.flushTokensData = flushTokensData;
109
+ /**
110
+ * Get the data required to make a flush native coins contract call
111
+ */
112
+ function flushCoinsData() {
113
+ const params = [];
114
+ const method = ethereumjs_abi_1.default.methodID('flush', walletUtil_1.flushCoinsTypes);
115
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushCoinsTypes, params);
116
+ return ethereumjs_util_1.addHexPrefix(buffer_1.Buffer.concat([method, args]).toString('hex'));
117
+ }
118
+ exports.flushCoinsData = flushCoinsData;
119
+ /**
120
+ * Returns the create forwarder method calling data
121
+ *
122
+ * @returns {string} - the createForwarder method encoded
123
+ */
124
+ function getAddressInitializationData() {
125
+ return walletUtil_1.createForwarderMethodId;
126
+ }
127
+ exports.getAddressInitializationData = getAddressInitializationData;
128
+ /**
129
+ * Returns whether or not the string is a valid Eth address
130
+ *
131
+ * @param {string} address - the tx hash to validate
132
+ * @returns {boolean} - the validation result
133
+ */
134
+ function isValidEthAddress(address) {
135
+ return ethereumjs_util_1.isValidAddress(address);
136
+ }
137
+ exports.isValidEthAddress = isValidEthAddress;
138
+ /**
139
+ * Returns whether or not the string is a valid amount number
140
+ *
141
+ * @param {string} amount - the string to validate
142
+ * @returns {boolean} - the validation result
143
+ */
144
+ function isValidAmount(amount) {
145
+ const bigNumberAmount = new bignumber_js_1.default(amount);
146
+ return bigNumberAmount.isInteger() && bigNumberAmount.isGreaterThanOrEqualTo(0);
147
+ }
148
+ exports.isValidAmount = isValidAmount;
149
+ /**
150
+ * Returns the smart contract encoded data
151
+ *
152
+ * @param {string} data The wallet creation data to decode
153
+ * @returns {string[]} - The list of signer addresses
154
+ */
155
+ function decodeWalletCreationData(data) {
156
+ if (!(data.startsWith(walletUtil_1.walletInitializationFirstBytes) || data.startsWith(walletUtil_1.v1CreateWalletMethodId))) {
157
+ throw new sdk_core_1.BuildTransactionError(`Invalid wallet bytecode: ${data}`);
158
+ }
159
+ if (data.startsWith(walletUtil_1.walletInitializationFirstBytes)) {
160
+ const dataBuffer = buffer_1.Buffer.from(data.slice(2), 'hex');
161
+ // the last 160 bytes contain the serialized address array
162
+ const serializedSigners = dataBuffer.slice(-160);
163
+ const resultEncodedParameters = ethereumjs_abi_1.default.rawDecode(walletUtil_1.walletSimpleConstructor, serializedSigners);
164
+ if (resultEncodedParameters.length !== 1) {
165
+ throw new sdk_core_1.BuildTransactionError(`Could not decode wallet constructor bytecode: ${resultEncodedParameters}`);
166
+ }
167
+ const addresses = resultEncodedParameters[0];
168
+ if (addresses.length !== 3) {
169
+ throw new sdk_core_1.BuildTransactionError(`invalid number of addresses in parsed constructor: ${addresses}`);
170
+ }
171
+ // sometimes ethereumjs-abi removes 0 padding at the start of addresses,
172
+ // so we should pad until they are the standard 20 bytes
173
+ const paddedAddresses = addresses.map((address) => ethereumjs_util_1.stripHexPrefix(address.toString('hex')).padStart(40, '0'));
174
+ return { owners: paddedAddresses.map((address) => ethereumjs_util_1.addHexPrefix(address)) };
175
+ }
176
+ else {
177
+ const decodedDataForWalletCreation = getRawDecoded(walletUtil_1.createV1WalletTypes, getBufferedByteCode(walletUtil_1.v1CreateWalletMethodId, data));
178
+ const addresses = decodedDataForWalletCreation[0];
179
+ const saltBuffer = decodedDataForWalletCreation[1];
180
+ const salt = ethereumjs_util_1.bufferToHex(saltBuffer);
181
+ const paddedAddresses = addresses.map((address) => ethereumjs_util_1.stripHexPrefix(address.toString()).padStart(40, '0'));
182
+ const owners = paddedAddresses.map((address) => ethereumjs_util_1.addHexPrefix(address));
183
+ return {
184
+ owners,
185
+ salt,
186
+ };
187
+ }
188
+ }
189
+ exports.decodeWalletCreationData = decodeWalletCreationData;
190
+ /**
191
+ * Decode the given ABI-encoded transfer data and return parsed fields
192
+ *
193
+ * @param data The data to decode
194
+ * @returns parsed transfer data
195
+ */
196
+ function decodeTransferData(data) {
197
+ if (data.startsWith(walletUtil_1.sendMultisigMethodId)) {
198
+ return decodeNativeTransferData(data);
199
+ }
200
+ else if (data.startsWith(walletUtil_1.sendMultisigTokenMethodId)) {
201
+ return decodeTokenTransferData(data);
202
+ }
203
+ else {
204
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
205
+ }
206
+ }
207
+ exports.decodeTransferData = decodeTransferData;
208
+ /**
209
+ * Decode the given ABI-encoded transfer data for the sendMultisigToken function and return parsed fields
210
+ *
211
+ * @param data The data to decode
212
+ * @returns parsed token transfer data
213
+ */
214
+ function decodeTokenTransferData(data) {
215
+ if (!data.startsWith(walletUtil_1.sendMultisigTokenMethodId)) {
216
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
217
+ }
218
+ const [to, amount, tokenContractAddress, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTokenTypes, getBufferedByteCode(walletUtil_1.sendMultisigTokenMethodId, data));
219
+ return {
220
+ to: ethereumjs_util_1.addHexPrefix(to),
221
+ amount: new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(amount)).toFixed(),
222
+ expireTime: ethereumjs_util_1.bufferToInt(expireTime),
223
+ sequenceId: ethereumjs_util_1.bufferToInt(sequenceId),
224
+ signature: ethereumjs_util_1.bufferToHex(signature),
225
+ tokenContractAddress: ethereumjs_util_1.addHexPrefix(tokenContractAddress),
226
+ };
227
+ }
228
+ exports.decodeTokenTransferData = decodeTokenTransferData;
229
+ function decodeERC721TransferData(data) {
230
+ if (!data.startsWith(walletUtil_1.sendMultisigMethodId)) {
231
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
232
+ }
233
+ const [to, amount, internalData, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTypes, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
234
+ const internalDataHex = ethereumjs_util_1.bufferToHex(internalData);
235
+ if (!internalDataHex.startsWith(walletUtil_1.ERC721SafeTransferTypeMethodId)) {
236
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
237
+ }
238
+ const [from, receiver, tokenId, userSentData] = getRawDecoded(walletUtil_1.ERC721SafeTransferTypes, getBufferedByteCode(walletUtil_1.ERC721SafeTransferTypeMethodId, internalDataHex));
239
+ return {
240
+ to: ethereumjs_util_1.addHexPrefix(receiver),
241
+ from: ethereumjs_util_1.addHexPrefix(from),
242
+ expireTime: ethereumjs_util_1.bufferToInt(expireTime),
243
+ amount: new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(amount)).toFixed(),
244
+ tokenId: new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(tokenId)).toFixed(),
245
+ sequenceId: ethereumjs_util_1.bufferToInt(sequenceId),
246
+ signature: ethereumjs_util_1.bufferToHex(signature),
247
+ tokenContractAddress: ethereumjs_util_1.addHexPrefix(to),
248
+ userData: ethereumjs_util_1.bufferToHex(userSentData),
249
+ };
250
+ }
251
+ exports.decodeERC721TransferData = decodeERC721TransferData;
252
+ function decodeERC1155TransferData(data) {
253
+ let from, receiver, userSentData;
254
+ let tokenIds;
255
+ let values;
256
+ if (!data.startsWith(walletUtil_1.sendMultisigMethodId)) {
257
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
258
+ }
259
+ const [to, amount, internalData, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTypes, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
260
+ const internalDataHex = ethereumjs_util_1.bufferToHex(internalData);
261
+ if (internalDataHex.startsWith(walletUtil_1.ERC1155SafeTransferTypeMethodId)) {
262
+ let tokenId;
263
+ let value;
264
+ [from, receiver, tokenId, value, userSentData] = getRawDecoded(walletUtil_1.ERC1155SafeTransferTypes, getBufferedByteCode(walletUtil_1.ERC1155SafeTransferTypeMethodId, internalDataHex));
265
+ tokenIds = [new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(tokenId)).toFixed()];
266
+ values = [new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(value)).toFixed()];
267
+ }
268
+ else if (ethereumjs_util_1.bufferToHex(internalData).startsWith(walletUtil_1.ERC1155BatchTransferTypeMethodId)) {
269
+ let tempTokenIds, tempValues;
270
+ [from, receiver, tempTokenIds, tempValues, userSentData] = getRawDecoded(walletUtil_1.ERC1155BatchTransferTypes, getBufferedByteCode(walletUtil_1.ERC1155BatchTransferTypeMethodId, internalDataHex));
271
+ tokenIds = tempTokenIds.map((x) => new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(x)).toFixed());
272
+ values = tempValues.map((x) => new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(x)).toFixed());
273
+ }
274
+ else {
275
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
276
+ }
277
+ return {
278
+ to: ethereumjs_util_1.addHexPrefix(receiver),
279
+ from: ethereumjs_util_1.addHexPrefix(from),
280
+ expireTime: ethereumjs_util_1.bufferToInt(expireTime),
281
+ amount: new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(amount)).toFixed(),
282
+ tokenIds,
283
+ values,
284
+ sequenceId: ethereumjs_util_1.bufferToInt(sequenceId),
285
+ signature: ethereumjs_util_1.bufferToHex(signature),
286
+ tokenContractAddress: ethereumjs_util_1.addHexPrefix(to),
287
+ userData: userSentData,
288
+ };
289
+ }
290
+ exports.decodeERC1155TransferData = decodeERC1155TransferData;
291
+ /**
292
+ * Decode the given ABI-encoded transfer data for the sendMultisig function and return parsed fields
293
+ *
294
+ * @param data The data to decode
295
+ * @returns parsed transfer data
296
+ */
297
+ function decodeNativeTransferData(data) {
298
+ if (!data.startsWith(walletUtil_1.sendMultisigMethodId)) {
299
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
300
+ }
301
+ const [to, amount, internalData, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTypes, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
302
+ return {
303
+ to: ethereumjs_util_1.addHexPrefix(to),
304
+ amount: new bignumber_js_1.default(ethereumjs_util_1.bufferToHex(amount)).toFixed(),
305
+ expireTime: ethereumjs_util_1.bufferToInt(expireTime),
306
+ sequenceId: ethereumjs_util_1.bufferToInt(sequenceId),
307
+ signature: ethereumjs_util_1.bufferToHex(signature),
308
+ data: ethereumjs_util_1.bufferToHex(internalData),
309
+ };
310
+ }
311
+ exports.decodeNativeTransferData = decodeNativeTransferData;
312
+ /**
313
+ * Decode the given ABI-encoded flush tokens data and return parsed fields
314
+ *
315
+ * @param data The data to decode
316
+ * @returns parsed transfer data
317
+ */
318
+ function decodeFlushTokensData(data) {
319
+ if (!data.startsWith(walletUtil_1.flushForwarderTokensMethodId)) {
320
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
321
+ }
322
+ const [forwarderAddress, tokenAddress] = getRawDecoded(walletUtil_1.flushTokensTypes, getBufferedByteCode(walletUtil_1.flushForwarderTokensMethodId, data));
323
+ return {
324
+ forwarderAddress: ethereumjs_util_1.addHexPrefix(forwarderAddress),
325
+ tokenAddress: ethereumjs_util_1.addHexPrefix(tokenAddress),
326
+ };
327
+ }
328
+ exports.decodeFlushTokensData = decodeFlushTokensData;
329
+ /**
330
+ * Classify the given transaction data based as a transaction type.
331
+ * ETH transactions are defined by the first 8 bytes of the transaction data, also known as the method id
332
+ *
333
+ * @param {string} data The data to classify the transaction with
334
+ * @returns {TransactionType} The classified transaction type
335
+ */
336
+ function classifyTransaction(data) {
337
+ if (data.length < 10) {
338
+ // contract calls must have at least 4 bytes (method id) and '0x'
339
+ // if it doesn't have enough data to be a contract call it must be a single sig send
340
+ return sdk_core_1.TransactionType.SingleSigSend;
341
+ }
342
+ // TODO(STLX-1970): validate if we are going to constraint to some methods allowed
343
+ let transactionType = transactionTypesMap[data.slice(0, 10).toLowerCase()];
344
+ if (transactionType === undefined) {
345
+ transactionType = sdk_core_1.TransactionType.ContractCall;
346
+ }
347
+ return transactionType;
348
+ }
349
+ exports.classifyTransaction = classifyTransaction;
350
+ /**
351
+ * A transaction types map according to the starting part of the encoded data
352
+ */
353
+ const transactionTypesMap = {
354
+ [walletUtil_1.walletInitializationFirstBytes]: sdk_core_1.TransactionType.WalletInitialization,
355
+ [walletUtil_1.recoveryWalletInitializationFirstBytes]: sdk_core_1.TransactionType.RecoveryWalletDeployment,
356
+ [walletUtil_1.v1CreateWalletMethodId]: sdk_core_1.TransactionType.WalletInitialization,
357
+ [walletUtil_1.createForwarderMethodId]: sdk_core_1.TransactionType.AddressInitialization,
358
+ [walletUtil_1.v1CreateForwarderMethodId]: sdk_core_1.TransactionType.AddressInitialization,
359
+ [walletUtil_1.v4CreateForwarderMethodId]: sdk_core_1.TransactionType.AddressInitialization,
360
+ [walletUtil_1.sendMultisigMethodId]: sdk_core_1.TransactionType.Send,
361
+ [walletUtil_1.flushForwarderTokensMethodId]: sdk_core_1.TransactionType.FlushTokens,
362
+ [walletUtil_1.flushCoinsMethodId]: sdk_core_1.TransactionType.FlushCoins,
363
+ [walletUtil_1.sendMultisigTokenMethodId]: sdk_core_1.TransactionType.Send,
364
+ [sdk_core_1.LockMethodId]: sdk_core_1.TransactionType.StakingLock,
365
+ [sdk_core_1.VoteMethodId]: sdk_core_1.TransactionType.StakingVote,
366
+ [sdk_core_1.ActivateMethodId]: sdk_core_1.TransactionType.StakingActivate,
367
+ [sdk_core_1.UnvoteMethodId]: sdk_core_1.TransactionType.StakingUnvote,
368
+ [sdk_core_1.UnlockMethodId]: sdk_core_1.TransactionType.StakingUnlock,
369
+ [sdk_core_1.WithdrawMethodId]: sdk_core_1.TransactionType.StakingWithdraw,
370
+ };
371
+ /**
372
+ *
373
+ * @param {number} num number to be converted to hex
374
+ * @returns {string} the hex number
375
+ */
376
+ function numberToHexString(num) {
377
+ const hex = num.toString(16);
378
+ return hex.length % 2 === 0 ? '0x' + hex : '0x0' + hex;
379
+ }
380
+ exports.numberToHexString = numberToHexString;
381
+ /**
382
+ *
383
+ * @param {string} hex The hex string to be converted
384
+ * @returns {number} the resulting number
385
+ */
386
+ function hexStringToNumber(hex) {
387
+ return parseInt(hex.slice(2), 16);
388
+ }
389
+ exports.hexStringToNumber = hexStringToNumber;
390
+ /**
391
+ * Generates an address of the forwarder address to be deployed
392
+ *
393
+ * @param {string} contractAddress the address which is creating this new address
394
+ * @param {number} contractCounter the nonce of the contract address
395
+ * @returns {string} the calculated forwarder contract address
396
+ */
397
+ function calculateForwarderAddress(contractAddress, contractCounter) {
398
+ const forwarderAddress = ethereumjs_util_1.generateAddress(buffer_1.Buffer.from(ethereumjs_util_1.stripHexPrefix(contractAddress), 'hex'), buffer_1.Buffer.from(ethereumjs_util_1.padToEven(ethereumjs_util_1.stripHexPrefix(numberToHexString(contractCounter))), 'hex'));
399
+ return ethereumjs_util_1.addHexPrefix(forwarderAddress.toString('hex'));
400
+ }
401
+ exports.calculateForwarderAddress = calculateForwarderAddress;
402
+ /**
403
+ * Calculate the forwarder v1 address that will be generated if `creatorAddress` creates it with salt `salt`
404
+ * and initcode `inicode using the create2 opcode
405
+ * @param {string} creatorAddress The address that is sending the tx to create a new address, hex string
406
+ * @param {string} salt The salt to create the address with using create2, hex string
407
+ * @param {string} initcode The initcode that will be deployed to the address, hex string
408
+ * @return {string} The calculated address
409
+ */
410
+ function calculateForwarderV1Address(creatorAddress, salt, initcode) {
411
+ const forwarderV1Address = ethereumjs_util_1.generateAddress2(buffer_1.Buffer.from(ethereumjs_util_1.stripHexPrefix(creatorAddress), 'hex'), buffer_1.Buffer.from(ethereumjs_util_1.stripHexPrefix(salt), 'hex'), buffer_1.Buffer.from(ethereumjs_util_1.padToEven(ethereumjs_util_1.stripHexPrefix(initcode)), 'hex'));
412
+ return ethereumjs_util_1.addHexPrefix(forwarderV1Address.toString('hex'));
413
+ }
414
+ exports.calculateForwarderV1Address = calculateForwarderV1Address;
415
+ /**
416
+ * Take the implementation address for the proxy contract, and get the binary initcode for the associated proxy
417
+ * @param {string} implementationAddress The address of the implementation contract for the proxy
418
+ * @return {string} Binary hex string of the proxy
419
+ */
420
+ function getProxyInitcode(implementationAddress) {
421
+ const target = ethereumjs_util_1.stripHexPrefix(implementationAddress.toLowerCase()).padStart(40, '0');
422
+ // bytecode of the proxy, from:
423
+ // https://github.com/BitGo/eth-multisig-v4/blob/d546a937f90f93e83b3423a5bf933d1d77c677c3/contracts/CloneFactory.sol#L42-L56
424
+ return `0x3d602d80600a3d3981f3363d3d373d3d3d363d73${target}5af43d82803e903d91602b57fd5bf3`;
425
+ }
426
+ exports.getProxyInitcode = getProxyInitcode;
427
+ /**
428
+ * Convert the given signature parts to a string representation
429
+ *
430
+ * @param {SignatureParts} sig The signature to convert to string
431
+ * @returns {string} String representation of the signature
432
+ */
433
+ function toStringSig(sig) {
434
+ return ethereumjs_util_1.bufferToHex(buffer_1.Buffer.concat([
435
+ ethereumjs_util_1.setLengthLeft(buffer_1.Buffer.from(ethereumjs_util_1.stripHexPrefix(sig.r), 'hex'), 32),
436
+ ethereumjs_util_1.setLengthLeft(buffer_1.Buffer.from(ethereumjs_util_1.stripHexPrefix(sig.s), 'hex'), 32),
437
+ ethereumjs_util_1.toBuffer(sig.v),
438
+ ]));
439
+ }
440
+ exports.toStringSig = toStringSig;
441
+ /**
442
+ * Return whether or not the given tx data has a signature
443
+ *
444
+ * @param {TxData} txData The transaction data to check for signature
445
+ * @returns {boolean} true if the tx has a signature, else false
446
+ */
447
+ function hasSignature(txData) {
448
+ return (txData.v !== undefined &&
449
+ txData.r !== undefined &&
450
+ txData.s !== undefined &&
451
+ txData.v.length > 0 &&
452
+ txData.r.length > 0 &&
453
+ txData.s.length > 0);
454
+ }
455
+ exports.hasSignature = hasSignature;
456
+ /**
457
+ * Get the raw data decoded for some types
458
+ *
459
+ * @param {string[]} types ABI types definition
460
+ * @param {Buffer} serializedArgs encoded args
461
+ * @returns {Buffer[]} the decoded raw
462
+ */
463
+ function getRawDecoded(types, serializedArgs) {
464
+ function normalize(v, i) {
465
+ if (bn_js_1.default.isBN(v)) {
466
+ return v;
467
+ }
468
+ else if (typeof v === 'string' || buffer_1.Buffer.isBuffer(v)) {
469
+ return v;
470
+ }
471
+ else if (Array.isArray(v)) {
472
+ return v.map(normalize);
473
+ }
474
+ else {
475
+ throw new Error(`For ${types}[${i}] got ${typeof v}`);
476
+ }
477
+ }
478
+ return ethereumjs_abi_1.default.rawDecode(types, serializedArgs).map(normalize);
479
+ }
480
+ exports.getRawDecoded = getRawDecoded;
481
+ /**
482
+ * Get the buffered bytecode from rawData using a methodId as delimiter
483
+ *
484
+ * @param {string} methodId the hex encoded method Id
485
+ * @param {string} rawData the hex encoded raw data
486
+ * @returns {Buffer} data buffered bytecode
487
+ */
488
+ function getBufferedByteCode(methodId, rawData) {
489
+ const splitBytecode = rawData.split(methodId);
490
+ if (splitBytecode.length !== 2) {
491
+ throw new sdk_core_1.BuildTransactionError(`Invalid send bytecode: ${rawData}`);
492
+ }
493
+ if (splitBytecode[1].length % 2 !== 0) {
494
+ throw new sdk_core_1.BuildTransactionError(`Invalid send bytecode: ${rawData} (wrong lenght)`);
495
+ }
496
+ return buffer_1.Buffer.from(splitBytecode[1], 'hex');
497
+ }
498
+ exports.getBufferedByteCode = getBufferedByteCode;
499
+ /**
500
+ * Get the statics coin object matching a given contract address if it exists
501
+ *
502
+ * @param tokenContractAddress The contract address to match against
503
+ * @returns statics BaseCoin object for the matching token
504
+ */
505
+ function getToken(tokenContractAddress, network) {
506
+ const tokens = statics_1.coins.filter((coin) => {
507
+ if (coin instanceof statics_1.ContractAddressDefinedToken) {
508
+ return (coin.network.type === network.type && coin.contractAddress.toLowerCase() === tokenContractAddress.toLowerCase());
509
+ }
510
+ return false;
511
+ });
512
+ // if length of tokens is 1, return the first, else return undefined
513
+ // Can't directly index into tokens, or call `length`, so we use map to get an array
514
+ const tokensArray = tokens.map((token) => token);
515
+ if (tokensArray.length >= 1) {
516
+ // there should never be two tokens with the same contract address, so we assert that here
517
+ assert_1.default(tokensArray.length === 1);
518
+ return tokensArray[0];
519
+ }
520
+ return undefined;
521
+ }
522
+ exports.getToken = getToken;
523
+ /**
524
+ * Returns the create wallet method calling data for v1 wallets
525
+ *
526
+ * @param {string[]} walletOwners - wallet owner addresses for wallet initialization transactions
527
+ * @param {string} salt - The salt for wallet initialization transactions
528
+ * @returns {string} - the createWallet method encoded
529
+ */
530
+ function getV1WalletInitializationData(walletOwners, salt) {
531
+ const saltBuffer = ethereumjs_util_1.setLengthLeft(ethereumjs_util_1.toBuffer(salt), 32);
532
+ const params = [walletOwners, saltBuffer];
533
+ const method = ethereumjs_abi_1.default.methodID('createWallet', walletUtil_1.createV1WalletTypes);
534
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.createV1WalletTypes, params);
535
+ return ethereumjs_util_1.addHexPrefix(buffer_1.Buffer.concat([method, args]).toString('hex'));
536
+ }
537
+ exports.getV1WalletInitializationData = getV1WalletInitializationData;
538
+ /**
539
+ * Returns the create address method calling data for v1, v2, v4 forwarders
540
+ *
541
+ * @param {string} baseAddress - The address of the wallet contract
542
+ * @param {string} salt - The salt for address initialization transactions
543
+ * @param {string} feeAddress - The fee address for the enterprise
544
+ * @returns {string} - the createForwarder method encoded
545
+ */
546
+ function getV1AddressInitializationData(baseAddress, salt, feeAddress) {
547
+ const saltBuffer = ethereumjs_util_1.setLengthLeft(ethereumjs_util_1.toBuffer(salt), 32);
548
+ const { createForwarderParams, createForwarderTypes } = getCreateForwarderParamsAndTypes(baseAddress, saltBuffer, feeAddress);
549
+ const method = ethereumjs_abi_1.default.methodID('createForwarder', createForwarderTypes);
550
+ const args = ethereumjs_abi_1.default.rawEncode(createForwarderTypes, createForwarderParams);
551
+ return ethereumjs_util_1.addHexPrefix(buffer_1.Buffer.concat([method, args]).toString('hex'));
552
+ }
553
+ exports.getV1AddressInitializationData = getV1AddressInitializationData;
554
+ /**
555
+ * Returns the create address method calling data for all forwarder versions
556
+ *
557
+ * @param {number} forwarderVersion - The version of the forwarder to create
558
+ * @param {string} baseAddress - The address of the wallet contract
559
+ * @param {string} salt - The salt for address initialization transactions
560
+ * @param {string} feeAddress - The fee address for the enterprise
561
+ * @returns {string} - the createForwarder method encoded
562
+ *
563
+ */
564
+ function getAddressInitDataAllForwarderVersions(forwarderVersion, baseAddress, salt, feeAddress) {
565
+ if (forwarderVersion === walletUtil_1.defaultForwarderVersion) {
566
+ return getAddressInitializationData();
567
+ }
568
+ else {
569
+ return getV1AddressInitializationData(baseAddress, salt, feeAddress);
570
+ }
571
+ }
572
+ exports.getAddressInitDataAllForwarderVersions = getAddressInitDataAllForwarderVersions;
573
+ /**
574
+ * Returns the createForwarderTypes and createForwarderParams for all forwarder versions
575
+ *
576
+ * @param {string} baseAddress - The address of the wallet contract
577
+ * @param {Buffer} saltBuffer - The salt for address initialization transaction
578
+ * @param {string} feeAddress - The fee address for the enterprise
579
+ * @returns {createForwarderParams: (string | Buffer)[], createForwarderTypes: string[]}
580
+ */
581
+ function getCreateForwarderParamsAndTypes(baseAddress, saltBuffer, feeAddress) {
582
+ let createForwarderParams = [baseAddress, saltBuffer];
583
+ let createForwarderTypes = walletUtil_1.createV1ForwarderTypes;
584
+ if (feeAddress) {
585
+ createForwarderParams = [baseAddress, feeAddress, saltBuffer];
586
+ createForwarderTypes = walletUtil_1.createV4ForwarderTypes;
587
+ }
588
+ return { createForwarderParams, createForwarderTypes };
589
+ }
590
+ exports.getCreateForwarderParamsAndTypes = getCreateForwarderParamsAndTypes;
591
+ /**
592
+ * Decode the given ABI-encoded create forwarder data and return parsed fields
593
+ *
594
+ * @param data The data to decode
595
+ * @returns parsed transfer data
596
+ */
597
+ function decodeForwarderCreationData(data) {
598
+ if (!(data.startsWith(walletUtil_1.v4CreateForwarderMethodId) ||
599
+ data.startsWith(walletUtil_1.v1CreateForwarderMethodId) ||
600
+ data.startsWith(walletUtil_1.createForwarderMethodId))) {
601
+ throw new sdk_core_1.BuildTransactionError(`Invalid address bytecode: ${data}`);
602
+ }
603
+ if (data.startsWith(walletUtil_1.createForwarderMethodId)) {
604
+ return {
605
+ baseAddress: undefined,
606
+ addressCreationSalt: undefined,
607
+ feeAddress: undefined,
608
+ };
609
+ }
610
+ else if (data.startsWith(walletUtil_1.v1CreateForwarderMethodId)) {
611
+ const [baseAddress, saltBuffer] = getRawDecoded(walletUtil_1.createV1ForwarderTypes, getBufferedByteCode(walletUtil_1.v1CreateForwarderMethodId, data));
612
+ return {
613
+ baseAddress: ethereumjs_util_1.addHexPrefix(baseAddress),
614
+ addressCreationSalt: ethereumjs_util_1.bufferToHex(saltBuffer),
615
+ feeAddress: undefined,
616
+ };
617
+ }
618
+ else {
619
+ const [baseAddress, feeAddress, saltBuffer] = getRawDecoded(walletUtil_1.createV4ForwarderTypes, getBufferedByteCode(walletUtil_1.v4CreateForwarderMethodId, data));
620
+ return {
621
+ baseAddress: ethereumjs_util_1.addHexPrefix(baseAddress),
622
+ addressCreationSalt: ethereumjs_util_1.bufferToHex(saltBuffer),
623
+ feeAddress: ethereumjs_util_1.addHexPrefix(feeAddress),
624
+ };
625
+ }
626
+ }
627
+ exports.decodeForwarderCreationData = decodeForwarderCreationData;
628
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1DQUFnQztBQUNoQyxvREFBNEI7QUFDNUIscURBV3lCO0FBQ3pCLGlEQUFpSDtBQUNqSCxvRUFBeUM7QUFDekMsZ0VBQWdEO0FBQ2hELGtEQUF1QjtBQUN2QixnRUFBcUM7QUFDckMsbURBVThCO0FBZTlCLDZDQTBCc0I7QUFDdEIsbUNBQTZDO0FBRTdDOztHQUVHO0FBQ0gsU0FBZ0IsU0FBUyxDQUFDLE9BQXdCO0lBQ2hELE9BQU8sZ0JBQWMsQ0FBQyxjQUFjO0lBQ2xDLHdFQUF3RTtJQUN4RSxTQUFTLEVBQ1Q7UUFDRSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDbEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQzFCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztLQUN6QixFQUNELFFBQVEsQ0FDVCxDQUFDO0FBQ0osQ0FBQztBQVhELDhCQVdDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSSxLQUFLLFVBQVUsWUFBWSxDQUNoQyxlQUF1QixFQUN2QixPQUFnQixFQUNoQixZQUE0QjtJQUU1QixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRTtRQUMxQixNQUFNLElBQUksdUJBQVksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0tBQy9DO0lBQ0QsTUFBTSxLQUFLLEdBQUcsMEJBQWtCLENBQUMsUUFBUSxDQUFDLGVBQWUsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN6RSxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3BCLE9BQU8sS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDO0FBQzlCLENBQUM7QUFYRCxvQ0FXQztBQUVEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSxJQUFJLENBQUMsZUFBdUIsRUFBRSxPQUFnQjtJQUNsRSxPQUFP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QUFDO1lBQ2hELG1CQUFtQixFQUFFLDZCQUFXLENBQUMsVUFBb0IsQ0FBQztZQUN0RCxVQUFVLEVBQUUsU0FBUztTQUNiLENBQUM7S0FDWjtTQUFNO1FBQ0wsTUFBTSxDQUFDLFdBQVcsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLEdBQUcsYUFBYSxDQUN6RCxtQ0FBc0IsRUFDdEIsbUJBQW1CLENBQUMsc0NBQXlCLEVBQUUsSUFBSSxDQUFDLENBQ3JELENBQUM7UUFFRixPQUFPO1lBQ0wsV0FBVyxFQUFFLDhCQUFZLENBQUMsV0FBcUIsQ0FBQztZQUNoRCxtQkFBbUIsRUFBRSw2QkFBVyxDQUFDLFVBQW9CLENBQUM7WUFDdEQsVUFBVSxFQUFFLDhCQUFZLENBQUMsVUFBb0IsQ0FBQztTQUN0QyxDQUFDO0tBQ1o7QUFDSCxDQUFDO0FBeENELGtFQXdDQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQge1xuICBhZGRIZXhQcmVmaXgsXG4gIGJ1ZmZlclRvSGV4LFxuICBidWZmZXJUb0ludCxcbiAgZ2VuZXJhdGVBZGRyZXNzLFxuICBpc1ZhbGlkQWRkcmVzcyxcbiAgc2V0TGVuZ3RoTGVmdCxcbiAgc3RyaXBIZXhQcmVmaXgsXG4gIHRvQnVmZmVyLFxuICBnZW5lcmF0ZUFkZHJlc3MyLFxuICBwYWRUb0V2ZW4sXG59IGZyb20gJ2V0aGVyZXVtanMtdXRpbCc7XG5pbXBvcnQgeyBCYXNlQ29pbiwgQmFzZU5ldHdvcmssIGNvaW5zLCBDb250cmFjdEFkZHJlc3NEZWZpbmVkVG9rZW4sIEV0aGVyZXVtTmV0d29yayB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IEV0aGVyZXVtQWJpIGZyb20gJ2V0aGVyZXVtanMtYWJpJztcbmltcG9ydCBFdGhlcmV1bUNvbW1vbiBmcm9tICdAZXRoZXJldW1qcy9jb21tb24nO1xuaW1wb3J0IEJOIGZyb20gJ2JuLmpzJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7XG4gIEFjdGl2YXRlTWV0aG9kSWQsXG4gIEJ1aWxkVHJhbnNhY3Rpb25FcnJvcixcbiAgTG9ja01ldGhvZElkLFxuICBTaWduaW5nRXJyb3IsXG4gIFRyYW5zYWN0aW9uVHlwZSxcbiAgVW5sb2NrTWV0aG9kSWQsXG4gIFVudm90ZU1ldGhvZElkLFxuICBWb3RlTWV0aG9kSWQsXG4gIFdpdGhkcmF3TWV0aG9kSWQsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcblxuaW1wb3J0IHtcbiAgRVJDMTE1NVRyYW5zZmVyRGF0YSxcbiAgRVJDNzIxVHJhbnNmZXJEYXRhLFxuICBGbHVzaFRva2Vuc0RhdGEsXG4gIE5hdGl2ZVRyYW5zZmVyRGF0YSxcbiAgU2lnbmF0dXJlUGFydHMsXG4gIFRva2VuVHJhbnNmZXJEYXRhLFxuICBUcmFuc2ZlckRhdGEsXG4gIFR4RGF0YSxcbiAgV2FsbGV0SW5pdGlhbGl6YXRpb25EYXRhLFxuICBGb3J3YXJkZXJJbml0aWFsaXphdGlvbkRhdGEsXG59IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHsgS2V5UGFpciB9IGZyb20gJy4va2V5UGFpcic7XG5pbXBvcnQge1xuICBjcmVhdGVGb3J3YXJkZXJNZXRob2RJZCxcbiAgRVJDMTE1NUJhdGNoVHJhbnNmZXJUeXBlTWV0aG9kSWQsXG4gIEVSQzExNTVCYXRjaFRyYW5zZmVyVHlwZXMsXG4gIEVSQzExNTVTYWZlVHJhbnNmZXJUeXBlTWV0aG9kSWQsXG4gIEVSQzExNTVTYWZlVHJhbnNmZXJUeXBlcyxcbiAgRVJDNzIxU2FmZVRyYW5zZmVyVHlwZU1ldGhvZElkLFxuICBFUkM3MjFTYWZlVHJhbnNmZXJUeXBlcyxcbiAgZmx1c2hDb2luc01ldGhvZElkLFxuICBmbHVzaENvaW5zVHlwZXMsXG4gIGZsdXNoRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWQsXG4gIGZsdXNoVG9rZW5zVHlwZXMsXG4gIHNlbmRNdWx0aXNpZ01ldGhvZElkLFxuICBzZW5kTXVsdGlzaWdUb2tlbk1ldGhvZElkLFxuICBzZW5kTXVsdGlTaWdUb2tlblR5cGVzLFxuICBzZW5kTXVsdGlTaWdUeXBlcyxcbiAgd2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzLFxuICB2MUNyZWF0ZUZvcndhcmRlck1ldGhvZElkLFxuICB3YWxsZXRTaW1wbGVDb25zdHJ1Y3RvcixcbiAgY3JlYXRlVjFXYWxsZXRUeXBlcyxcbiAgdjFDcmVhdGVXYWxsZXRNZXRob2RJZCxcbiAgY3JlYXRlVjFGb3J3YXJkZXJUeXBlcyxcbiAgcmVjb3ZlcnlXYWxsZXRJbml0aWFsaXphdGlvbkZpcnN0Qnl0ZXMsXG4gIGRlZmF1bHRGb3J3YXJkZXJWZXJzaW9uLFxuICBjcmVhdGVWNEZvcndhcmRlclR5cGVzLFxuICB2NENyZWF0ZUZvcndhcmRlck1ldGhvZElkLFxufSBmcm9tICcuL3dhbGxldFV0aWwnO1xuaW1wb3J0IHsgRXRoVHJhbnNhY3Rpb25EYXRhIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogQHBhcmFtIG5ldHdvcmtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbW1vbihuZXR3b3JrOiBFdGhlcmV1bU5ldHdvcmspOiBFdGhlcmV1bUNvbW1vbiB7XG4gIHJldHVybiBFdGhlcmV1bUNvbW1vbi5mb3JDdXN0b21DaGFpbihcbiAgICAvLyB1c2UgdGhlIG1haW5uZXQgY29uZmlnIGFzIGEgYmFzZSwgb3ZlcnJpZGUgY2hhaW4gaWRzIGFuZCBuZXR3b3JrIG5hbWVcbiAgICAnbWFpbm5ldCcsXG4gICAge1xuICAgICAgbmFtZTogbmV0d29yay50eXBlLFxuICAgICAgbmV0d29ya0lkOiBuZXR3b3JrLmNoYWluSWQsXG4gICAgICBjaGFpbklkOiBuZXR3b3JrLmNoYWluSWQsXG4gICAgfSxcbiAgICAnbG9uZG9uJ1xuICApO1xufVxuXG4vKipcbiAqIFNpZ25zIHRoZSB0cmFuc2FjdGlvbiB1c2luZyB0aGUgYXBwcm9wcmlhdGUgYWxnb3JpdGhtXG4gKiBhbmQgdGhlIHByb3ZpZGVkIGNvbW1vbiBmb3IgdGhlIGJsb2NrY2hhaW5cbiAqXG4gKiBAcGFyYW0ge1R4RGF0YX0gdHJhbnNhY3Rpb25EYXRhIHRoZSB0cmFuc2FjdGlvbiBkYXRhIHRvIHNpZ25cbiAqIEBwYXJhbSB7S2V5UGFpcn0ga2V5UGFpciB0aGUgc2lnbmVyJ3Mga2V5cGFpclxuICogQHBhcmFtIHtFdGhlcmV1bUNvbW1vbn0gY3VzdG9tQ29tbW9uIHRoZSBuZXR3b3JrJ3MgY3VzdG9tIGNvbW1vblxuICogQHJldHVybnMge3N0cmluZ30gdGhlIHRyYW5zYWN0aW9uIHNpZ25lZCBhbmQgZW5jb2RlZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkludGVybmFsKFxuICB0cmFuc2FjdGlvbkRhdGE6IFR4RGF0YSxcbiAga2V5UGFpcjogS2V5UGFpcixcbiAgY3VzdG9tQ29tbW9uOiBFdGhlcmV1bUNvbW1vblxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgaWYgKCFrZXlQYWlyLmdldEtleXMoKS5wcnYpIHtcbiAgICB0aHJvdyBuZXcgU2lnbmluZ0Vycm9yKCdNaXNzaW5nIHByaXZhdGUga2V5Jyk7XG4gIH1cbiAgY29uc3QgZXRoVHggPSBFdGhUcmFuc2FjdGlvbkRhdGEuZnJvbUpzb24odHJhbnNhY3Rpb25EYXRhLCBjdXN0b21Db21tb24pO1xuICBldGhUeC5zaWduKGtleVBhaXIpO1xuICByZXR1cm4gZXRoVHgudG9TZXJpYWxpemVkKCk7XG59XG5cbi8qKlxuICogU2lnbnMgdGhlIHRyYW5zYWN0aW9uIHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBhbGdvcml0aG1cbiAqXG4gKiBAcGFyYW0ge1R4RGF0YX0gdHJhbnNhY3Rpb25EYXRhIHRoZSB0cmFuc2FjdGlvbiBkYXRhIHRvIHNpZ25cbiAqIEBwYXJhbSB7S2V5UGFpcn0ga2V5UGFpciB0aGUgc2lnbmVyJ3Mga2V5cGFpclxuICogQHJldHVybnMge3N0cmluZ30gdGhlIHRyYW5zYWN0aW9uIHNpZ25lZCBhbmQgZW5jb2RlZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbih0cmFuc2FjdGlvbkRhdGE6IFR4RGF0YSwga2V5UGFpcjogS2V5UGFpcik6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBzaWduSW50ZXJuYWwodHJhbnNhY3Rpb25EYXRhLCBrZXlQYWlyLCBnZXRDb21tb24oY29pbnMuZ2V0KCd0ZXRoJykubmV0d29yayBhcyBFdGhlcmV1bU5ldHdvcmspKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjb250cmFjdCBtZXRob2QgZW5jb2RlZCBkYXRhXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRvIGRlc3RpbmF0aW9uIGFkZHJlc3NcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBBbW91bnQgdG8gdHJhbmZlclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgYWRpdGlvbmFsIG1ldGhvZCBjYWxsIGRhdGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBleHBpcmVUaW1lIGV4cGlyYXRpb24gdGltZSBmb3IgdGhlIHRyYW5zYWN0aW9uIGluIHNlY29uZHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBzZXF1ZW5jZUlkIHNlcXVlbmNlIGlkXG4gKiBAcGFyYW0ge3N0cmluZ30gc2lnbmF0dXJlIHNpZ25hdHVyZSBvZiB0aGUgY2FsbFxuICogQHJldHVybnMge3N0cmluZ30gLS0gdGhlIGNvbnRyYWN0IG1ldGhvZCBlbmNvZGVkIGRhdGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRNdWx0aVNpZ0RhdGEoXG4gIHRvOiBzdHJpbmcsXG4gIHZhbHVlOiBzdHJpbmcsXG4gIGRhdGE6IHN0cmluZyxcbiAgZXhwaXJlVGltZTogbnVtYmVyLFxuICBzZXF1ZW5jZUlkOiBudW1iZXIsXG4gIHNpZ25hdHVyZTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCBwYXJhbXMgPSBbdG8sIHZhbHVlLCB0b0J1ZmZlcihkYXRhKSwgZXhwaXJlVGltZSwgc2VxdWVuY2VJZCwgdG9CdWZmZXIoc2lnbmF0dXJlKV07XG4gIGNvbnN0IG1ldGhvZCA9IEV0aGVyZXVtQWJpLm1ldGhvZElEKCdzZW5kTXVsdGlTaWcnLCBzZW5kTXVsdGlTaWdUeXBlcyk7XG4gIGNvbnN0IGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoc2VuZE11bHRpU2lnVHlwZXMsIHBhcmFtcyk7XG4gIHJldHVybiBhZGRIZXhQcmVmaXgoQnVmZmVyLmNvbmNhdChbbWV0aG9kLCBhcmdzXSkudG9TdHJpbmcoJ2hleCcpKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjb250cmFjdCBtZXRob2QgZW5jb2RlZCBkYXRhXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRvIGRlc3RpbmF0aW9uIGFkZHJlc3NcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBBbW91bnQgdG8gdHJhbmZlclxuICogQHBhcmFtIHtzdHJpbmd9IHRva2VuQ29udHJhY3RBZGRyZXNzIHRoZSBhZGRyZXNzIG9mIHRoZSBlcmMyMCB0b2tlbiBjb250cmFjdFxuICogQHBhcmFtIHtudW1iZXJ9IGV4cGlyZVRpbWUgZXhwaXJhdGlvbiB0aW1lIGZvciB0aGUgdHJhbnNhY3Rpb24gaW4gc2Vjb25kc1xuICogQHBhcmFtIHtudW1iZXJ9IHNlcXVlbmNlSWQgc2VxdWVuY2UgaWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzaWduYXR1cmUgc2lnbmF0dXJlIG9mIHRoZSBjYWxsXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtLSB0aGUgY29udHJhY3QgbWV0aG9kIGVuY29kZWQgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VuZE11bHRpU2lnVG9rZW5EYXRhKFxuICB0bzogc3RyaW5nLFxuICB2YWx1ZTogc3RyaW5nLFxuICB0b2tlbkNvbnRyYWN0QWRkcmVzczogc3RyaW5nLFxuICBleHBpcmVUaW1lOiBudW1iZXIsXG4gIHNlcXVlbmNlSWQ6IG51bWJlcixcbiAgc2lnbmF0dXJlOiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IHBhcmFtcyA9IFt0bywgdmFsdWUsIHRva2VuQ29udHJhY3RBZGRyZXNzLCBleHBpcmVUaW1lLCBzZXF1ZW5jZUlkLCB0b0J1ZmZlcihzaWduYXR1cmUpXTtcblxuICBjb25zdCBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnc2VuZE11bHRpU2lnVG9rZW4nLCBzZW5kTXVsdGlTaWdUb2tlblR5cGVzKTtcbiAgY29uc3QgYXJncyA9IEV0aGVyZXVtQWJpLnJhd0VuY29kZShzZW5kTXVsdGlTaWdUb2tlblR5cGVzLCBwYXJhbXMpO1xuICByZXR1cm4gYWRkSGV4UHJlZml4KEJ1ZmZlci5jb25jYXQoW21ldGhvZCwgYXJnc10pLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBkYXRhIHJlcXVpcmVkIHRvIG1ha2UgYSBmbHVzaCB0b2tlbnMgY29udHJhY3QgY2FsbFxuICpcbiAqIEBwYXJhbSBmb3J3YXJkZXJBZGRyZXNzIFRoZSBmb3J3YXJkZXIgYWRkcmVzcyB0byBmbHVzaFxuICogQHBhcmFtIHRva2VuQWRkcmVzcyBUaGUgdG9rZW4gYWRkcmVzcyB0byBmbHVzaCBmcm9tXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbHVzaFRva2Vuc0RhdGEoZm9yd2FyZGVyQWRkcmVzczogc3RyaW5nLCB0b2tlbkFkZHJlc3M6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcmFtcyA9IFtmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3NdO1xuICBjb25zdCBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnZmx1c2hGb3J3YXJkZXJUb2tlbnMnLCBmbHVzaFRva2Vuc1R5cGVzKTtcbiAgY29uc3QgYXJncyA9IEV0aGVyZXVtQWJpLnJhd0VuY29kZShmbHVzaFRva2Vuc1R5cGVzLCBwYXJhbXMpO1xuICByZXR1cm4gYWRkSGV4UHJlZml4KEJ1ZmZlci5jb25jYXQoW21ldGhvZCwgYXJnc10pLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBkYXRhIHJlcXVpcmVkIHRvIG1ha2UgYSBmbHVzaCBuYXRpdmUgY29pbnMgY29udHJhY3QgY2FsbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmx1c2hDb2luc0RhdGEoKTogc3RyaW5nIHtcbiAgY29uc3QgcGFyYW1zID0gW107XG4gIGNvbnN0IG1ldGhvZCA9IEV0aGVyZXVtQWJpLm1ldGhvZElEKCdmbHVzaCcsIGZsdXNoQ29pbnNUeXBlcyk7XG4gIGNvbnN0IGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoZmx1c2hDb2luc1R5cGVzLCBwYXJhbXMpO1xuICByZXR1cm4gYWRkSGV4UHJlZml4KEJ1ZmZlci5jb25jYXQoW21ldGhvZCwgYXJnc10pLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3JlYXRlIGZvcndhcmRlciBtZXRob2QgY2FsbGluZyBkYXRhXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gLSB0aGUgY3JlYXRlRm9yd2FyZGVyIG1ldGhvZCBlbmNvZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRyZXNzSW5pdGlhbGl6YXRpb25EYXRhKCk6IHN0cmluZyB7XG4gIHJldHVybiBjcmVhdGVGb3J3YXJkZXJNZXRob2RJZDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBFdGggYWRkcmVzc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIC0gdGhlIHR4IGhhc2ggdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBhbW91bnQgbnVtYmVyXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGFtb3VudCAtIHRoZSBzdHJpbmcgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEFtb3VudChhbW91bnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBiaWdOdW1iZXJBbW91bnQgPSBuZXcgQmlnTnVtYmVyKGFtb3VudCk7XG4gIHJldHVybiBiaWdOdW1iZXJBbW91bnQuaXNJbnRlZ2VyKCkgJiYgYmlnTnVtYmVyQW1vdW50LmlzR3JlYXRlclRoYW5PckVxdWFsVG8oMCk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc21hcnQgY29udHJhY3QgZW5jb2RlZCBkYXRhXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgVGhlIHdhbGxldCBjcmVhdGlvbiBkYXRhIHRvIGRlY29kZVxuICogQHJldHVybnMge3N0cmluZ1tdfSAtIFRoZSBsaXN0IG9mIHNpZ25lciBhZGRyZXNzZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVdhbGxldENyZWF0aW9uRGF0YShkYXRhOiBzdHJpbmcpOiBXYWxsZXRJbml0aWFsaXphdGlvbkRhdGEge1xuICBpZiAoIShkYXRhLnN0YXJ0c1dpdGgod2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzKSB8fCBkYXRhLnN0YXJ0c1dpdGgodjFDcmVhdGVXYWxsZXRNZXRob2RJZCkpKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB3YWxsZXQgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGlmIChkYXRhLnN0YXJ0c1dpdGgod2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzKSkge1xuICAgIGNvbnN0IGRhdGFCdWZmZXIgPSBCdWZmZXIuZnJvbShkYXRhLnNsaWNlKDIpLCAnaGV4Jyk7XG5cbiAgICAvLyB0aGUgbGFzdCAxNjAgYnl0ZXMgY29udGFpbiB0aGUgc2VyaWFsaXplZCBhZGRyZXNzIGFycmF5XG4gICAgY29uc3Qgc2VyaWFsaXplZFNpZ25lcnMgPSBkYXRhQnVmZmVyLnNsaWNlKC0xNjApO1xuXG4gICAgY29uc3QgcmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMgPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUod2FsbGV0U2ltcGxlQ29uc3RydWN0b3IsIHNlcmlhbGl6ZWRTaWduZXJzKTtcbiAgICBpZiAocmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBDb3VsZCBub3QgZGVjb2RlIHdhbGxldCBjb25zdHJ1Y3RvciBieXRlY29kZTogJHtyZXN1bHRFbmNvZGVkUGFyYW1ldGVyc31gKTtcbiAgICB9XG5cbiAgICBjb25zdCBhZGRyZXNzZXM6IEJOW10gPSByZXN1bHRFbmNvZGVkUGFyYW1ldGVyc1swXTtcbiAgICBpZiAoYWRkcmVzc2VzLmxlbmd0aCAhPT0gMykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgaW52YWxpZCBudW1iZXIgb2YgYWRkcmVzc2VzIGluIHBhcnNlZCBjb25zdHJ1Y3RvcjogJHthZGRyZXNzZXN9YCk7XG4gICAgfVxuXG4gICAgLy8gc29tZXRpbWVzIGV0aGVyZXVtanMtYWJpIHJlbW92ZXMgMCBwYWRkaW5nIGF0IHRoZSBzdGFydCBvZiBhZGRyZXNzZXMsXG4gICAgLy8gc28gd2Ugc2hvdWxkIHBhZCB1bnRpbCB0aGV5IGFyZSB0aGUgc3RhbmRhcmQgMjAgYnl0ZXNcbiAgICBjb25zdCBwYWRkZWRBZGRyZXNzZXMgPSBhZGRyZXNzZXMubWFwKChhZGRyZXNzKSA9PiBzdHJpcEhleFByZWZpeChhZGRyZXNzLnRvU3RyaW5nKCdoZXgnKSkucGFkU3RhcnQoNDAsICcwJykpO1xuXG4gICAgcmV0dXJuIHsgb3duZXJzOiBwYWRkZWRBZGRyZXNzZXMubWFwKChhZGRyZXNzKSA9PiBhZGRIZXhQcmVmaXgoYWRkcmVzcykpIH07XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgZGVjb2RlZERhdGFGb3JXYWxsZXRDcmVhdGlvbiA9IGdldFJhd0RlY29kZWQoXG4gICAgICBjcmVhdGVWMVdhbGxldFR5cGVzLFxuICAgICAgZ2V0QnVmZmVyZWRCeXRlQ29kZSh2MUNyZWF0ZVdhbGxldE1ldGhvZElkLCBkYXRhKVxuICAgICk7XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlZERhdGFGb3JXYWxsZXRDcmVhdGlvblswXSBhcyBzdHJpbmdbXTtcbiAgICBjb25zdCBzYWx0QnVmZmVyID0gZGVjb2RlZERhdGFGb3JXYWxsZXRDcmVhdGlvblsxXTtcbiAgICBjb25zdCBzYWx0ID0gYnVmZmVyVG9IZXgoc2FsdEJ1ZmZlciBhcyBCdWZmZXIpO1xuICAgIGNvbnN0IHBhZGRlZEFkZHJlc3NlcyA9IGFkZHJlc3Nlcy5tYXAoKGFkZHJlc3MpID0+IHN0cmlwSGV4UHJlZml4KGFkZHJlc3MudG9TdHJpbmcoKSkucGFkU3RhcnQoNDAsICcwJykpO1xuICAgIGNvbnN0IG93bmVycyA9IHBhZGRlZEFkZHJlc3Nlcy5tYXAoKGFkZHJlc3MpID0+IGFkZEhleFByZWZpeChhZGRyZXNzKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIG93bmVycyxcbiAgICAgIHNhbHQsXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIERlY29kZSB0aGUgZ2l2ZW4gQUJJLWVuY29kZWQgdHJhbnNmZXIgZGF0YSBhbmQgcmV0dXJuIHBhcnNlZCBmaWVsZHNcbiAqXG4gKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBkZWNvZGVcbiAqIEByZXR1cm5zIHBhcnNlZCB0cmFuc2ZlciBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUcmFuc2ZlckRhdGEoZGF0YTogc3RyaW5nKTogVHJhbnNmZXJEYXRhIHtcbiAgaWYgKGRhdGEuc3RhcnRzV2l0aChzZW5kTXVsdGlzaWdNZXRob2RJZCkpIHtcbiAgICByZXR1cm4gZGVjb2RlTmF0aXZlVHJhbnNmZXJEYXRhKGRhdGEpO1xuICB9IGVsc2UgaWYgKGRhdGEuc3RhcnRzV2l0aChzZW5kTXVsdGlzaWdUb2tlbk1ldGhvZElkKSkge1xuICAgIHJldHVybiBkZWNvZGVUb2tlblRyYW5zZmVyRGF0YShkYXRhKTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIHRyYW5zZmVyIGJ5dGVjb2RlOiAke2RhdGF9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBEZWNvZGUgdGhlIGdpdmVuIEFCSS1lbmNvZGVkIHRyYW5zZmVyIGRhdGEgZm9yIHRoZSBzZW5kTXVsdGlzaWdUb2tlbiBmdW5jdGlvbiBhbmQgcmV0dXJuIHBhcnNlZCBmaWVsZHNcbiAqXG4gKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBkZWNvZGVcbiAqIEByZXR1cm5zIHBhcnNlZCB0b2tlbiB0cmFuc2ZlciBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUb2tlblRyYW5zZmVyRGF0YShkYXRhOiBzdHJpbmcpOiBUb2tlblRyYW5zZmVyRGF0YSB7XG4gIGlmICghZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ1Rva2VuTWV0aG9kSWQpKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG5cbiAgY29uc3QgW3RvLCBhbW91bnQsIHRva2VuQ29udHJhY3RBZGRyZXNzLCBleHBpcmVUaW1lLCBzZXF1ZW5jZUlkLCBzaWduYXR1cmVdID0gZ2V0UmF3RGVjb2RlZChcbiAgICBzZW5kTXVsdGlTaWdUb2tlblR5cGVzLFxuICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoc2VuZE11bHRpc2lnVG9rZW5NZXRob2RJZCwgZGF0YSlcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHRvOiBhZGRIZXhQcmVmaXgodG8gYXMgc3RyaW5nKSxcbiAgICBhbW91bnQ6IG5ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgoYW1vdW50IGFzIEJ1ZmZlcikpLnRvRml4ZWQoKSxcbiAgICBleHBpcmVUaW1lOiBidWZmZXJUb0ludChleHBpcmVUaW1lIGFzIEJ1ZmZlciksXG4gICAgc2VxdWVuY2VJZDogYnVmZmVyVG9JbnQoc2VxdWVuY2VJZCBhcyBCdWZmZXIpLFxuICAgIHNpZ25hdHVyZTogYnVmZmVyVG9IZXgoc2lnbmF0dXJlIGFzIEJ1ZmZlciksXG4gICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IGFkZEhleFByZWZpeCh0b2tlbkNvbnRyYWN0QWRkcmVzcyBhcyBzdHJpbmcpLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRVJDNzIxVHJhbnNmZXJEYXRhKGRhdGE6IHN0cmluZyk6IEVSQzcyMVRyYW5zZmVyRGF0YSB7XG4gIGlmICghZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ01ldGhvZElkKSkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGNvbnN0IFt0bywgYW1vdW50LCBpbnRlcm5hbERhdGEsIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWQsIHNpZ25hdHVyZV0gPSBnZXRSYXdEZWNvZGVkKFxuICAgIHNlbmRNdWx0aVNpZ1R5cGVzLFxuICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoc2VuZE11bHRpc2lnTWV0aG9kSWQsIGRhdGEpXG4gICk7XG5cbiAgY29uc3QgaW50ZXJuYWxEYXRhSGV4ID0gYnVmZmVyVG9IZXgoaW50ZXJuYWxEYXRhIGFzIEJ1ZmZlcik7XG4gIGlmICghaW50ZXJuYWxEYXRhSGV4LnN0YXJ0c1dpdGgoRVJDNzIxU2FmZVRyYW5zZmVyVHlwZU1ldGhvZElkKSkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGNvbnN0IFtmcm9tLCByZWNlaXZlciwgdG9rZW5JZCwgdXNlclNlbnREYXRhXSA9IGdldFJhd0RlY29kZWQoXG4gICAgRVJDNzIxU2FmZVRyYW5zZmVyVHlwZXMsXG4gICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShFUkM3MjFTYWZlVHJhbnNmZXJUeXBlTWV0aG9kSWQsIGludGVybmFsRGF0YUhleClcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHRvOiBhZGRIZXhQcmVmaXgocmVjZWl2ZXIgYXMgc3RyaW5nKSxcbiAgICBmcm9tOiBhZGRIZXhQcmVmaXgoZnJvbSBhcyBzdHJpbmcpLFxuICAgIGV4cGlyZVRpbWU6IGJ1ZmZlclRvSW50KGV4cGlyZVRpbWUgYXMgQnVmZmVyKSxcbiAgICBhbW91bnQ6IG5ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgoYW1vdW50IGFzIEJ1ZmZlcikpLnRvRml4ZWQoKSxcbiAgICB0b2tlbklkOiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHRva2VuSWQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgIHNlcXVlbmNlSWQ6IGJ1ZmZlclRvSW50KHNlcXVlbmNlSWQgYXMgQnVmZmVyKSxcbiAgICBzaWduYXR1cmU6IGJ1ZmZlclRvSGV4KHNpZ25hdHVyZSBhcyBCdWZmZXIpLFxuICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBhZGRIZXhQcmVmaXgodG8gYXMgc3RyaW5nKSxcbiAgICB1c2VyRGF0YTogYnVmZmVyVG9IZXgodXNlclNlbnREYXRhIGFzIEJ1ZmZlciksXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVFUkMxMTU1VHJhbnNmZXJEYXRhKGRhdGE6IHN0cmluZyk6IEVSQzExNTVUcmFuc2ZlckRhdGEge1xuICBsZXQgZnJvbSwgcmVjZWl2ZXIsIHVzZXJTZW50RGF0YTtcbiAgbGV0IHRva2VuSWRzOiBzdHJpbmdbXTtcbiAgbGV0IHZhbHVlczogc3RyaW5nW107XG5cbiAgaWYgKCFkYXRhLnN0YXJ0c1dpdGgoc2VuZE11bHRpc2lnTWV0aG9kSWQpKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG5cbiAgY29uc3QgW3RvLCBhbW91bnQsIGludGVybmFsRGF0YSwgZXhwaXJlVGltZSwgc2VxdWVuY2VJZCwgc2lnbmF0dXJlXSA9IGdldFJhd0RlY29kZWQoXG4gICAgc2VuZE11bHRpU2lnVHlwZXMsXG4gICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShzZW5kTXVsdGlzaWdNZXRob2RJZCwgZGF0YSlcbiAgKTtcblxuICBjb25zdCBpbnRlcm5hbERhdGFIZXggPSBidWZmZXJUb0hleChpbnRlcm5hbERhdGEgYXMgQnVmZmVyKTtcbiAgaWYgKGludGVybmFsRGF0YUhleC5zdGFydHNXaXRoKEVSQzExNTVTYWZlVHJhbnNmZXJUeXBlTWV0aG9kSWQpKSB7XG4gICAgbGV0IHRva2VuSWQ7XG4gICAgbGV0IHZhbHVlO1xuXG4gICAgW2Zyb20sIHJlY2VpdmVyLCB0b2tlbklkLCB2YWx1ZSwgdXNlclNlbnREYXRhXSA9IGdldFJhd0RlY29kZWQoXG4gICAgICBFUkMxMTU1U2FmZVRyYW5zZmVyVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKEVSQzExNTVTYWZlVHJhbnNmZXJUeXBlTWV0aG9kSWQsIGludGVybmFsRGF0YUhleClcbiAgICApO1xuXG4gICAgdG9rZW5JZHMgPSBbbmV3IEJpZ051bWJlcihidWZmZXJUb0hleCh0b2tlbklkKSkudG9GaXhlZCgpXTtcbiAgICB2YWx1ZXMgPSBbbmV3IEJpZ051bWJlcihidWZmZXJUb0hleCh2YWx1ZSkpLnRvRml4ZWQoKV07XG4gIH0gZWxzZSBpZiAoYnVmZmVyVG9IZXgoaW50ZXJuYWxEYXRhIGFzIEJ1ZmZlcikuc3RhcnRzV2l0aChFUkMxMTU1QmF0Y2hUcmFuc2ZlclR5cGVNZXRob2RJZCkpIHtcbiAgICBsZXQgdGVtcFRva2VuSWRzLCB0ZW1wVmFsdWVzO1xuICAgIFtmcm9tLCByZWNlaXZlciwgdGVtcFRva2VuSWRzLCB0ZW1wVmFsdWVzLCB1c2VyU2VudERhdGFdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIEVSQzExNTVCYXRjaFRyYW5zZmVyVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKEVSQzExNTVCYXRjaFRyYW5zZmVyVHlwZU1ldGhvZElkLCBpbnRlcm5hbERhdGFIZXgpXG4gICAgKTtcbiAgICB0b2tlbklkcyA9IHRlbXBUb2tlbklkcy5tYXAoKHgpID0+IG5ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgoeCkpLnRvRml4ZWQoKSk7XG4gICAgdmFsdWVzID0gdGVtcFZhbHVlcy5tYXAoKHgpID0+IG5ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgoeCkpLnRvRml4ZWQoKSk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0bzogYWRkSGV4UHJlZml4KHJlY2VpdmVyKSxcbiAgICBmcm9tOiBhZGRIZXhQcmVmaXgoZnJvbSksXG4gICAgZXhwaXJlVGltZTogYnVmZmVyVG9JbnQoZXhwaXJlVGltZSBhcyBCdWZmZXIpLFxuICAgIGFtb3VudDogbmV3IEJpZ051bWJlcihidWZmZXJUb0hleChhbW91bnQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgIHRva2VuSWRzLFxuICAgIHZhbHVlcyxcbiAgICBzZXF1ZW5jZUlkOiBidWZmZXJUb0ludChzZXF1ZW5jZUlkIGFzIEJ1ZmZlciksXG4gICAgc2lnbmF0dXJlOiBidWZmZXJUb0hleChzaWduYXR1cmUgYXMgQnVmZmVyKSxcbiAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogYWRkSGV4UHJlZml4KHRvIGFzIHN0cmluZyksXG4gICAgdXNlckRhdGE6IHVzZXJTZW50RGF0YSxcbiAgfTtcbn1cblxuLyoqXG4gKiBEZWNvZGUgdGhlIGdpdmVuIEFCSS1lbmNvZGVkIHRyYW5zZmVyIGRhdGEgZm9yIHRoZSBzZW5kTXVsdGlzaWcgZnVuY3Rpb24gYW5kIHJldHVybiBwYXJzZWQgZmllbGRzXG4gKlxuICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyBwYXJzZWQgdHJhbnNmZXIgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlTmF0aXZlVHJhbnNmZXJEYXRhKGRhdGE6IHN0cmluZyk6IE5hdGl2ZVRyYW5zZmVyRGF0YSB7XG4gIGlmICghZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ01ldGhvZElkKSkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGNvbnN0IFt0bywgYW1vdW50LCBpbnRlcm5hbERhdGEsIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWQsIHNpZ25hdHVyZV0gPSBnZXRSYXdEZWNvZGVkKFxuICAgIHNlbmRNdWx0aVNpZ1R5cGVzLFxuICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoc2VuZE11bHRpc2lnTWV0aG9kSWQsIGRhdGEpXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICB0bzogYWRkSGV4UHJlZml4KHRvIGFzIHN0cmluZyksXG4gICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KGFtb3VudCBhcyBCdWZmZXIpKS50b0ZpeGVkKCksXG4gICAgZXhwaXJlVGltZTogYnVmZmVyVG9JbnQoZXhwaXJlVGltZSBhcyBCdWZmZXIpLFxuICAgIHNlcXVlbmNlSWQ6IGJ1ZmZlclRvSW50KHNlcXVlbmNlSWQgYXMgQnVmZmVyKSxcbiAgICBzaWduYXR1cmU6IGJ1ZmZlclRvSGV4KHNpZ25hdHVyZSBhcyBCdWZmZXIpLFxuICAgIGRhdGE6IGJ1ZmZlclRvSGV4KGludGVybmFsRGF0YSBhcyBCdWZmZXIpLFxuICB9O1xufVxuXG4vKipcbiAqIERlY29kZSB0aGUgZ2l2ZW4gQUJJLWVuY29kZWQgZmx1c2ggdG9rZW5zIGRhdGEgYW5kIHJldHVybiBwYXJzZWQgZmllbGRzXG4gKlxuICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyBwYXJzZWQgdHJhbnNmZXIgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRmx1c2hUb2tlbnNEYXRhKGRhdGE6IHN0cmluZyk6IEZsdXNoVG9rZW5zRGF0YSB7XG4gIGlmICghZGF0YS5zdGFydHNXaXRoKGZsdXNoRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWQpKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG5cbiAgY29uc3QgW2ZvcndhcmRlckFkZHJlc3MsIHRva2VuQWRkcmVzc10gPSBnZXRSYXdEZWNvZGVkKFxuICAgIGZsdXNoVG9rZW5zVHlwZXMsXG4gICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShmbHVzaEZvcndhcmRlclRva2Vuc01ldGhvZElkLCBkYXRhKVxuICApO1xuXG4gIHJldHVybiB7XG4gICAgZm9yd2FyZGVyQWRkcmVzczogYWRkSGV4UHJlZml4KGZvcndhcmRlckFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgICB0b2tlbkFkZHJlc3M6IGFkZEhleFByZWZpeCh0b2tlbkFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDbGFzc2lmeSB0aGUgZ2l2ZW4gdHJhbnNhY3Rpb24gZGF0YSBiYXNlZCBhcyBhIHRyYW5zYWN0aW9uIHR5cGUuXG4gKiBFVEggdHJhbnNhY3Rpb25zIGFyZSBkZWZpbmVkIGJ5IHRoZSBmaXJzdCA4IGJ5dGVzIG9mIHRoZSB0cmFuc2FjdGlvbiBkYXRhLCBhbHNvIGtub3duIGFzIHRoZSBtZXRob2QgaWRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YSBUaGUgZGF0YSB0byBjbGFzc2lmeSB0aGUgdHJhbnNhY3Rpb24gd2l0aFxuICogQHJldHVybnMge1RyYW5zYWN0aW9uVHlwZX0gVGhlIGNsYXNzaWZpZWQgdHJhbnNhY3Rpb24gdHlwZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhc3NpZnlUcmFuc2FjdGlvbihkYXRhOiBzdHJpbmcpOiBUcmFuc2FjdGlvblR5cGUge1xuICBpZiAoZGF0YS5sZW5ndGggPCAxMCkge1xuICAgIC8vIGNvbnRyYWN0IGNhbGxzIG11c3QgaGF2ZSBhdCBsZWFzdCA0IGJ5dGVzIChtZXRob2QgaWQpIGFuZCAnMHgnXG4gICAgLy8gaWYgaXQgZG9lc24ndCBoYXZlIGVub3VnaCBkYXRhIHRvIGJlIGEgY29udHJhY3QgY2FsbCBpdCBtdXN0IGJlIGEgc2luZ2xlIHNpZyBzZW5kXG4gICAgcmV0dXJuIFRyYW5zYWN0aW9uVHlwZS5TaW5nbGVTaWdTZW5kO1xuICB9XG5cbiAgLy8gVE9ETyhTVExYLTE5NzApOiB2YWxpZGF0ZSBpZiB3ZSBhcmUgZ29pbmcgdG8gY29uc3RyYWludCB0byBzb21lIG1ldGhvZHMgYWxsb3dlZFxuICBsZXQgdHJhbnNhY3Rpb25UeXBlID0gdHJhbnNhY3Rpb25UeXBlc01hcFtkYXRhLnNsaWNlKDAsIDEwKS50b0xvd2VyQ2FzZSgpXTtcbiAgaWYgKHRyYW5zYWN0aW9uVHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdHJhbnNhY3Rpb25UeXBlID0gVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbDtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2FjdGlvblR5cGU7XG59XG5cbi8qKlxuICogQSB0cmFuc2FjdGlvbiB0eXBlcyBtYXAgYWNjb3JkaW5nIHRvIHRoZSBzdGFydGluZyBwYXJ0IG9mIHRoZSBlbmNvZGVkIGRhdGFcbiAqL1xuY29uc3QgdHJhbnNhY3Rpb25UeXBlc01hcCA9IHtcbiAgW3dhbGxldEluaXRpYWxpemF0aW9uRmlyc3RCeXRlc106IFRyYW5zYWN0aW9uVHlwZS5XYWxsZXRJbml0aWFsaXphdGlvbixcbiAgW3JlY292ZXJ5V2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzXTogVHJhbnNhY3Rpb25UeXBlLlJlY292ZXJ5V2FsbGV0RGVwbG95bWVudCxcbiAgW3YxQ3JlYXRlV2FsbGV0TWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb24sXG4gIFtjcmVhdGVGb3J3YXJkZXJNZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb24sXG4gIFt2MUNyZWF0ZUZvcndhcmRlck1ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLkFkZHJlc3NJbml0aWFsaXphdGlvbixcbiAgW3Y0Q3JlYXRlRm9yd2FyZGVyTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuQWRkcmVzc0luaXRpYWxpemF0aW9uLFxuICBbc2VuZE11bHRpc2lnTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuU2VuZCxcbiAgW2ZsdXNoRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuRmx1c2hUb2tlbnMsXG4gIFtmbHVzaENvaW5zTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuRmx1c2hDb2lucyxcbiAgW3NlbmRNdWx0aXNpZ1Rva2VuTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuU2VuZCxcbiAgW0xvY2tNZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nTG9jayxcbiAgW1ZvdGVNZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nVm90ZSxcbiAgW0FjdGl2YXRlTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlLFxuICBbVW52b3RlTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1Vudm90ZSxcbiAgW1VubG9ja01ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2ssXG4gIFtXaXRoZHJhd01ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdyxcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBudW0gbnVtYmVyIHRvIGJlIGNvbnZlcnRlZCB0byBoZXhcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBoZXggbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJUb0hleFN0cmluZyhudW06IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGhleCA9IG51bS50b1N0cmluZygxNik7XG4gIHJldHVybiBoZXgubGVuZ3RoICUgMiA9PT0gMCA/ICcweCcgKyBoZXggOiAnMHgwJyArIGhleDtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGhleCBUaGUgaGV4IHN0cmluZyB0byBiZSBjb252ZXJ0ZWRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IHRoZSByZXN1bHRpbmcgbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoZXhTdHJpbmdUb051bWJlcihoZXg6IHN0cmluZyk6IG51bWJlciB7XG4gIHJldHVybiBwYXJzZUludChoZXguc2xpY2UoMiksIDE2KTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYW4gYWRkcmVzcyBvZiB0aGUgZm9yd2FyZGVyIGFkZHJlc3MgdG8gYmUgZGVwbG95ZWRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udHJhY3RBZGRyZXNzIHRoZSBhZGRyZXNzIHdoaWNoIGlzIGNyZWF0aW5nIHRoaXMgbmV3IGFkZHJlc3NcbiAqIEBwYXJhbSB7bnVtYmVyfSBjb250cmFjdENvdW50ZXIgdGhlIG5vbmNlIG9mIHRoZSBjb250cmFjdCBhZGRyZXNzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB0aGUgY2FsY3VsYXRlZCBmb3J3YXJkZXIgY29udHJhY3QgYWRkcmVzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlRm9yd2FyZGVyQWRkcmVzcyhjb250cmFjdEFkZHJlc3M6IHN0cmluZywgY29udHJhY3RDb3VudGVyOiBudW1iZXIpOiBzdHJpbmcge1xuICBjb25zdCBmb3J3YXJkZXJBZGRyZXNzID0gZ2VuZXJhdGVBZGRyZXNzKFxuICAgIEJ1ZmZlci5mcm9tKHN0cmlwSGV4UHJlZml4KGNvbnRyYWN0QWRkcmVzcyksICdoZXgnKSxcbiAgICBCdWZmZXIuZnJvbShwYWRUb0V2ZW4oc3RyaXBIZXhQcmVmaXgobnVtYmVyVG9IZXhTdHJpbmcoY29udHJhY3RDb3VudGVyKSkpLCAnaGV4JylcbiAgKTtcbiAgcmV0dXJuIGFkZEhleFByZWZpeChmb3J3YXJkZXJBZGRyZXNzLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSBmb3J3YXJkZXIgdjEgYWRkcmVzcyB0aGF0IHdpbGwgYmUgZ2VuZXJhdGVkIGlmIGBjcmVhdG9yQWRkcmVzc2AgY3JlYXRlcyBpdCB3aXRoIHNhbHQgYHNhbHRgXG4gKiBhbmQgaW5pdGNvZGUgYGluaWNvZGUgdXNpbmcgdGhlIGNyZWF0ZTIgb3Bjb2RlXG4gKiBAcGFyYW0ge3N0cmluZ30gY3JlYXRvckFkZHJlc3MgVGhlIGFkZHJlc3MgdGhhdCBpcyBzZW5kaW5nIHRoZSB0eCB0byBjcmVhdGUgYSBuZXcgYWRkcmVzcywgaGV4IHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHNhbHQgVGhlIHNhbHQgdG8gY3JlYXRlIHRoZSBhZGRyZXNzIHdpdGggdXNpbmcgY3JlYXRlMiwgaGV4IHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IGluaXRjb2RlIFRoZSBpbml0Y29kZSB0aGF0IHdpbGwgYmUgZGVwbG95ZWQgdG8gdGhlIGFkZHJlc3MsIGhleCBzdHJpbmdcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGNhbGN1bGF0ZWQgYWRkcmVzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlRm9yd2FyZGVyVjFBZGRyZXNzKGNyZWF0b3JBZGRyZXNzOiBzdHJpbmcsIHNhbHQ6IHN0cmluZywgaW5pdGNvZGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGZvcndhcmRlclYxQWRkcmVzcyA9IGdlbmVyYXRlQWRkcmVzczIoXG4gICAgQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoY3JlYXRvckFkZHJlc3MpLCAnaGV4JyksXG4gICAgQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoc2FsdCksICdoZXgnKSxcbiAgICBCdWZmZXIuZnJvbShwYWRUb0V2ZW4oc3RyaXBIZXhQcmVmaXgoaW5pdGNvZGUpKSwgJ2hleCcpXG4gICk7XG4gIHJldHVybiBhZGRIZXhQcmVmaXgoZm9yd2FyZGVyVjFBZGRyZXNzLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogVGFrZSB0aGUgaW1wbGVtZW50YXRpb24gYWRkcmVzcyBmb3IgdGhlIHByb3h5IGNvbnRyYWN0LCBhbmQgZ2V0IHRoZSBiaW5hcnkgaW5pdGNvZGUgZm9yIHRoZSBhc3NvY2lhdGVkIHByb3h5XG4gKiBAcGFyYW0ge3N0cmluZ30gaW1wbGVtZW50YXRpb25BZGRyZXNzIFRoZSBhZGRyZXNzIG9mIHRoZSBpbXBsZW1lbnRhdGlvbiBjb250cmFjdCBmb3IgdGhlIHByb3h5XG4gKiBAcmV0dXJuIHtzdHJpbmd9IEJpbmFyeSBoZXggc3RyaW5nIG9mIHRoZSBwcm94eVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJveHlJbml0Y29kZShpbXBsZW1lbnRhdGlvbkFkZHJlc3M6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHRhcmdldCA9IHN0cmlwSGV4UHJlZml4KGltcGxlbWVudGF0aW9uQWRkcmVzcy50b0xvd2VyQ2FzZSgpKS5wYWRTdGFydCg0MCwgJzAnKTtcblxuICAvLyBieXRlY29kZSBvZiB0aGUgcHJveHksIGZyb206XG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9CaXRHby9ldGgtbXVsdGlzaWctdjQvYmxvYi9kNTQ2YTkzN2Y5MGY5M2U4M2IzNDIzYTViZjkzM2QxZDc3YzY3N2MzL2NvbnRyYWN0cy9DbG9uZUZhY3Rvcnkuc29sI0w0Mi1MNTZcbiAgcmV0dXJuIGAweDNkNjAyZDgwNjAwYTNkMzk4MWYzMzYzZDNkMzczZDNkM2QzNjNkNzMke3RhcmdldH01YWY0M2Q4MjgwM2U5MDNkOTE2MDJiNTdmZDViZjNgO1xufVxuXG4vKipcbiAqIENvbnZlcnQgdGhlIGdpdmVuIHNpZ25hdHVyZSBwYXJ0cyB0byBhIHN0cmluZyByZXByZXNlbnRhdGlvblxuICpcbiAqIEBwYXJhbSB7U2lnbmF0dXJlUGFydHN9IHNpZyBUaGUgc2lnbmF0dXJlIHRvIGNvbnZlcnQgdG8gc3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHNpZ25hdHVyZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TdHJpbmdTaWcoc2lnOiBTaWduYXR1cmVQYXJ0cyk6IHN0cmluZyB7XG4gIHJldHVybiBidWZmZXJUb0hleChcbiAgICBCdWZmZXIuY29uY2F0KFtcbiAgICAgIHNldExlbmd0aExlZnQoQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoc2lnLnIpLCAnaGV4JyksIDMyKSxcbiAgICAgIHNldExlbmd0aExlZnQoQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoc2lnLnMpLCAnaGV4JyksIDMyKSxcbiAgICAgIHRvQnVmZmVyKHNpZy52KSxcbiAgICBdKVxuICApO1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIG9yIG5vdCB0aGUgZ2l2ZW4gdHggZGF0YSBoYXMgYSBzaWduYXR1cmVcbiAqXG4gKiBAcGFyYW0ge1R4RGF0YX0gdHhEYXRhIFRoZSB0cmFuc2FjdGlvbiBkYXRhIHRvIGNoZWNrIGZvciBzaWduYXR1cmVcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSB0eCBoYXMgYSBzaWduYXR1cmUsIGVsc2UgZmFsc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1NpZ25hdHVyZSh0eERhdGE6IFR4RGF0YSk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIHR4RGF0YS52ICE9PSB1bmRlZmluZWQgJiZcbiAgICB0eERhdGEuciAhPT0gdW5kZWZpbmVkICYmXG4gICAgdHhEYXRhLnMgIT09IHVuZGVmaW5lZCAmJlxuICAgIHR4RGF0YS52Lmxlbmd0aCA+IDAgJiZcbiAgICB0eERhdGEuci5sZW5ndGggPiAwICYmXG4gICAgdHhEYXRhLnMubGVuZ3RoID4gMFxuICApO1xufVxuXG50eXBlIFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nID0gc3RyaW5nIHwgQnVmZmVyIHwgQk4gfCBSZWN1cnNpdmVCdWZmZXJPclN0cmluZ1tdO1xuXG4vKipcbiAqIEdldCB0aGUgcmF3IGRhdGEgZGVjb2RlZCBmb3Igc29tZSB0eXBlc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nW119IHR5cGVzIEFCSSB0eXBlcyBkZWZpbml0aW9uXG4gKiBAcGFyYW0ge0J1ZmZlcn0gc2VyaWFsaXplZEFyZ3MgZW5jb2RlZCBhcmdzXG4gKiBAcmV0dXJucyB7QnVmZmVyW119IHRoZSBkZWNvZGVkIHJhd1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmF3RGVjb2RlZCh0eXBlczogc3RyaW5nW10sIHNlcmlhbGl6ZWRBcmdzOiBCdWZmZXIpOiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZ1tdIHtcbiAgZnVuY3Rpb24gbm9ybWFsaXplKHY6IHVua25vd24sIGk6IG51bWJlcik6IHVua25vd24ge1xuICAgIGlmIChCTi5pc0JOKHYpKSB7XG4gICAgICByZXR1cm4gdjtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2ID09PSAnc3RyaW5nJyB8fCBCdWZmZXIuaXNCdWZmZXIodikpIHtcbiAgICAgIHJldHVybiB2O1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2KSkge1xuICAgICAgcmV0dXJuIHYubWFwKG5vcm1hbGl6ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm9yICR7dHlwZXN9WyR7aX1dIGdvdCAke3R5cGVvZiB2fWApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBFdGhlcmV1bUFiaS5yYXdEZWNvZGUodHlwZXMsIHNlcmlhbGl6ZWRBcmdzKS5tYXAobm9ybWFsaXplKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGJ1ZmZlcmVkIGJ5dGVjb2RlIGZyb20gcmF3RGF0YSB1c2luZyBhIG1ldGhvZElkIGFzIGRlbGltaXRlclxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RJZCB0aGUgaGV4IGVuY29kZWQgbWV0aG9kIElkXG4gKiBAcGFyYW0ge3N0cmluZ30gcmF3RGF0YSB0aGUgaGV4IGVuY29kZWQgcmF3IGRhdGFcbiAqIEByZXR1cm5zIHtCdWZmZXJ9IGRhdGEgYnVmZmVyZWQgYnl0ZWNvZGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEJ1ZmZlcmVkQnl0ZUNvZGUobWV0aG9kSWQ6IHN0cmluZywgcmF3RGF0YTogc3RyaW5nKTogQnVmZmVyIHtcbiAgY29uc3Qgc3BsaXRCeXRlY29kZSA9IHJhd0RhdGEuc3BsaXQobWV0aG9kSWQpO1xuICBpZiAoc3BsaXRCeXRlY29kZS5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIHNlbmQgYnl0ZWNvZGU6ICR7cmF3RGF0YX1gKTtcbiAgfVxuICBpZiAoc3BsaXRCeXRlY29kZVsxXS5sZW5ndGggJSAyICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBzZW5kIGJ5dGVjb2RlOiAke3Jhd0RhdGF9ICh3cm9uZyBsZW5naHQpYCk7XG4gIH1cbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKHNwbGl0Qnl0ZWNvZGVbMV0sICdoZXgnKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHN0YXRpY3MgY29pbiBvYmplY3QgbWF0Y2hpbmcgYSBnaXZlbiBjb250cmFjdCBhZGRyZXNzIGlmIGl0IGV4aXN0c1xuICpcbiAqIEBwYXJhbSB0b2tlbkNvbnRyYWN0QWRkcmVzcyBUaGUgY29udHJhY3QgYWRkcmVzcyB0byBtYXRjaCBhZ2FpbnN0XG4gKiBAcmV0dXJucyBzdGF0aWNzIEJhc2VDb2luIG9iamVjdCBmb3IgdGhlIG1hdGNoaW5nIHRva2VuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb2tlbih0b2tlbkNvbnRyYWN0QWRkcmVzczogc3RyaW5nLCBuZXR3b3JrOiBCYXNlTmV0d29yayk6IFJlYWRvbmx5PEJhc2VDb2luPiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHRva2VucyA9IGNvaW5zLmZpbHRlcigoY29pbikgPT4ge1xuICAgIGlmIChjb2luIGluc3RhbmNlb2YgQ29udHJhY3RBZGRyZXNzRGVmaW5lZFRva2VuKSB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBjb2luLm5ldHdvcmsudHlwZSA9PT0gbmV0d29yay50eXBlICYmIGNvaW4uY29udHJhY3RBZGRyZXNzLnRvTG93ZXJDYXNlKCkgPT09IHRva2VuQ29udHJhY3RBZGRyZXNzLnRvTG93ZXJDYXNlKClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfSk7XG5cbiAgLy8gaWYgbGVuZ3RoIG9mIHRva2VucyBpcyAxLCByZXR1cm4gdGhlIGZpcnN0LCBlbHNlIHJldHVybiB1bmRlZmluZWRcbiAgLy8gQ2FuJ3QgZGlyZWN0bHkgaW5kZXggaW50byB0b2tlbnMsIG9yIGNhbGwgYGxlbmd0aGAsIHNvIHdlIHVzZSBtYXAgdG8gZ2V0IGFuIGFycmF5XG4gIGNvbnN0IHRva2Vuc0FycmF5ID0gdG9rZW5zLm1hcCgodG9rZW4pID0+IHRva2VuKTtcbiAgaWYgKHRva2Vuc0FycmF5Lmxlbmd0aCA+PSAxKSB7XG4gICAgLy8gdGhlcmUgc2hvdWxkIG5ldmVyIGJlIHR3byB0b2tlbnMgd2l0aCB0aGUgc2FtZSBjb250cmFjdCBhZGRyZXNzLCBzbyB3ZSBhc3NlcnQgdGhhdCBoZXJlXG4gICAgYXNzZXJ0KHRva2Vuc0FycmF5Lmxlbmd0aCA9PT0gMSk7XG4gICAgcmV0dXJuIHRva2Vuc0FycmF5WzBdO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3JlYXRlIHdhbGxldCBtZXRob2QgY2FsbGluZyBkYXRhIGZvciB2MSB3YWxsZXRzXG4gKlxuICogQHBhcmFtIHtzdHJpbmdbXX0gd2FsbGV0T3duZXJzIC0gd2FsbGV0IG93bmVyIGFkZHJlc3NlcyBmb3Igd2FsbGV0IGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IHNhbHQgLSBUaGUgc2FsdCBmb3Igd2FsbGV0IGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uc1xuICogQHJldHVybnMge3N0cmluZ30gLSB0aGUgY3JlYXRlV2FsbGV0IG1ldGhvZCBlbmNvZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRWMVdhbGxldEluaXRpYWxpemF0aW9uRGF0YSh3YWxsZXRPd25lcnM6IHN0cmluZ1tdLCBzYWx0OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBzYWx0QnVmZmVyID0gc2V0TGVuZ3RoTGVmdCh0b0J1ZmZlcihzYWx0KSwgMzIpO1xuICBjb25zdCBwYXJhbXMgPSBbd2FsbGV0T3duZXJzLCBzYWx0QnVmZmVyXTtcbiAgY29uc3QgbWV0aG9kID0gRXRoZXJldW1BYmkubWV0aG9kSUQoJ2NyZWF0ZVdhbGxldCcsIGNyZWF0ZVYxV2FsbGV0VHlwZXMpO1xuICBjb25zdCBhcmdzID0gRXRoZXJldW1BYmkucmF3RW5jb2RlKGNyZWF0ZVYxV2FsbGV0VHlwZXMsIHBhcmFtcyk7XG4gIHJldHVybiBhZGRIZXhQcmVmaXgoQnVmZmVyLmNvbmNhdChbbWV0aG9kLCBhcmdzXSkudG9TdHJpbmcoJ2hleCcpKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjcmVhdGUgYWRkcmVzcyBtZXRob2QgY2FsbGluZyBkYXRhIGZvciB2MSwgdjIsIHY0IGZvcndhcmRlcnNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZUFkZHJlc3MgLSBUaGUgYWRkcmVzcyBvZiB0aGUgd2FsbGV0IGNvbnRyYWN0XG4gKiBAcGFyYW0ge3N0cmluZ30gc2FsdCAtIFRoZSBzYWx0IGZvciBhZGRyZXNzIGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IGZlZUFkZHJlc3MgLSBUaGUgZmVlIGFkZHJlc3MgZm9yIHRoZSBlbnRlcnByaXNlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIHRoZSBjcmVhdGVGb3J3YXJkZXIgbWV0aG9kIGVuY29kZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFYxQWRkcmVzc0luaXRpYWxpemF0aW9uRGF0YShiYXNlQWRkcmVzczogc3RyaW5nLCBzYWx0OiBzdHJpbmcsIGZlZUFkZHJlc3M/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBzYWx0QnVmZmVyID0gc2V0TGVuZ3RoTGVmdCh0b0J1ZmZlcihzYWx0KSwgMzIpO1xuICBjb25zdCB7IGNyZWF0ZUZvcndhcmRlclBhcmFtcywgY3JlYXRlRm9yd2FyZGVyVHlwZXMgfSA9IGdldENyZWF0ZUZvcndhcmRlclBhcmFtc0FuZFR5cGVzKFxuICAgIGJhc2VBZGRyZXNzLFxuICAgIHNhbHRCdWZmZXIsXG4gICAgZmVlQWRkcmVzc1xuICApO1xuXG4gIGNvbnN0IG1ldGhvZCA9IEV0aGVyZXVtQWJpLm1ldGhvZElEKCdjcmVhdGVGb3J3YXJkZXInLCBjcmVhdGVGb3J3YXJkZXJUeXBlcyk7XG4gIGNvbnN0IGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoY3JlYXRlRm9yd2FyZGVyVHlwZXMsIGNyZWF0ZUZvcndhcmRlclBhcmFtcyk7XG4gIHJldHVybiBhZGRIZXhQcmVmaXgoQnVmZmVyLmNvbmNhdChbbWV0aG9kLCBhcmdzXSkudG9TdHJpbmcoJ2hleCcpKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjcmVhdGUgYWRkcmVzcyBtZXRob2QgY2FsbGluZyBkYXRhIGZvciBhbGwgZm9yd2FyZGVyIHZlcnNpb25zXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGZvcndhcmRlclZlcnNpb24gLSBUaGUgdmVyc2lvbiBvZiB0aGUgZm9yd2FyZGVyIHRvIGNyZWF0ZVxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2VBZGRyZXNzIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldCBjb250cmFjdFxuICogQHBhcmFtIHtzdHJpbmd9IHNhbHQgLSBUaGUgc2FsdCBmb3IgYWRkcmVzcyBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvbnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBmZWVBZGRyZXNzIC0gVGhlIGZlZSBhZGRyZXNzIGZvciB0aGUgZW50ZXJwcmlzZVxuICogQHJldHVybnMge3N0cmluZ30gLSB0aGUgY3JlYXRlRm9yd2FyZGVyIG1ldGhvZCBlbmNvZGVkXG4gKlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWRkcmVzc0luaXREYXRhQWxsRm9yd2FyZGVyVmVyc2lvbnMoXG4gIGZvcndhcmRlclZlcnNpb246IG51bWJlcixcbiAgYmFzZUFkZHJlc3M6IHN0cmluZyxcbiAgc2FsdDogc3RyaW5nLFxuICBmZWVBZGRyZXNzPzogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBpZiAoZm9yd2FyZGVyVmVyc2lvbiA9PT0gZGVmYXVsdEZvcndhcmRlclZlcnNpb24pIHtcbiAgICByZXR1cm4gZ2V0QWRkcmVzc0luaXRpYWxpemF0aW9uRGF0YSgpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBnZXRWMUFkZHJlc3NJbml0aWFsaXphdGlvbkRhdGEoYmFzZUFkZHJlc3MsIHNhbHQsIGZlZUFkZHJlc3MpO1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3JlYXRlRm9yd2FyZGVyVHlwZXMgYW5kIGNyZWF0ZUZvcndhcmRlclBhcmFtcyBmb3IgYWxsIGZvcndhcmRlciB2ZXJzaW9uc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlQWRkcmVzcyAtIFRoZSBhZGRyZXNzIG9mIHRoZSB3YWxsZXQgY29udHJhY3RcbiAqIEBwYXJhbSB7QnVmZmVyfSBzYWx0QnVmZmVyIC0gVGhlIHNhbHQgZm9yIGFkZHJlc3MgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBmZWVBZGRyZXNzIC0gVGhlIGZlZSBhZGRyZXNzIGZvciB0aGUgZW50ZXJwcmlzZVxuICogQHJldHVybnMge2NyZWF0ZUZvcndhcmRlclBhcmFtczogKHN0cmluZyB8IEJ1ZmZlcilbXSwgY3JlYXRlRm9yd2FyZGVyVHlwZXM6IHN0cmluZ1tdfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q3JlYXRlRm9yd2FyZGVyUGFyYW1zQW5kVHlwZXMoXG4gIGJhc2VBZGRyZXNzOiBzdHJpbmcsXG4gIHNhbHRCdWZmZXI6IEJ1ZmZlcixcbiAgZmVlQWRkcmVzcz86IHN0cmluZ1xuKTogeyBjcmVhdGVGb3J3YXJkZXJQYXJhbXM6IChzdHJpbmcgfCBCdWZmZXIpW107IGNyZWF0ZUZvcndhcmRlclR5cGVzOiBzdHJpbmdbXSB9IHtcbiAgbGV0IGNyZWF0ZUZvcndhcmRlclBhcmFtcyA9IFtiYXNlQWRkcmVzcywgc2FsdEJ1ZmZlcl07XG4gIGxldCBjcmVhdGVGb3J3YXJkZXJUeXBlcyA9IGNyZWF0ZVYxRm9yd2FyZGVyVHlwZXM7XG4gIGlmIChmZWVBZGRyZXNzKSB7XG4gICAgY3JlYXRlRm9yd2FyZGVyUGFyYW1zID0gW2Jhc2VBZGRyZXNzLCBmZWVBZGRyZXNzLCBzYWx0QnVmZmVyXTtcbiAgICBjcmVhdGVGb3J3YXJkZXJUeXBlcyA9IGNyZWF0ZVY0Rm9yd2FyZGVyVHlwZXM7XG4gIH1cbiAgcmV0dXJuIHsgY3JlYXRlRm9yd2FyZGVyUGFyYW1zLCBjcmVhdGVGb3J3YXJkZXJUeXBlcyB9O1xufVxuXG4vKipcbiAqIERlY29kZSB0aGUgZ2l2ZW4gQUJJLWVuY29kZWQgY3JlYXRlIGZvcndhcmRlciBkYXRhIGFuZCByZXR1cm4gcGFyc2VkIGZpZWxkc1xuICpcbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGRlY29kZVxuICogQHJldHVybnMgcGFyc2VkIHRyYW5zZmVyIGRhdGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUZvcndhcmRlckNyZWF0aW9uRGF0YShkYXRhOiBzdHJpbmcpOiBGb3J3YXJkZXJJbml0aWFsaXphdGlvbkRhdGEge1xuICBpZiAoXG4gICAgIShcbiAgICAgIGRhdGEuc3RhcnRzV2l0aCh2NENyZWF0ZUZvcndhcmRlck1ldGhvZElkKSB8fFxuICAgICAgZGF0YS5zdGFydHNXaXRoKHYxQ3JlYXRlRm9yd2FyZGVyTWV0aG9kSWQpIHx8XG4gICAgICBkYXRhLnN0YXJ0c1dpdGgoY3JlYXRlRm9yd2FyZGVyTWV0aG9kSWQpXG4gICAgKVxuICApIHtcbiAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIGFkZHJlc3MgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGlmIChkYXRhLnN0YXJ0c1dpdGgoY3JlYXRlRm9yd2FyZGVyTWV0aG9kSWQpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGJhc2VBZGRyZXNzOiB1bmRlZmluZWQsXG4gICAgICBhZGRyZXNzQ3JlYXRpb25TYWx0OiB1bmRlZmluZWQsXG4gICAgICBmZWVBZGRyZXNzOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfSBlbHNlIGlmIChkYXRhLnN0YXJ0c1dpdGgodjFDcmVhdGVGb3J3YXJkZXJNZXRob2RJZCkpIHtcbiAgICBjb25zdCBbYmFzZUFkZHJlc3MsIHNhbHRCdWZmZXJdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGNyZWF0ZVYxRm9yd2FyZGVyVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKHYxQ3JlYXRlRm9yd2FyZGVyTWV0aG9kSWQsIGRhdGEpXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBiYXNlQWRkcmVzczogYWRkSGV4UHJlZml4KGJhc2VBZGRyZXNzIGFzIHN0cmluZyksXG4gICAgICBhZGRyZXNzQ3JlYXRpb25TYWx0OiBidWZmZXJUb0hleChzYWx0QnVmZmVyIGFzIEJ1ZmZlciksXG4gICAgICBmZWVBZGRyZXNzOiB1bmRlZmluZWQsXG4gICAgfSBhcyBjb25zdDtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBbYmFzZUFkZHJlc3MsIGZlZUFkZHJlc3MsIHNhbHRCdWZmZXJdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGNyZWF0ZVY0Rm9yd2FyZGVyVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKHY0Q3JlYXRlRm9yd2FyZGVyTWV0aG9kSWQsIGRhdGEpXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICBiYXNlQWRkcmVzczogYWRkSGV4UHJlZml4KGJhc2VBZGRyZXNzIGFzIHN0cmluZyksXG4gICAgICBhZGRyZXNzQ3JlYXRpb25TYWx0OiBidWZmZXJUb0hleChzYWx0QnVmZmVyIGFzIEJ1ZmZlciksXG4gICAgICBmZWVBZGRyZXNzOiBhZGRIZXhQcmVmaXgoZmVlQWRkcmVzcyBhcyBzdHJpbmcpLFxuICAgIH0gYXMgY29uc3Q7XG4gIH1cbn1cbiJdfQ==