@bitgo-beta/abstract-eth 1.0.2-beta.201 → 1.0.2-beta.2010

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 (172) hide show
  1. package/dist/src/abstractEthLikeCoin.d.ts +20 -9
  2. package/dist/src/abstractEthLikeCoin.d.ts.map +1 -1
  3. package/dist/src/abstractEthLikeCoin.js +46 -15
  4. package/dist/src/abstractEthLikeNewCoins.d.ts +847 -0
  5. package/dist/src/abstractEthLikeNewCoins.d.ts.map +1 -0
  6. package/dist/src/abstractEthLikeNewCoins.js +2545 -0
  7. package/dist/src/ethLikeToken.d.ts +38 -6
  8. package/dist/src/ethLikeToken.d.ts.map +1 -1
  9. package/dist/src/ethLikeToken.js +289 -10
  10. package/dist/src/index.d.ts +2 -0
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/index.js +8 -2
  13. package/dist/src/lib/constants.d.ts +4 -0
  14. package/dist/src/lib/constants.d.ts.map +1 -0
  15. package/dist/src/lib/constants.js +11 -0
  16. package/dist/src/lib/contractCall.d.ts +8 -0
  17. package/dist/src/lib/contractCall.d.ts.map +1 -0
  18. package/dist/src/lib/contractCall.js +17 -0
  19. package/dist/src/lib/decryptionDelegationBuilder.d.ts +90 -0
  20. package/dist/src/lib/decryptionDelegationBuilder.d.ts.map +1 -0
  21. package/dist/src/lib/decryptionDelegationBuilder.js +59 -0
  22. package/dist/src/lib/iface.d.ts +137 -0
  23. package/dist/src/lib/iface.d.ts.map +1 -0
  24. package/dist/src/lib/iface.js +8 -0
  25. package/dist/src/lib/index.d.ts +19 -0
  26. package/dist/src/lib/index.d.ts.map +1 -0
  27. package/dist/src/lib/index.js +60 -0
  28. package/dist/src/lib/keyPair.d.ts +26 -0
  29. package/dist/src/lib/keyPair.d.ts.map +1 -0
  30. package/dist/src/lib/keyPair.js +65 -0
  31. package/dist/src/lib/messages/eip191/eip191Message.d.ts +12 -0
  32. package/dist/src/lib/messages/eip191/eip191Message.d.ts.map +1 -0
  33. package/dist/src/lib/messages/eip191/eip191Message.js +25 -0
  34. package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts +19 -0
  35. package/dist/src/lib/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
  36. package/dist/src/lib/messages/eip191/eip191MessageBuilder.js +27 -0
  37. package/dist/src/lib/messages/eip191/index.d.ts +3 -0
  38. package/dist/src/lib/messages/eip191/index.d.ts.map +1 -0
  39. package/dist/src/lib/messages/eip191/index.js +19 -0
  40. package/dist/src/lib/messages/eip712/eip712Message.d.ts +6 -0
  41. package/dist/src/lib/messages/eip712/eip712Message.d.ts.map +1 -0
  42. package/dist/src/lib/messages/eip712/eip712Message.js +27 -0
  43. package/dist/src/lib/messages/eip712/eip712MessageBuilder.d.ts +7 -0
  44. package/dist/src/lib/messages/eip712/eip712MessageBuilder.d.ts.map +1 -0
  45. package/dist/src/lib/messages/eip712/eip712MessageBuilder.js +15 -0
  46. package/dist/src/lib/messages/eip712/index.d.ts +3 -0
  47. package/dist/src/lib/messages/eip712/index.d.ts.map +1 -0
  48. package/dist/src/lib/messages/eip712/index.js +19 -0
  49. package/dist/src/lib/messages/index.d.ts +4 -0
  50. package/dist/src/lib/messages/index.d.ts.map +1 -0
  51. package/dist/src/lib/messages/index.js +20 -0
  52. package/dist/src/lib/messages/messageBuilderFactory.d.ts +7 -0
  53. package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
  54. package/dist/src/lib/messages/messageBuilderFactory.js +23 -0
  55. package/dist/src/lib/transaction.d.ts +69 -0
  56. package/dist/src/lib/transaction.d.ts.map +1 -0
  57. package/dist/src/lib/transaction.js +149 -0
  58. package/dist/src/lib/transactionBuilder.d.ts +270 -0
  59. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  60. package/dist/src/lib/transactionBuilder.js +834 -0
  61. package/dist/src/lib/transferBuilder.d.ts +76 -0
  62. package/dist/src/lib/transferBuilder.d.ts.map +1 -0
  63. package/dist/src/lib/transferBuilder.js +307 -0
  64. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts +54 -0
  65. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts.map +1 -0
  66. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.js +120 -0
  67. package/dist/src/lib/transferBuilders/index.d.ts +4 -0
  68. package/dist/src/lib/transferBuilders/index.d.ts.map +1 -0
  69. package/dist/src/lib/transferBuilders/index.js +20 -0
  70. package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts +17 -0
  71. package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts.map +1 -0
  72. package/dist/src/lib/transferBuilders/transferBuilderERC1155.js +96 -0
  73. package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts +21 -0
  74. package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts.map +1 -0
  75. package/dist/src/lib/transferBuilders/transferBuilderERC721.js +91 -0
  76. package/dist/src/lib/types.d.ts +40 -0
  77. package/dist/src/lib/types.d.ts.map +1 -0
  78. package/dist/src/lib/types.js +140 -0
  79. package/dist/src/lib/utils.d.ts +310 -0
  80. package/dist/src/lib/utils.d.ts.map +1 -0
  81. package/dist/src/lib/utils.js +851 -0
  82. package/dist/src/lib/walletUtil.d.ts +42 -0
  83. package/dist/src/lib/walletUtil.d.ts.map +1 -0
  84. package/dist/src/lib/walletUtil.js +45 -0
  85. package/dist/src/lib/zamaUtils.d.ts +73 -0
  86. package/dist/src/lib/zamaUtils.d.ts.map +1 -0
  87. package/dist/src/lib/zamaUtils.js +159 -0
  88. package/dist/src/types.d.ts +9 -0
  89. package/dist/src/types.d.ts.map +1 -0
  90. package/dist/src/types.js +3 -0
  91. package/dist/test/index.d.ts +2 -0
  92. package/dist/test/index.d.ts.map +1 -0
  93. package/dist/test/index.js +18 -0
  94. package/dist/test/unit/coin.d.ts +8 -0
  95. package/dist/test/unit/coin.d.ts.map +1 -0
  96. package/dist/test/unit/coin.js +577 -0
  97. package/dist/test/unit/decryptionDelegationBuilder.d.ts +2 -0
  98. package/dist/test/unit/decryptionDelegationBuilder.d.ts.map +1 -0
  99. package/dist/test/unit/decryptionDelegationBuilder.js +265 -0
  100. package/dist/test/unit/index.d.ts +8 -0
  101. package/dist/test/unit/index.d.ts.map +1 -0
  102. package/dist/test/unit/index.js +24 -0
  103. package/dist/test/unit/messages/abstractEthMessageBuilderTests.d.ts +3 -0
  104. package/dist/test/unit/messages/abstractEthMessageBuilderTests.d.ts.map +1 -0
  105. package/dist/test/unit/messages/abstractEthMessageBuilderTests.js +110 -0
  106. package/dist/test/unit/messages/abstractEthMessageTestTypes.d.ts +43 -0
  107. package/dist/test/unit/messages/abstractEthMessageTestTypes.d.ts.map +1 -0
  108. package/dist/test/unit/messages/abstractEthMessageTestTypes.js +3 -0
  109. package/dist/test/unit/messages/abstractEthMessagesTests.d.ts +3 -0
  110. package/dist/test/unit/messages/abstractEthMessagesTests.d.ts.map +1 -0
  111. package/dist/test/unit/messages/abstractEthMessagesTests.js +129 -0
  112. package/dist/test/unit/messages/eip191/eip191Message.d.ts +2 -0
  113. package/dist/test/unit/messages/eip191/eip191Message.d.ts.map +1 -0
  114. package/dist/test/unit/messages/eip191/eip191Message.js +15 -0
  115. package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts +2 -0
  116. package/dist/test/unit/messages/eip191/eip191MessageBuilder.d.ts.map +1 -0
  117. package/dist/test/unit/messages/eip191/eip191MessageBuilder.js +16 -0
  118. package/dist/test/unit/messages/eip191/fixtures.d.ts +109 -0
  119. package/dist/test/unit/messages/eip191/fixtures.d.ts.map +1 -0
  120. package/dist/test/unit/messages/eip191/fixtures.js +63 -0
  121. package/dist/test/unit/messages/eip712/eip712Message.d.ts +2 -0
  122. package/dist/test/unit/messages/eip712/eip712Message.d.ts.map +1 -0
  123. package/dist/test/unit/messages/eip712/eip712Message.js +15 -0
  124. package/dist/test/unit/messages/eip712/eip712MessageBuilder.d.ts +2 -0
  125. package/dist/test/unit/messages/eip712/eip712MessageBuilder.d.ts.map +1 -0
  126. package/dist/test/unit/messages/eip712/eip712MessageBuilder.js +16 -0
  127. package/dist/test/unit/messages/eip712/fixtures.d.ts +76 -0
  128. package/dist/test/unit/messages/eip712/fixtures.d.ts.map +1 -0
  129. package/dist/test/unit/messages/eip712/fixtures.js +120 -0
  130. package/dist/test/unit/messages/index.d.ts +4 -0
  131. package/dist/test/unit/messages/index.d.ts.map +1 -0
  132. package/dist/test/unit/messages/index.js +20 -0
  133. package/dist/test/unit/messages/messageBuilderFactory.d.ts +2 -0
  134. package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
  135. package/dist/test/unit/messages/messageBuilderFactory.js +52 -0
  136. package/dist/test/unit/token.d.ts +2 -0
  137. package/dist/test/unit/token.d.ts.map +1 -0
  138. package/dist/test/unit/token.js +37 -0
  139. package/dist/test/unit/transaction.d.ts +3 -0
  140. package/dist/test/unit/transaction.d.ts.map +1 -0
  141. package/dist/test/unit/transaction.js +73 -0
  142. package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +8 -0
  143. package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
  144. package/dist/test/unit/transactionBuilder/addressInitialization.js +95 -0
  145. package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts +3 -0
  146. package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts.map +1 -0
  147. package/dist/test/unit/transactionBuilder/decryptionDelegation.js +161 -0
  148. package/dist/test/unit/transactionBuilder/flushNft.d.ts +2 -0
  149. package/dist/test/unit/transactionBuilder/flushNft.d.ts.map +1 -0
  150. package/dist/test/unit/transactionBuilder/flushNft.js +381 -0
  151. package/dist/test/unit/transactionBuilder/index.d.ts +6 -0
  152. package/dist/test/unit/transactionBuilder/index.d.ts.map +1 -0
  153. package/dist/test/unit/transactionBuilder/index.js +22 -0
  154. package/dist/test/unit/transactionBuilder/send.d.ts +3 -0
  155. package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
  156. package/dist/test/unit/transactionBuilder/send.js +197 -0
  157. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +11 -0
  158. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
  159. package/dist/test/unit/transactionBuilder/walletInitialization.js +137 -0
  160. package/dist/test/unit/transferBuilder.d.ts +2 -0
  161. package/dist/test/unit/transferBuilder.d.ts.map +1 -0
  162. package/dist/test/unit/transferBuilder.js +76 -0
  163. package/dist/test/unit/utils.d.ts +2 -0
  164. package/dist/test/unit/utils.d.ts.map +1 -0
  165. package/dist/test/unit/utils.js +214 -0
  166. package/dist/test/unit/zamaUtils.d.ts +2 -0
  167. package/dist/test/unit/zamaUtils.d.ts.map +1 -0
  168. package/dist/test/unit/zamaUtils.js +251 -0
  169. package/dist/tsconfig.tsbuildinfo +1 -8244
  170. package/package.json +34 -10
  171. package/.eslintignore +0 -5
  172. package/CHANGELOG.md +0 -166
@@ -0,0 +1,851 @@
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.getCommon = getCommon;
7
+ exports.signInternal = signInternal;
8
+ exports.sign = sign;
9
+ exports.sendMultiSigData = sendMultiSigData;
10
+ exports.sendMultiSigTokenData = sendMultiSigTokenData;
11
+ exports.flushTokensData = flushTokensData;
12
+ exports.flushCoinsData = flushCoinsData;
13
+ exports.flushERC721TokensData = flushERC721TokensData;
14
+ exports.decodeFlushERC721TokensData = decodeFlushERC721TokensData;
15
+ exports.flushERC1155TokensData = flushERC1155TokensData;
16
+ exports.decodeFlushERC1155TokensData = decodeFlushERC1155TokensData;
17
+ exports.getAddressInitializationData = getAddressInitializationData;
18
+ exports.isValidEthAddress = isValidEthAddress;
19
+ exports.isValidAmount = isValidAmount;
20
+ exports.decodeWalletCreationData = decodeWalletCreationData;
21
+ exports.decodeTransferData = decodeTransferData;
22
+ exports.decodeTokenTransferData = decodeTokenTransferData;
23
+ exports.decodeERC721TransferData = decodeERC721TransferData;
24
+ exports.decodeERC1155TransferData = decodeERC1155TransferData;
25
+ exports.decodeNativeTransferData = decodeNativeTransferData;
26
+ exports.decodeFlushTokensData = decodeFlushTokensData;
27
+ exports.classifyTransaction = classifyTransaction;
28
+ exports.numberToHexString = numberToHexString;
29
+ exports.hexStringToNumber = hexStringToNumber;
30
+ exports.calculateForwarderAddress = calculateForwarderAddress;
31
+ exports.calculateForwarderV1Address = calculateForwarderV1Address;
32
+ exports.getProxyInitcode = getProxyInitcode;
33
+ exports.toStringSig = toStringSig;
34
+ exports.hasSignature = hasSignature;
35
+ exports.getRawDecoded = getRawDecoded;
36
+ exports.getBufferedByteCode = getBufferedByteCode;
37
+ exports.getToken = getToken;
38
+ exports.getV1WalletInitializationData = getV1WalletInitializationData;
39
+ exports.getV1AddressInitializationData = getV1AddressInitializationData;
40
+ exports.getAddressInitDataAllForwarderVersions = getAddressInitDataAllForwarderVersions;
41
+ exports.getCreateForwarderParamsAndTypes = getCreateForwarderParamsAndTypes;
42
+ exports.decodeForwarderCreationData = decodeForwarderCreationData;
43
+ exports.recoveryBlockchainExplorerQuery = recoveryBlockchainExplorerQuery;
44
+ exports.getDefaultExpireTime = getDefaultExpireTime;
45
+ const buffer_1 = require("buffer");
46
+ const superagent_1 = __importDefault(require("superagent"));
47
+ const assert_1 = __importDefault(require("assert"));
48
+ const ethereumjs_util_1 = require("ethereumjs-util");
49
+ const statics_1 = require("@bitgo-beta/statics");
50
+ const ethereumjs_abi_1 = __importDefault(require("ethereumjs-abi"));
51
+ const common_1 = __importDefault(require("@ethereumjs/common"));
52
+ const bn_js_1 = __importDefault(require("bn.js"));
53
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
54
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
55
+ const walletUtil_1 = require("./walletUtil");
56
+ const types_1 = require("./types");
57
+ const zamaUtils_1 = require("./zamaUtils");
58
+ /**
59
+ * @param network
60
+ */
61
+ function getCommon(network) {
62
+ return common_1.default.forCustomChain(
63
+ // use the mainnet config as a base, override chain ids and network name
64
+ 'mainnet', {
65
+ name: network.type,
66
+ networkId: network.chainId,
67
+ chainId: network.chainId,
68
+ }, 'london');
69
+ }
70
+ /**
71
+ * Signs the transaction using the appropriate algorithm
72
+ * and the provided common for the blockchain
73
+ *
74
+ * @param {TxData} transactionData the transaction data to sign
75
+ * @param {KeyPair} keyPair the signer's keypair
76
+ * @param {EthereumCommon} customCommon the network's custom common
77
+ * @returns {string} the transaction signed and encoded
78
+ */
79
+ async function signInternal(transactionData, keyPair, customCommon) {
80
+ if (!keyPair.getKeys().prv) {
81
+ throw new sdk_core_1.SigningError('Missing private key');
82
+ }
83
+ const ethTx = types_1.EthTransactionData.fromJson(transactionData, customCommon);
84
+ ethTx.sign(keyPair);
85
+ return ethTx.toSerialized();
86
+ }
87
+ /**
88
+ * Signs the transaction using the appropriate algorithm
89
+ *
90
+ * @param {TxData} transactionData the transaction data to sign
91
+ * @param {KeyPair} keyPair the signer's keypair
92
+ * @returns {string} the transaction signed and encoded
93
+ */
94
+ async function sign(transactionData, keyPair) {
95
+ return signInternal(transactionData, keyPair, getCommon(statics_1.coins.get('teth').network));
96
+ }
97
+ /**
98
+ * Returns the contract method encoded data
99
+ *
100
+ * @param {string} to destination address
101
+ * @param {number} value Amount to tranfer
102
+ * @param {string} data aditional method call data
103
+ * @param {number} expireTime expiration time for the transaction in seconds
104
+ * @param {number} sequenceId sequence id
105
+ * @param {string} signature signature of the call
106
+ * @returns {string} -- the contract method encoded data
107
+ */
108
+ function sendMultiSigData(to, value, data, expireTime, sequenceId, signature) {
109
+ const params = [to, value, (0, ethereumjs_util_1.toBuffer)(data), expireTime, sequenceId, (0, ethereumjs_util_1.toBuffer)(signature)];
110
+ const method = ethereumjs_abi_1.default.methodID('sendMultiSig', walletUtil_1.sendMultiSigTypes);
111
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.sendMultiSigTypes, params);
112
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
113
+ }
114
+ /**
115
+ * Returns the contract method encoded data
116
+ *
117
+ * @param {string} to destination address
118
+ * @param {number} value Amount to tranfer
119
+ * @param {string} tokenContractAddress the address of the erc20 token contract
120
+ * @param {number} expireTime expiration time for the transaction in seconds
121
+ * @param {number} sequenceId sequence id
122
+ * @param {string} signature signature of the call
123
+ * @returns {string} -- the contract method encoded data
124
+ */
125
+ function sendMultiSigTokenData(to, value, tokenContractAddress, expireTime, sequenceId, signature) {
126
+ const params = [to, value, tokenContractAddress, expireTime, sequenceId, (0, ethereumjs_util_1.toBuffer)(signature)];
127
+ const method = ethereumjs_abi_1.default.methodID('sendMultiSigToken', walletUtil_1.sendMultiSigTokenTypes);
128
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.sendMultiSigTokenTypes, params);
129
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
130
+ }
131
+ /**
132
+ * Get the data required to make a flush tokens contract call
133
+ *
134
+ * @param forwarderAddress The forwarder address to flush
135
+ * @param tokenAddress The token address to flush from
136
+ */
137
+ function flushTokensData(forwarderAddress, tokenAddress, forwarderVersion) {
138
+ let params;
139
+ let method;
140
+ let args;
141
+ if (forwarderVersion >= 4) {
142
+ params = [tokenAddress];
143
+ method = ethereumjs_abi_1.default.methodID('flushTokens', walletUtil_1.flushTokensTypesv4);
144
+ args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushTokensTypesv4, params);
145
+ }
146
+ else {
147
+ params = [forwarderAddress, tokenAddress];
148
+ method = ethereumjs_abi_1.default.methodID('flushForwarderTokens', walletUtil_1.flushTokensTypes);
149
+ args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushTokensTypes, params);
150
+ }
151
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
152
+ }
153
+ /**
154
+ * Get the data required to make a flush native coins contract call
155
+ */
156
+ function flushCoinsData() {
157
+ const params = [];
158
+ const method = ethereumjs_abi_1.default.methodID('flush', walletUtil_1.flushCoinsTypes);
159
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushCoinsTypes, params);
160
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
161
+ }
162
+ /**
163
+ * Get the data required to make a flush ERC721 tokens contract call
164
+ * @param forwarderAddress - The forwarder address (for v0-v3)
165
+ * @param tokenAddress - The ERC721 token contract address
166
+ * @param tokenId - The token ID to flush
167
+ * @param forwarderVersion - The forwarder version
168
+ */
169
+ function flushERC721TokensData(forwarderAddress, tokenAddress, tokenId, forwarderVersion) {
170
+ let params;
171
+ let method;
172
+ let args;
173
+ if (forwarderVersion >= 4) {
174
+ params = [tokenAddress, tokenId];
175
+ method = ethereumjs_abi_1.default.methodID('flushERC721Token', walletUtil_1.flushERC721TokensTypesv4);
176
+ args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushERC721TokensTypesv4, params);
177
+ }
178
+ else {
179
+ params = [forwarderAddress, tokenAddress, tokenId];
180
+ method = ethereumjs_abi_1.default.methodID('flushERC721ForwarderTokens', walletUtil_1.flushERC721TokensTypes);
181
+ args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushERC721TokensTypes, params);
182
+ }
183
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
184
+ }
185
+ /**
186
+ * Decode the given ABI-encoded flush ERC721 tokens data
187
+ * @param data The data to decode
188
+ * @param to The to address (contract address for v4+)
189
+ * @returns parsed flush data with forwarderAddress, tokenAddress, tokenId and forwarderVersion
190
+ */
191
+ function decodeFlushERC721TokensData(data, to) {
192
+ if (data.startsWith(walletUtil_1.flushERC721ForwarderTokensMethodIdV4)) {
193
+ if (!to) {
194
+ throw new sdk_core_1.BuildTransactionError(`Missing to address: ${to}`);
195
+ }
196
+ const [tokenAddress, tokenId] = getRawDecoded(walletUtil_1.flushERC721TokensTypesv4, getBufferedByteCode(walletUtil_1.flushERC721ForwarderTokensMethodIdV4, data));
197
+ return {
198
+ forwarderAddress: to,
199
+ tokenAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenAddress),
200
+ tokenId: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed(),
201
+ forwarderVersion: 4,
202
+ };
203
+ }
204
+ else if (data.startsWith(walletUtil_1.flushERC721ForwarderTokensMethodId)) {
205
+ const [forwarderAddress, tokenAddress, tokenId] = getRawDecoded(walletUtil_1.flushERC721TokensTypes, getBufferedByteCode(walletUtil_1.flushERC721ForwarderTokensMethodId, data));
206
+ return {
207
+ forwarderAddress: (0, ethereumjs_util_1.addHexPrefix)(forwarderAddress),
208
+ tokenAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenAddress),
209
+ tokenId: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed(),
210
+ };
211
+ }
212
+ throw new sdk_core_1.BuildTransactionError(`Invalid flush ERC721 bytecode: ${data}`);
213
+ }
214
+ /**
215
+ * Get the data required to make a flush ERC1155 tokens contract call
216
+ * @param forwarderAddress - The forwarder address (for v0-v3)
217
+ * @param tokenAddress - The ERC1155 token contract address
218
+ * @param tokenId - The token ID to flush
219
+ * @param forwarderVersion - The forwarder version
220
+ */
221
+ function flushERC1155TokensData(forwarderAddress, tokenAddress, tokenId, forwarderVersion) {
222
+ let params;
223
+ let method;
224
+ let args;
225
+ if (forwarderVersion >= 4) {
226
+ params = [tokenAddress, tokenId];
227
+ method = ethereumjs_abi_1.default.methodID('flushERC1155Tokens', walletUtil_1.flushERC1155TokensTypesv4);
228
+ args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushERC1155TokensTypesv4, params);
229
+ }
230
+ else {
231
+ params = [forwarderAddress, tokenAddress, tokenId];
232
+ method = ethereumjs_abi_1.default.methodID('flushERC1155ForwarderTokens', walletUtil_1.flushERC1155TokensTypes);
233
+ args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.flushERC1155TokensTypes, params);
234
+ }
235
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
236
+ }
237
+ /**
238
+ * Decode the given ABI-encoded flush ERC1155 tokens data
239
+ * @param data The data to decode
240
+ * @param to The to address (contract address for v4+)
241
+ * @returns parsed flush data with forwarderAddress, tokenAddress, tokenId and forwarderVersion
242
+ */
243
+ function decodeFlushERC1155TokensData(data, to) {
244
+ if (data.startsWith(walletUtil_1.flushERC1155ForwarderTokensMethodIdV4)) {
245
+ if (!to) {
246
+ throw new sdk_core_1.BuildTransactionError(`Missing to address: ${to}`);
247
+ }
248
+ const [tokenAddress, tokenId] = getRawDecoded(walletUtil_1.flushERC1155TokensTypesv4, getBufferedByteCode(walletUtil_1.flushERC1155ForwarderTokensMethodIdV4, data));
249
+ return {
250
+ forwarderAddress: to,
251
+ tokenAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenAddress),
252
+ tokenId: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed(),
253
+ forwarderVersion: 4,
254
+ };
255
+ }
256
+ else if (data.startsWith(walletUtil_1.flushERC1155ForwarderTokensMethodId)) {
257
+ const [forwarderAddress, tokenAddress, tokenId] = getRawDecoded(walletUtil_1.flushERC1155TokensTypes, getBufferedByteCode(walletUtil_1.flushERC1155ForwarderTokensMethodId, data));
258
+ return {
259
+ forwarderAddress: (0, ethereumjs_util_1.addHexPrefix)(forwarderAddress),
260
+ tokenAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenAddress),
261
+ tokenId: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed(),
262
+ };
263
+ }
264
+ throw new sdk_core_1.BuildTransactionError(`Invalid flush ERC1155 bytecode: ${data}`);
265
+ }
266
+ /**
267
+ * Returns the create forwarder method calling data
268
+ *
269
+ * @returns {string} - the createForwarder method encoded
270
+ */
271
+ function getAddressInitializationData() {
272
+ return walletUtil_1.createForwarderMethodId;
273
+ }
274
+ /**
275
+ * Returns whether or not the string is a valid Eth address
276
+ *
277
+ * @param {string} address - the tx hash to validate
278
+ * @returns {boolean} - the validation result
279
+ */
280
+ function isValidEthAddress(address) {
281
+ return (0, ethereumjs_util_1.isValidAddress)(address);
282
+ }
283
+ /**
284
+ * Returns whether or not the string is a valid amount number
285
+ *
286
+ * @param {string} amount - the string to validate
287
+ * @returns {boolean} - the validation result
288
+ */
289
+ function isValidAmount(amount) {
290
+ const bigNumberAmount = new bignumber_js_1.default(amount);
291
+ return bigNumberAmount.isInteger() && bigNumberAmount.isGreaterThanOrEqualTo(0);
292
+ }
293
+ /**
294
+ * Returns the smart contract encoded data
295
+ *
296
+ * @param {string} data The wallet creation data to decode
297
+ * @returns {string[]} - The list of signer addresses
298
+ */
299
+ function decodeWalletCreationData(data) {
300
+ if (!(data.startsWith(walletUtil_1.walletInitializationFirstBytes) || data.startsWith(walletUtil_1.v1CreateWalletMethodId))) {
301
+ throw new sdk_core_1.BuildTransactionError(`Invalid wallet bytecode: ${data}`);
302
+ }
303
+ if (data.startsWith(walletUtil_1.walletInitializationFirstBytes)) {
304
+ const dataBuffer = buffer_1.Buffer.from(data.slice(2), 'hex');
305
+ // the last 160 bytes contain the serialized address array
306
+ const serializedSigners = dataBuffer.slice(-160);
307
+ const resultEncodedParameters = ethereumjs_abi_1.default.rawDecode(walletUtil_1.walletSimpleConstructor, serializedSigners);
308
+ if (resultEncodedParameters.length !== 1) {
309
+ throw new sdk_core_1.BuildTransactionError(`Could not decode wallet constructor bytecode: ${resultEncodedParameters}`);
310
+ }
311
+ const addresses = resultEncodedParameters[0];
312
+ if (addresses.length !== 3) {
313
+ throw new sdk_core_1.BuildTransactionError(`invalid number of addresses in parsed constructor: ${addresses}`);
314
+ }
315
+ // sometimes ethereumjs-abi removes 0 padding at the start of addresses,
316
+ // so we should pad until they are the standard 20 bytes
317
+ const paddedAddresses = addresses.map((address) => (0, ethereumjs_util_1.stripHexPrefix)(address.toString('hex')).padStart(40, '0'));
318
+ return { owners: paddedAddresses.map((address) => (0, ethereumjs_util_1.addHexPrefix)(address)) };
319
+ }
320
+ else {
321
+ const decodedDataForWalletCreation = getRawDecoded(walletUtil_1.createV1WalletTypes, getBufferedByteCode(walletUtil_1.v1CreateWalletMethodId, data));
322
+ const addresses = decodedDataForWalletCreation[0];
323
+ const saltBuffer = decodedDataForWalletCreation[1];
324
+ const salt = (0, ethereumjs_util_1.bufferToHex)(saltBuffer);
325
+ const paddedAddresses = addresses.map((address) => (0, ethereumjs_util_1.stripHexPrefix)(address.toString()).padStart(40, '0'));
326
+ const owners = paddedAddresses.map((address) => (0, ethereumjs_util_1.addHexPrefix)(address));
327
+ return {
328
+ owners,
329
+ salt,
330
+ };
331
+ }
332
+ }
333
+ /**
334
+ * Decode the given ABI-encoded transfer data and return parsed fields
335
+ *
336
+ * @param data The data to decode
337
+ * @param isFirstSigner whether transaction is being built for a first signer
338
+ * @returns parsed transfer data
339
+ */
340
+ function decodeTransferData(data, isFirstSigner) {
341
+ if (data.startsWith(walletUtil_1.sendMultisigMethodId)) {
342
+ return decodeNativeTransferData(data, isFirstSigner);
343
+ }
344
+ else if (data.startsWith(walletUtil_1.sendMultisigTokenMethodId)) {
345
+ return decodeTokenTransferData(data, isFirstSigner);
346
+ }
347
+ else {
348
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
349
+ }
350
+ }
351
+ /**
352
+ * Decode the given ABI-encoded transfer data for the sendMultisigToken function and return parsed fields
353
+ *
354
+ * @param data The data to decode
355
+ * @param isFirstSigner whether transaction is being built for a first signer
356
+ * @returns parsed token transfer data
357
+ */
358
+ function decodeTokenTransferData(data, isFirstSigner) {
359
+ if (!data.startsWith(walletUtil_1.sendMultisigTokenMethodId)) {
360
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
361
+ }
362
+ let to;
363
+ let amount;
364
+ let tokenContractAddress;
365
+ let expireTime;
366
+ let sequenceId;
367
+ let signature;
368
+ let prefix;
369
+ if (!isFirstSigner) {
370
+ [to, amount, tokenContractAddress, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTokenTypes, getBufferedByteCode(walletUtil_1.sendMultisigTokenMethodId, data));
371
+ }
372
+ else {
373
+ [prefix, to, amount, tokenContractAddress, expireTime, sequenceId] = getRawDecoded(walletUtil_1.sendMultiSigTokenTypesFirstSigner, getBufferedByteCode(walletUtil_1.sendMultisigTokenMethodId, data));
374
+ }
375
+ return {
376
+ operationHashPrefix: isFirstSigner ? prefix : undefined,
377
+ to: (0, ethereumjs_util_1.addHexPrefix)(to),
378
+ amount: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(amount)).toFixed(),
379
+ expireTime: (0, ethereumjs_util_1.bufferToInt)(expireTime),
380
+ sequenceId: (0, ethereumjs_util_1.bufferToInt)(sequenceId),
381
+ signature: (0, ethereumjs_util_1.bufferToHex)(signature),
382
+ tokenContractAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenContractAddress),
383
+ };
384
+ }
385
+ function decodeERC721TransferData(data) {
386
+ if (!data.startsWith(walletUtil_1.sendMultisigMethodId)) {
387
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
388
+ }
389
+ const [to, amount, internalData, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTypes, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
390
+ const internalDataHex = (0, ethereumjs_util_1.bufferToHex)(internalData);
391
+ if (internalDataHex.startsWith(walletUtil_1.ERC721SafeTransferTypeMethodId)) {
392
+ const [from, receiver, tokenId, userSentData] = getRawDecoded(walletUtil_1.ERC721SafeTransferTypes, getBufferedByteCode(walletUtil_1.ERC721SafeTransferTypeMethodId, internalDataHex));
393
+ return {
394
+ to: (0, ethereumjs_util_1.addHexPrefix)(receiver),
395
+ from: (0, ethereumjs_util_1.addHexPrefix)(from),
396
+ expireTime: (0, ethereumjs_util_1.bufferToInt)(expireTime),
397
+ amount: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(amount)).toFixed(),
398
+ tokenId: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed(),
399
+ sequenceId: (0, ethereumjs_util_1.bufferToInt)(sequenceId),
400
+ signature: (0, ethereumjs_util_1.bufferToHex)(signature),
401
+ tokenContractAddress: (0, ethereumjs_util_1.addHexPrefix)(to),
402
+ userData: (0, ethereumjs_util_1.bufferToHex)(userSentData),
403
+ };
404
+ }
405
+ if (internalDataHex.startsWith(walletUtil_1.ERC721TransferFromMethodId)) {
406
+ const [from, receiver, tokenId] = getRawDecoded(walletUtil_1.ERC721TransferFromTypes, getBufferedByteCode(walletUtil_1.ERC721TransferFromMethodId, internalDataHex));
407
+ return {
408
+ to: (0, ethereumjs_util_1.addHexPrefix)(receiver),
409
+ from: (0, ethereumjs_util_1.addHexPrefix)(from),
410
+ expireTime: (0, ethereumjs_util_1.bufferToInt)(expireTime),
411
+ amount: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(amount)).toFixed(),
412
+ tokenId: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed(),
413
+ sequenceId: (0, ethereumjs_util_1.bufferToInt)(sequenceId),
414
+ signature: (0, ethereumjs_util_1.bufferToHex)(signature),
415
+ tokenContractAddress: (0, ethereumjs_util_1.addHexPrefix)(to),
416
+ userData: '',
417
+ };
418
+ }
419
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
420
+ }
421
+ function decodeERC1155TransferData(data) {
422
+ let from, receiver, userSentData;
423
+ let tokenIds;
424
+ let values;
425
+ if (!data.startsWith(walletUtil_1.sendMultisigMethodId)) {
426
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
427
+ }
428
+ const [to, amount, internalData, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTypes, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
429
+ const internalDataHex = (0, ethereumjs_util_1.bufferToHex)(internalData);
430
+ if (internalDataHex.startsWith(walletUtil_1.ERC1155SafeTransferTypeMethodId)) {
431
+ let tokenId;
432
+ let value;
433
+ [from, receiver, tokenId, value, userSentData] = getRawDecoded(walletUtil_1.ERC1155SafeTransferTypes, getBufferedByteCode(walletUtil_1.ERC1155SafeTransferTypeMethodId, internalDataHex));
434
+ tokenIds = [new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(tokenId)).toFixed()];
435
+ values = [new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(value)).toFixed()];
436
+ }
437
+ else if ((0, ethereumjs_util_1.bufferToHex)(internalData).startsWith(walletUtil_1.ERC1155BatchTransferTypeMethodId)) {
438
+ let tempTokenIds, tempValues;
439
+ [from, receiver, tempTokenIds, tempValues, userSentData] = getRawDecoded(walletUtil_1.ERC1155BatchTransferTypes, getBufferedByteCode(walletUtil_1.ERC1155BatchTransferTypeMethodId, internalDataHex));
440
+ tokenIds = tempTokenIds.map((x) => new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(x)).toFixed());
441
+ values = tempValues.map((x) => new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(x)).toFixed());
442
+ }
443
+ else {
444
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
445
+ }
446
+ return {
447
+ to: (0, ethereumjs_util_1.addHexPrefix)(receiver),
448
+ from: (0, ethereumjs_util_1.addHexPrefix)(from),
449
+ expireTime: (0, ethereumjs_util_1.bufferToInt)(expireTime),
450
+ amount: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(amount)).toFixed(),
451
+ tokenIds,
452
+ values,
453
+ sequenceId: (0, ethereumjs_util_1.bufferToInt)(sequenceId),
454
+ signature: (0, ethereumjs_util_1.bufferToHex)(signature),
455
+ tokenContractAddress: (0, ethereumjs_util_1.addHexPrefix)(to),
456
+ userData: userSentData,
457
+ };
458
+ }
459
+ /**
460
+ * Decode the given ABI-encoded transfer data for the sendMultisig function and return parsed fields
461
+ *
462
+ * @param data The data to decode
463
+ * @param isFirstSigner whether transaction is being built for a first signer
464
+ * @returns parsed transfer data
465
+ */
466
+ function decodeNativeTransferData(data, isFirstSigner) {
467
+ if (!data.startsWith(walletUtil_1.sendMultisigMethodId)) {
468
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
469
+ }
470
+ let to;
471
+ let amount;
472
+ let internalData;
473
+ let expireTime;
474
+ let sequenceId;
475
+ let signature;
476
+ let prefix;
477
+ if (!isFirstSigner) {
478
+ [to, amount, internalData, expireTime, sequenceId, signature] = getRawDecoded(walletUtil_1.sendMultiSigTypes, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
479
+ }
480
+ else {
481
+ [prefix, to, amount, internalData, expireTime, sequenceId] = getRawDecoded(walletUtil_1.sendMultiSigTypesFirstSigner, getBufferedByteCode(walletUtil_1.sendMultisigMethodId, data));
482
+ }
483
+ return {
484
+ operationHashPrefix: isFirstSigner ? prefix : undefined,
485
+ to: (0, ethereumjs_util_1.addHexPrefix)(to),
486
+ amount: new bignumber_js_1.default((0, ethereumjs_util_1.bufferToHex)(amount)).toFixed(),
487
+ expireTime: (0, ethereumjs_util_1.bufferToInt)(expireTime),
488
+ sequenceId: (0, ethereumjs_util_1.bufferToInt)(sequenceId),
489
+ signature: (0, ethereumjs_util_1.bufferToHex)(signature),
490
+ data: (0, ethereumjs_util_1.bufferToHex)(internalData),
491
+ };
492
+ }
493
+ /**
494
+ * Decode the given ABI-encoded flush tokens data and return parsed fields
495
+ *
496
+ * @param data The data to decode
497
+ * @param to Optional to parameter of tx
498
+ * @returns parsed transfer data
499
+ */
500
+ function decodeFlushTokensData(data, to) {
501
+ if (data.startsWith(walletUtil_1.flushForwarderTokensMethodId)) {
502
+ const [forwarderAddress, tokenAddress] = getRawDecoded(walletUtil_1.flushTokensTypes, getBufferedByteCode(walletUtil_1.flushForwarderTokensMethodId, data));
503
+ return {
504
+ forwarderAddress: (0, ethereumjs_util_1.addHexPrefix)(forwarderAddress),
505
+ tokenAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenAddress),
506
+ };
507
+ }
508
+ else if (data.startsWith(walletUtil_1.flushForwarderTokensMethodIdV4)) {
509
+ const [tokenAddress] = getRawDecoded(walletUtil_1.flushTokensTypesv4, getBufferedByteCode(walletUtil_1.flushForwarderTokensMethodIdV4, data));
510
+ if (!to) {
511
+ throw new sdk_core_1.BuildTransactionError(`Missing to address: ${to}`);
512
+ }
513
+ return {
514
+ forwarderAddress: to,
515
+ tokenAddress: (0, ethereumjs_util_1.addHexPrefix)(tokenAddress),
516
+ forwarderVersion: 4,
517
+ };
518
+ }
519
+ else {
520
+ throw new sdk_core_1.BuildTransactionError(`Invalid transfer bytecode: ${data}`);
521
+ }
522
+ }
523
+ /**
524
+ * Classify the given transaction data based as a transaction type.
525
+ * ETH transactions are defined by the first 8 bytes of the transaction data, also known as the method id
526
+ *
527
+ * @param {string} data The data to classify the transaction with
528
+ * @returns {TransactionType} The classified transaction type
529
+ */
530
+ function classifyTransaction(data) {
531
+ if (data.length < 10) {
532
+ // contract calls must have at least 4 bytes (method id) and '0x'
533
+ // if it doesn't have enough data to be a contract call it must be a single sig send
534
+ return sdk_core_1.TransactionType.SingleSigSend;
535
+ }
536
+ // TODO(STLX-1970): validate if we are going to constraint to some methods allowed
537
+ let transactionType = transactionTypesMap[data.slice(0, 10).toLowerCase()];
538
+ if (transactionType === undefined) {
539
+ transactionType = sdk_core_1.TransactionType.ContractCall;
540
+ }
541
+ return transactionType;
542
+ }
543
+ /**
544
+ * A transaction types map according to the starting part of the encoded data
545
+ */
546
+ const transactionTypesMap = {
547
+ [walletUtil_1.walletInitializationFirstBytes]: sdk_core_1.TransactionType.WalletInitialization,
548
+ [walletUtil_1.recoveryWalletInitializationFirstBytes]: sdk_core_1.TransactionType.RecoveryWalletDeployment,
549
+ [walletUtil_1.v1CreateWalletMethodId]: sdk_core_1.TransactionType.WalletInitialization,
550
+ [walletUtil_1.createForwarderMethodId]: sdk_core_1.TransactionType.AddressInitialization,
551
+ [walletUtil_1.v1CreateForwarderMethodId]: sdk_core_1.TransactionType.AddressInitialization,
552
+ [walletUtil_1.v4CreateForwarderMethodId]: sdk_core_1.TransactionType.AddressInitialization,
553
+ [walletUtil_1.sendMultisigMethodId]: sdk_core_1.TransactionType.Send,
554
+ [walletUtil_1.flushForwarderTokensMethodId]: sdk_core_1.TransactionType.FlushTokens,
555
+ [walletUtil_1.flushForwarderTokensMethodIdV4]: sdk_core_1.TransactionType.FlushTokens,
556
+ [walletUtil_1.flushCoinsMethodId]: sdk_core_1.TransactionType.FlushCoins,
557
+ [walletUtil_1.flushERC721ForwarderTokensMethodId]: sdk_core_1.TransactionType.FlushERC721,
558
+ [walletUtil_1.flushERC721ForwarderTokensMethodIdV4]: sdk_core_1.TransactionType.FlushERC721,
559
+ [walletUtil_1.flushERC1155ForwarderTokensMethodId]: sdk_core_1.TransactionType.FlushERC1155,
560
+ [walletUtil_1.flushERC1155ForwarderTokensMethodIdV4]: sdk_core_1.TransactionType.FlushERC1155,
561
+ [walletUtil_1.sendMultisigTokenMethodId]: sdk_core_1.TransactionType.Send,
562
+ [sdk_core_1.LockMethodId]: sdk_core_1.TransactionType.StakingLock,
563
+ [sdk_core_1.VoteMethodId]: sdk_core_1.TransactionType.StakingVote,
564
+ [sdk_core_1.ActivateMethodId]: sdk_core_1.TransactionType.StakingActivate,
565
+ [sdk_core_1.UnvoteMethodId]: sdk_core_1.TransactionType.StakingUnvote,
566
+ [sdk_core_1.UnlockMethodId]: sdk_core_1.TransactionType.StakingUnlock,
567
+ [sdk_core_1.WithdrawMethodId]: sdk_core_1.TransactionType.StakingWithdraw,
568
+ // aclMulticallMethodId (multicall(bytes[])) is intentionally NOT mapped here.
569
+ // classifyTransaction() only sees calldata, not `to`, so 0xac9650d8 would mislabel
570
+ // any OpenZeppelin MulticallUpgradeable call (routers, aggregators, unrelated contracts)
571
+ // as DecryptionDelegation. Builder output (which always uses multicall) therefore
572
+ // classifies as ContractCall; callers should set TransactionType.DecryptionDelegation
573
+ // explicitly when building from a known delegation template.
574
+ [zamaUtils_1.delegateForUserDecryptionMethodId]: sdk_core_1.TransactionType.DecryptionDelegation,
575
+ };
576
+ /**
577
+ *
578
+ * @param {number} num number to be converted to hex
579
+ * @returns {string} the hex number
580
+ */
581
+ function numberToHexString(num) {
582
+ const hex = num.toString(16);
583
+ return hex.length % 2 === 0 ? '0x' + hex : '0x0' + hex;
584
+ }
585
+ /**
586
+ *
587
+ * @param {string} hex The hex string to be converted
588
+ * @returns {number} the resulting number
589
+ */
590
+ function hexStringToNumber(hex) {
591
+ return parseInt(hex.slice(2), 16);
592
+ }
593
+ /**
594
+ * Generates an address of the forwarder address to be deployed
595
+ *
596
+ * @param {string} contractAddress the address which is creating this new address
597
+ * @param {number} contractCounter the nonce of the contract address
598
+ * @returns {string} the calculated forwarder contract address
599
+ */
600
+ function calculateForwarderAddress(contractAddress, contractCounter) {
601
+ const forwarderAddress = (0, ethereumjs_util_1.generateAddress)(buffer_1.Buffer.from((0, ethereumjs_util_1.stripHexPrefix)(contractAddress), 'hex'), buffer_1.Buffer.from((0, ethereumjs_util_1.padToEven)((0, ethereumjs_util_1.stripHexPrefix)(numberToHexString(contractCounter))), 'hex'));
602
+ return (0, ethereumjs_util_1.addHexPrefix)(forwarderAddress.toString('hex'));
603
+ }
604
+ /**
605
+ * Calculate the forwarder v1 address that will be generated if `creatorAddress` creates it with salt `salt`
606
+ * and initcode `inicode using the create2 opcode
607
+ * @param {string} creatorAddress The address that is sending the tx to create a new address, hex string
608
+ * @param {string} salt The salt to create the address with using create2, hex string
609
+ * @param {string} initcode The initcode that will be deployed to the address, hex string
610
+ * @return {string} The calculated address
611
+ */
612
+ function calculateForwarderV1Address(creatorAddress, salt, initcode) {
613
+ const forwarderV1Address = (0, ethereumjs_util_1.generateAddress2)(buffer_1.Buffer.from((0, ethereumjs_util_1.stripHexPrefix)(creatorAddress), 'hex'), buffer_1.Buffer.from((0, ethereumjs_util_1.stripHexPrefix)(salt), 'hex'), buffer_1.Buffer.from((0, ethereumjs_util_1.padToEven)((0, ethereumjs_util_1.stripHexPrefix)(initcode)), 'hex'));
614
+ return (0, ethereumjs_util_1.addHexPrefix)(forwarderV1Address.toString('hex'));
615
+ }
616
+ /**
617
+ * Take the implementation address for the proxy contract, and get the binary initcode for the associated proxy
618
+ * @param {string} implementationAddress The address of the implementation contract for the proxy
619
+ * @return {string} Binary hex string of the proxy
620
+ */
621
+ function getProxyInitcode(implementationAddress) {
622
+ const target = (0, ethereumjs_util_1.stripHexPrefix)(implementationAddress.toLowerCase()).padStart(40, '0');
623
+ // bytecode of the proxy, from:
624
+ // https://github.com/BitGo/eth-multisig-v4/blob/d546a937f90f93e83b3423a5bf933d1d77c677c3/contracts/CloneFactory.sol#L42-L56
625
+ return `0x3d602d80600a3d3981f3363d3d373d3d3d363d73${target}5af43d82803e903d91602b57fd5bf3`;
626
+ }
627
+ /**
628
+ * Convert the given signature parts to a string representation
629
+ *
630
+ * @param {SignatureParts} sig The signature to convert to string
631
+ * @returns {string} String representation of the signature
632
+ */
633
+ function toStringSig(sig) {
634
+ return (0, ethereumjs_util_1.bufferToHex)(buffer_1.Buffer.concat([
635
+ (0, ethereumjs_util_1.setLengthLeft)(buffer_1.Buffer.from((0, ethereumjs_util_1.stripHexPrefix)(sig.r), 'hex'), 32),
636
+ (0, ethereumjs_util_1.setLengthLeft)(buffer_1.Buffer.from((0, ethereumjs_util_1.stripHexPrefix)(sig.s), 'hex'), 32),
637
+ (0, ethereumjs_util_1.toBuffer)(sig.v),
638
+ ]));
639
+ }
640
+ /**
641
+ * Return whether or not the given tx data has a signature
642
+ *
643
+ * @param {TxData} txData The transaction data to check for signature
644
+ * @returns {boolean} true if the tx has a signature, else false
645
+ */
646
+ function hasSignature(txData) {
647
+ return (txData.v !== undefined &&
648
+ txData.r !== undefined &&
649
+ txData.s !== undefined &&
650
+ txData.v.length > 0 &&
651
+ txData.r.length > 0 &&
652
+ txData.s.length > 0);
653
+ }
654
+ /**
655
+ * Get the raw data decoded for some types
656
+ *
657
+ * @param {string[]} types ABI types definition
658
+ * @param {Buffer} serializedArgs encoded args
659
+ * @returns {Buffer[]} the decoded raw
660
+ */
661
+ function getRawDecoded(types, serializedArgs) {
662
+ function normalize(v, i) {
663
+ if (bn_js_1.default.isBN(v)) {
664
+ return v;
665
+ }
666
+ else if (typeof v === 'string' || buffer_1.Buffer.isBuffer(v)) {
667
+ return v;
668
+ }
669
+ else if (Array.isArray(v)) {
670
+ return v.map(normalize);
671
+ }
672
+ else {
673
+ throw new Error(`For ${types}[${i}] got ${typeof v}`);
674
+ }
675
+ }
676
+ return ethereumjs_abi_1.default.rawDecode(types, serializedArgs).map(normalize);
677
+ }
678
+ /**
679
+ * Get the buffered bytecode from rawData using a methodId as delimiter
680
+ *
681
+ * @param {string} methodId the hex encoded method Id
682
+ * @param {string} rawData the hex encoded raw data
683
+ * @returns {Buffer} data buffered bytecode
684
+ */
685
+ function getBufferedByteCode(methodId, rawData) {
686
+ const splitBytecode = rawData.split(methodId);
687
+ if (splitBytecode.length !== 2) {
688
+ throw new sdk_core_1.BuildTransactionError(`Invalid send bytecode: ${rawData}`);
689
+ }
690
+ if (splitBytecode[1].length % 2 !== 0) {
691
+ throw new sdk_core_1.BuildTransactionError(`Invalid send bytecode: ${rawData} (wrong lenght)`);
692
+ }
693
+ return buffer_1.Buffer.from(splitBytecode[1], 'hex');
694
+ }
695
+ /**
696
+ * Get the statics coin object matching a given contract address if it exists
697
+ *
698
+ * @param tokenContractAddress The contract address to match against
699
+ * @param network - the coin network
700
+ * @param family - the coin family
701
+ * @returns statics BaseCoin object for the matching token
702
+ */
703
+ function getToken(tokenContractAddress, network, family) {
704
+ // filter the coins array to find the token with the matching contract address, network and coin family
705
+ // coin family is needed to avoid causing issues when a token has same contract address on two different chains
706
+ const tokens = statics_1.coins.filter((coin) => {
707
+ if (coin instanceof statics_1.ContractAddressDefinedToken) {
708
+ return (coin.network.type === network.type &&
709
+ coin.family === family &&
710
+ coin.contractAddress.toLowerCase() === tokenContractAddress.toLowerCase());
711
+ }
712
+ return false;
713
+ });
714
+ // if length of tokens is 1, return the first, else return undefined
715
+ // Can't directly index into tokens, or call `length`, so we use map to get an array
716
+ const tokensArray = tokens.map((token) => token);
717
+ if (tokensArray.length >= 1) {
718
+ // there should never be two tokens with the same contract address, so we assert that here
719
+ (0, assert_1.default)(tokensArray.length === 1);
720
+ return tokensArray[0];
721
+ }
722
+ return undefined;
723
+ }
724
+ /**
725
+ * Returns the create wallet method calling data for v1 wallets
726
+ *
727
+ * @param {string[]} walletOwners - wallet owner addresses for wallet initialization transactions
728
+ * @param {string} salt - The salt for wallet initialization transactions
729
+ * @returns {string} - the createWallet method encoded
730
+ */
731
+ function getV1WalletInitializationData(walletOwners, salt) {
732
+ const saltBuffer = (0, ethereumjs_util_1.setLengthLeft)((0, ethereumjs_util_1.toBuffer)(salt), 32);
733
+ const params = [walletOwners, saltBuffer];
734
+ const method = ethereumjs_abi_1.default.methodID('createWallet', walletUtil_1.createV1WalletTypes);
735
+ const args = ethereumjs_abi_1.default.rawEncode(walletUtil_1.createV1WalletTypes, params);
736
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
737
+ }
738
+ /**
739
+ * Returns the create address method calling data for v1, v2, v4 forwarders
740
+ *
741
+ * @param {string} baseAddress - The address of the wallet contract
742
+ * @param {string} salt - The salt for address initialization transactions
743
+ * @param {string} feeAddress - The fee address for the enterprise
744
+ * @returns {string} - the createForwarder method encoded
745
+ */
746
+ function getV1AddressInitializationData(baseAddress, salt, feeAddress) {
747
+ const saltBuffer = (0, ethereumjs_util_1.setLengthLeft)((0, ethereumjs_util_1.toBuffer)(salt), 32);
748
+ const { createForwarderParams, createForwarderTypes } = getCreateForwarderParamsAndTypes(baseAddress, saltBuffer, feeAddress);
749
+ const method = ethereumjs_abi_1.default.methodID('createForwarder', createForwarderTypes);
750
+ const args = ethereumjs_abi_1.default.rawEncode(createForwarderTypes, createForwarderParams);
751
+ return (0, ethereumjs_util_1.addHexPrefix)(buffer_1.Buffer.concat([method, args]).toString('hex'));
752
+ }
753
+ /**
754
+ * Returns the create address method calling data for all forwarder versions
755
+ *
756
+ * @param {number} forwarderVersion - The version of the forwarder to create
757
+ * @param {string} baseAddress - The address of the wallet contract
758
+ * @param {string} salt - The salt for address initialization transactions
759
+ * @param {string} feeAddress - The fee address for the enterprise
760
+ * @returns {string} - the createForwarder method encoded
761
+ *
762
+ */
763
+ function getAddressInitDataAllForwarderVersions(forwarderVersion, baseAddress, salt, feeAddress) {
764
+ if (forwarderVersion === walletUtil_1.defaultForwarderVersion) {
765
+ return getAddressInitializationData();
766
+ }
767
+ else {
768
+ return getV1AddressInitializationData(baseAddress, salt, feeAddress);
769
+ }
770
+ }
771
+ /**
772
+ * Returns the createForwarderTypes and createForwarderParams for all forwarder versions
773
+ *
774
+ * @param {string} baseAddress - The address of the wallet contract
775
+ * @param {Buffer} saltBuffer - The salt for address initialization transaction
776
+ * @param {string} feeAddress - The fee address for the enterprise
777
+ * @returns {createForwarderParams: (string | Buffer)[], createForwarderTypes: string[]}
778
+ */
779
+ function getCreateForwarderParamsAndTypes(baseAddress, saltBuffer, feeAddress) {
780
+ let createForwarderParams = [baseAddress, saltBuffer];
781
+ let createForwarderTypes = walletUtil_1.createV1ForwarderTypes;
782
+ if (feeAddress) {
783
+ createForwarderParams = [baseAddress, feeAddress, saltBuffer];
784
+ createForwarderTypes = walletUtil_1.createV4ForwarderTypes;
785
+ }
786
+ return { createForwarderParams, createForwarderTypes };
787
+ }
788
+ /**
789
+ * Decode the given ABI-encoded create forwarder data and return parsed fields
790
+ *
791
+ * @param data The data to decode
792
+ * @returns parsed transfer data
793
+ */
794
+ function decodeForwarderCreationData(data) {
795
+ if (!(data.startsWith(walletUtil_1.v4CreateForwarderMethodId) ||
796
+ data.startsWith(walletUtil_1.v1CreateForwarderMethodId) ||
797
+ data.startsWith(walletUtil_1.createForwarderMethodId))) {
798
+ throw new sdk_core_1.BuildTransactionError(`Invalid address bytecode: ${data}`);
799
+ }
800
+ if (data.startsWith(walletUtil_1.createForwarderMethodId)) {
801
+ return {
802
+ baseAddress: undefined,
803
+ addressCreationSalt: undefined,
804
+ feeAddress: undefined,
805
+ };
806
+ }
807
+ else if (data.startsWith(walletUtil_1.v1CreateForwarderMethodId)) {
808
+ const [baseAddress, saltBuffer] = getRawDecoded(walletUtil_1.createV1ForwarderTypes, getBufferedByteCode(walletUtil_1.v1CreateForwarderMethodId, data));
809
+ return {
810
+ baseAddress: (0, ethereumjs_util_1.addHexPrefix)(baseAddress),
811
+ addressCreationSalt: (0, ethereumjs_util_1.bufferToHex)(saltBuffer),
812
+ feeAddress: undefined,
813
+ };
814
+ }
815
+ else {
816
+ const [baseAddress, feeAddress, saltBuffer] = getRawDecoded(walletUtil_1.createV4ForwarderTypes, getBufferedByteCode(walletUtil_1.v4CreateForwarderMethodId, data));
817
+ return {
818
+ baseAddress: (0, ethereumjs_util_1.addHexPrefix)(baseAddress),
819
+ addressCreationSalt: (0, ethereumjs_util_1.bufferToHex)(saltBuffer),
820
+ feeAddress: (0, ethereumjs_util_1.addHexPrefix)(feeAddress),
821
+ };
822
+ }
823
+ }
824
+ /**
825
+ * Make a query to explorer for information such as balance, token balance, solidity calls
826
+ * @param {Object} query key-value pairs of parameters to append after /api
827
+ * @param {string} token the API token to use for the request
828
+ * @param {string} explorerUrl the URL of the explorer
829
+ * @returns {Promise<Object>} response from explorer
830
+ */
831
+ async function recoveryBlockchainExplorerQuery(query, explorerUrl, token) {
832
+ if (token) {
833
+ query.apikey = token;
834
+ }
835
+ const response = await superagent_1.default.get(`${explorerUrl}/api`).query(query);
836
+ if (!response.ok) {
837
+ throw new Error('could not reach explorer');
838
+ }
839
+ if (response.body.status === '0' && response.body.message === 'NOTOK') {
840
+ throw new Error('Explorer rate limit reached');
841
+ }
842
+ return response.body;
843
+ }
844
+ /**
845
+ * Default expire time for a contract call (1 week)
846
+ * @returns {number} Time in seconds
847
+ */
848
+ function getDefaultExpireTime() {
849
+ return Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 * 7;
850
+ }
851
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBNEZBLDhCQVdDO0FBV0Qsb0NBV0M7QUFTRCxvQkFFQztBQWFELDRDQVlDO0FBYUQsc0RBYUM7QUFRRCwwQ0FlQztBQUtELHdDQUtDO0FBU0Qsc0RBb0JDO0FBUUQsa0VBbUNDO0FBU0Qsd0RBb0JDO0FBUUQsb0VBbUNDO0FBT0Qsb0VBRUM7QUFRRCw4Q0FFQztBQVFELHNDQUdDO0FBUUQsNERBeUNDO0FBU0QsZ0RBUUM7QUFTRCwwREFnQ0M7QUFFRCw0REFtREM7QUFFRCw4REFrREM7QUFTRCw0REFpQ0M7QUFTRCxzREF1QkM7QUFTRCxrREFjQztBQXlDRCw4Q0FHQztBQU9ELDhDQUVDO0FBU0QsOERBTUM7QUFVRCxrRUFPQztBQU9ELDRDQU1DO0FBUUQsa0NBUUM7QUFRRCxvQ0FTQztBQVdELHNDQWNDO0FBU0Qsa0RBU0M7QUFVRCw0QkEyQkM7QUFTRCxzRUFNQztBQVVELHdFQVdDO0FBWUQsd0ZBV0M7QUFVRCw0RUFZQztBQVFELGtFQXdDQztBQVNELDBFQWtCQztBQU1ELG9EQUVDO0FBdGpDRCxtQ0FBZ0M7QUFDaEMsNERBQWlDO0FBQ2pDLG9EQUE0QjtBQUM1QixxREFXeUI7QUFDekIsaURBQWlIO0FBQ2pILG9FQUF5QztBQUN6QyxnRUFBZ0Q7QUFDaEQsa0RBQXVCO0FBQ3ZCLGdFQUFxQztBQUNyQyxtREFVOEI7QUFlOUIsNkNBd0NzQjtBQUN0QixtQ0FBNkM7QUFDN0MsMkNBQWdFO0FBRWhFOztHQUVHO0FBQ0gsU0FBZ0IsU0FBUyxDQUFDLE9BQXdCO0lBQ2hELE9BQU8sZ0JBQWMsQ0FBQyxjQUFjO0lBQ2xDLHdFQUF3RTtJQUN4RSxTQUFTLEVBQ1Q7UUFDRSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDbEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQzFCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztLQUN6QixFQUNELFFBQVEsQ0FDVCxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0ksS0FBSyxVQUFVLFlBQVksQ0FDaEMsZUFBdUIsRUFDdkIsT0FBZ0IsRUFDaEIsWUFBNEI7SUFFNUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUMzQixNQUFNLElBQUksdUJBQVksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRywwQkFBa0IsQ0FBQyxRQUFRLENBQUMsZUFBZSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3pFLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDcEIsT0FBTyxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7QUFDOUIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSxJQUFJLENBQUMsZUFBdUIsRUFBRSxPQUFnQjtJQUNsRSxPQUFPLFlBQVksQ0FBQyxlQUFlLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQTBCLENBQUMsQ0FBQyxDQUFDO0FBQ3pHLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsU0FBZ0IsZ0JBQWdCLENBQzlCLEVBQVUsRUFDVixLQUFhLEVBQ2IsSUFBWSxFQUNaLFVBQWtCLEVBQ2xCLFVBQWtCLEVBQ2xCLFNBQWlCO0lBRWpCLE1BQU0sTUFBTSxHQUFHLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFBLDBCQUFRLEVBQUMsSUFBSSxDQUFDLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxJQUFBLDBCQUFRLEVBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUN4RixNQUFNLE1BQU0sR0FBRyx3QkFBVyxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsOEJBQWlCLENBQUMsQ0FBQztJQUN2RSxNQUFNLElBQUksR0FBRyx3QkFBVyxDQUFDLFNBQVMsQ0FBQyw4QkFBaUIsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM5RCxPQUFPLElBQUEsOEJBQVksRUFBQyxlQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQixxQkFBcUIsQ0FDbkMsRUFBVSxFQUNWLEtBQWEsRUFDYixvQkFBNEIsRUFDNUIsVUFBa0IsRUFDbEIsVUFBa0IsRUFDbEIsU0FBaUI7SUFFakIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLG9CQUFvQixFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsSUFBQSwwQkFBUSxFQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFFOUYsTUFBTSxNQUFNLEdBQUcsd0JBQVcsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsbUNBQXNCLENBQUMsQ0FBQztJQUNqRixNQUFNLElBQUksR0FBRyx3QkFBVyxDQUFDLFNBQVMsQ0FBQyxtQ0FBc0IsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNuRSxPQUFPLElBQUEsOEJBQVksRUFBQyxlQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLGdCQUF3QixFQUFFLFlBQW9CLEVBQUUsZ0JBQXdCO0lBQ3RHLElBQUksTUFBZ0IsQ0FBQztJQUNyQixJQUFJLE1BQWtCLENBQUM7SUFDdkIsSUFBSSxJQUFnQixDQUFDO0lBRXJCLElBQUksZ0JBQWdCLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDMUIsTUFBTSxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDeEIsTUFBTSxHQUFHLHdCQUFXLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSwrQkFBa0IsQ0FBQyxDQUFDO1FBQ2pFLElBQUksR0FBRyx3QkFBVyxDQUFDLFNBQVMsQ0FBQywrQkFBa0IsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMzRCxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sR0FBRyxDQUFDLGdCQUFnQixFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFDLE1BQU0sR0FBRyx3QkFBVyxDQUFDLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSw2QkFBZ0IsQ0FBQyxDQUFDO1FBQ3hFLElBQUksR0FBRyx3QkFBVyxDQUFDLFNBQVMsQ0FBQyw2QkFBZ0IsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsT0FBTyxJQUFBLDhCQUFZLEVBQUMsZUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3JFLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLGNBQWM7SUFDNUIsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLE1BQU0sTUFBTSxHQUFHLHdCQUFXLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSw0QkFBZSxDQUFDLENBQUM7SUFDOUQsTUFBTSxJQUFJLEdBQUcsd0JBQVcsQ0FBQyxTQUFTLENBQUMsNEJBQWUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM1RCxPQUFPLElBQUEsOEJBQVksRUFBQyxlQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLHFCQUFxQixDQUNuQyxnQkFBd0IsRUFDeEIsWUFBb0IsRUFDcEIsT0FBZSxFQUNmLGdCQUF3QjtJQUV4QixJQUFJLE1BQTJCLENBQUM7SUFDaEMsSUFBSSxNQUFrQixDQUFDO0lBQ3ZCLElBQUksSUFBZ0IsQ0FBQztJQUVyQixJQUFJLGdCQUFnQixJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sR0FBRyxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNqQyxNQUFNLEdBQUcsd0JBQVcsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLEVBQUUscUNBQXdCLENBQUMsQ0FBQztRQUM1RSxJQUFJLEdBQUcsd0JBQVcsQ0FBQyxTQUFTLENBQUMscUNBQXdCLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDakUsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbkQsTUFBTSxHQUFHLHdCQUFXLENBQUMsUUFBUSxDQUFDLDRCQUE0QixFQUFFLG1DQUFzQixDQUFDLENBQUM7UUFDcEYsSUFBSSxHQUFHLHdCQUFXLENBQUMsU0FBUyxDQUFDLG1DQUFzQixFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFDRCxPQUFPLElBQUEsOEJBQVksRUFBQyxlQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsMkJBQTJCLENBQ3pDLElBQVksRUFDWixFQUFXO0lBT1gsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGlEQUFvQyxDQUFDLEVBQUUsQ0FBQztRQUMxRCxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDUixNQUFNLElBQUksZ0NBQXFCLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDL0QsQ0FBQztRQUNELE1BQU0sQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsYUFBYSxDQUMzQyxxQ0FBd0IsRUFDeEIsbUJBQW1CLENBQUMsaURBQW9DLEVBQUUsSUFBSSxDQUFDLENBQ2hFLENBQUM7UUFDRixPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsRUFBRTtZQUNwQixZQUFZLEVBQUUsSUFBQSw4QkFBWSxFQUFDLFlBQXNCLENBQUM7WUFDbEQsT0FBTyxFQUFFLElBQUksc0JBQVMsQ0FBQyxJQUFBLDZCQUFXLEVBQUMsT0FBaUIsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFO1lBQ2hFLGdCQUFnQixFQUFFLENBQUM7U0FDcEIsQ0FBQztJQUNKLENBQUM7U0FBTSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsK0NBQWtDLENBQUMsRUFBRSxDQUFDO1FBQy9ELE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsYUFBYSxDQUM3RCxtQ0FBc0IsRUFDdEIsbUJBQW1CLENBQUMsK0NBQWtDLEVBQUUsSUFBSSxDQUFDLENBQzlELENBQUM7UUFDRixPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsSUFBQSw4QkFBWSxFQUFDLGdCQUEwQixDQUFDO1lBQzFELFlBQVksRUFBRSxJQUFBLDhCQUFZLEVBQUMsWUFBc0IsQ0FBQztZQUNsRCxPQUFPLEVBQUUsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxPQUFpQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7U0FDakUsQ0FBQztJQUNKLENBQUM7SUFDRCxNQUFNLElBQUksZ0NBQXFCLENBQUMsa0NBQWtDLElBQUksRUFBRSxDQUFDLENBQUM7QUFDNUUsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLHNCQUFzQixDQUNwQyxnQkFBd0IsRUFDeEIsWUFBb0IsRUFDcEIsT0FBZSxFQUNmLGdCQUF3QjtJQUV4QixJQUFJLE1BQTJCLENBQUM7SUFDaEMsSUFBSSxNQUFrQixDQUFDO0lBQ3ZCLElBQUksSUFBZ0IsQ0FBQztJQUVyQixJQUFJLGdCQUFnQixJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzFCLE1BQU0sR0FBRyxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNqQyxNQUFNLEdBQUcsd0JBQVcsQ0FBQyxRQUFRLENBQUMsb0JBQW9CLEVBQUUsc0NBQXlCLENBQUMsQ0FBQztRQUMvRSxJQUFJLEdBQUcsd0JBQVcsQ0FBQyxTQUFTLENBQUMsc0NBQXlCLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDbEUsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbkQsTUFBTSxHQUFHLHdCQUFXLENBQUMsUUFBUSxDQUFDLDZCQUE2QixFQUFFLG9DQUF1QixDQUFDLENBQUM7UUFDdEYsSUFBSSxHQUFHLHdCQUFXLENBQUMsU0FBUyxDQUFDLG9DQUF1QixFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFDRCxPQUFPLElBQUEsOEJBQVksRUFBQyxlQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsNEJBQTRCLENBQzFDLElBQVksRUFDWixFQUFXO0lBT1gsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGtEQUFxQyxDQUFDLEVBQUUsQ0FBQztRQUMzRCxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDUixNQUFNLElBQUksZ0NBQXFCLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDL0QsQ0FBQztRQUNELE1BQU0sQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsYUFBYSxDQUMzQyxzQ0FBeUIsRUFDekIsbUJBQW1CLENBQUMsa0RBQXFDLEVBQUUsSUFBSSxDQUFDLENBQ2pFLENBQUM7UUFDRixPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsRUFBRTtZQUNwQixZQUFZLEVBQUUsSUFBQSw4QkFBWSxFQUFDLFlBQXNCLENBQUM7WUFDbEQsT0FBTyxFQUFFLElBQUksc0JBQVMsQ0FBQyxJQUFBLDZCQUFXLEVBQUMsT0FBaUIsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFO1lBQ2hFLGdCQUFnQixFQUFFLENBQUM7U0FDcEIsQ0FBQztJQUNKLENBQUM7U0FBTSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsZ0RBQW1DLENBQUMsRUFBRSxDQUFDO1FBQ2hFLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsT0FBTyxDQUFDLEdBQUcsYUFBYSxDQUM3RCxvQ0FBdUIsRUFDdkIsbUJBQW1CLENBQUMsZ0RBQW1DLEVBQUUsSUFBSSxDQUFDLENBQy9ELENBQUM7UUFDRixPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsSUFBQSw4QkFBWSxFQUFDLGdCQUEwQixDQUFDO1lBQzFELFlBQVksRUFBRSxJQUFBLDhCQUFZLEVBQUMsWUFBc0IsQ0FBQztZQUNsRCxPQUFPLEVBQUUsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxPQUFpQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7U0FDakUsQ0FBQztJQUNKLENBQUM7SUFDRCxNQUFNLElBQUksZ0NBQXFCLENBQUMsbUNBQW1DLElBQUksRUFBRSxDQUFDLENBQUM7QUFDN0UsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQiw0QkFBNEI7SUFDMUMsT0FBTyxvQ0FBdUIsQ0FBQztBQUNqQyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxPQUFlO0lBQy9DLE9BQU8sSUFBQSxnQ0FBYyxFQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQ2pDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLGFBQWEsQ0FBQyxNQUFjO0lBQzFDLE1BQU0sZUFBZSxHQUFHLElBQUksc0JBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QyxPQUFPLGVBQWUsQ0FBQyxTQUFTLEVBQUUsSUFBSSxlQUFlLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDbEYsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0Isd0JBQXdCLENBQUMsSUFBWTtJQUNuRCxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLDJDQUE4QixDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxtQ0FBc0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNsRyxNQUFNLElBQUksZ0NBQXFCLENBQUMsNEJBQTRCLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVELElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQywyQ0FBOEIsQ0FBQyxFQUFFLENBQUM7UUFDcEQsTUFBTSxVQUFVLEdBQUcsZUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXJELDBEQUEwRDtRQUMxRCxNQUFNLGlCQUFpQixHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUVqRCxNQUFNLHVCQUF1QixHQUFHLHdCQUFXLENBQUMsU0FBUyxDQUFDLG9DQUF1QixFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFDbEcsSUFBSSx1QkFBdUIsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekMsTUFBTSxJQUFJLGdDQUFxQixDQUFDLGlEQUFpRCx1QkFBdUIsRUFBRSxDQUFDLENBQUM7UUFDOUcsQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFTLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELElBQUksU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksZ0NBQXFCLENBQUMsc0RBQXNELFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDckcsQ0FBQztRQUVELHdFQUF3RTtRQUN4RSx3REFBd0Q7UUFDeEQsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBQSxnQ0FBYyxFQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFOUcsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFBLDhCQUFZLEVBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzdFLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSw0QkFBNEIsR0FBRyxhQUFhLENBQ2hELGdDQUFtQixFQUNuQixtQkFBbUIsQ0FBQyxtQ0FBc0IsRUFBRSxJQUFJLENBQUMsQ0FDbEQsQ0FBQztRQUNGLE1BQU0sU0FBUyxHQUFHLDRCQUE0QixDQUFDLENBQUMsQ0FBYSxDQUFDO1FBQzlELE1BQU0sVUFBVSxHQUFHLDRCQUE0QixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sSUFBSSxHQUFHLElBQUEsNkJBQVcsRUFBQyxVQUFvQixDQUFDLENBQUM7UUFDL0MsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBQSxnQ0FBYyxFQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN6RyxNQUFNLE1BQU0sR0FBRyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFBLDhCQUFZLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUN2RSxPQUFPO1lBQ0wsTUFBTTtZQUNOLElBQUk7U0FDTCxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixrQkFBa0IsQ0FBQyxJQUFZLEVBQUUsYUFBdUI7SUFDdEUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLGlDQUFvQixDQUFDLEVBQUUsQ0FBQztRQUMxQyxPQUFPLHdCQUF3QixDQUFDLElBQUksRUFBRSxhQUFhLENBQUMsQ0FBQztJQUN2RCxDQUFDO1NBQU0sSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLHNDQUF5QixDQUFDLEVBQUUsQ0FBQztRQUN0RCxPQUFPLHVCQUF1QixDQUFDLElBQUksRUFBRSxhQUFhLENBQUMsQ0FBQztJQUN0RCxDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQyw4QkFBOEIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN4RSxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLHVCQUF1QixDQUFDLElBQVksRUFBRSxhQUF1QjtJQUMzRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQ0FBeUIsQ0FBQyxFQUFFLENBQUM7UUFDaEQsTUFBTSxJQUFJLGdDQUFxQixDQUFDLDhCQUE4QixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFDRCxJQUFJLEVBQXVDLENBQUM7SUFDNUMsSUFBSSxNQUEyQyxDQUFDO0lBQ2hELElBQUksb0JBQXlELENBQUM7SUFDOUQsSUFBSSxVQUErQyxDQUFDO0lBQ3BELElBQUksVUFBK0MsQ0FBQztJQUNwRCxJQUFJLFNBQThDLENBQUM7SUFDbkQsSUFBSSxNQUEyQyxDQUFDO0lBQ2hELElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNuQixDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsb0JBQW9CLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxTQUFTLENBQUMsR0FBRyxhQUFhLENBQ25GLG1DQUFzQixFQUN0QixtQkFBbUIsQ0FBQyxzQ0FBeUIsRUFBRSxJQUFJLENBQUMsQ0FDckQsQ0FBQztJQUNKLENBQUM7U0FBTSxDQUFDO1FBQ04sQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxvQkFBb0IsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLEdBQUcsYUFBYSxDQUNoRiw4Q0FBaUMsRUFDakMsbUJBQW1CLENBQUMsc0NBQXlCLEVBQUUsSUFBSSxDQUFDLENBQ3JELENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTztRQUNMLG1CQUFtQixFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUUsTUFBaUIsQ0FBQyxDQUFDLENBQUMsU0FBUztRQUNuRSxFQUFFLEVBQUUsSUFBQSw4QkFBWSxFQUFDLEVBQVksQ0FBQztRQUM5QixNQUFNLEVBQUUsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxNQUFnQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDOUQsVUFBVSxFQUFFLElBQUEsNkJBQVcsRUFBQyxVQUFvQixDQUFDO1FBQzdDLFVBQVUsRUFBRSxJQUFBLDZCQUFXLEVBQUMsVUFBb0IsQ0FBQztRQUM3QyxTQUFTLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFNBQW1CLENBQUM7UUFDM0Msb0JBQW9CLEVBQUUsSUFBQSw4QkFBWSxFQUFDLG9CQUE4QixDQUFDO0tBQ25FLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBZ0Isd0JBQXdCLENBQUMsSUFBWTtJQUNuRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxpQ0FBb0IsQ0FBQyxFQUFFLENBQUM7UUFDM0MsTUFBTSxJQUFJLGdDQUFxQixDQUFDLDhCQUE4QixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFRCxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxTQUFTLENBQUMsR0FBRyxhQUFhLENBQ2pGLDhCQUFpQixFQUNqQixtQkFBbUIsQ0FBQyxpQ0FBb0IsRUFBRSxJQUFJLENBQUMsQ0FDaEQsQ0FBQztJQUVGLE1BQU0sZUFBZSxHQUFHLElBQUEsNkJBQVcsRUFBQyxZQUFzQixDQUFDLENBQUM7SUFFNUQsSUFBSSxlQUFlLENBQUMsVUFBVSxDQUFDLDJDQUE4QixDQUFDLEVBQUUsQ0FBQztRQUMvRCxNQUFNLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLEdBQUcsYUFBYSxDQUMzRCxvQ0FBdUIsRUFDdkIsbUJBQW1CLENBQUMsMkNBQThCLEVBQUUsZUFBZSxDQUFDLENBQ3JFLENBQUM7UUFFRixPQUFPO1lBQ0wsRUFBRSxFQUFFLElBQUEsOEJBQVksRUFBQyxRQUFrQixDQUFDO1lBQ3BDLElBQUksRUFBRSxJQUFBLDhCQUFZLEVBQUMsSUFBYyxDQUFDO1lBQ2xDLFVBQVUsRUFBRSxJQUFBLDZCQUFXLEVBQUMsVUFBb0IsQ0FBQztZQUM3QyxNQUFNLEVBQUUsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxNQUFnQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7WUFDOUQsT0FBTyxFQUFFLElBQUksc0JBQVMsQ0FBQyxJQUFBLDZCQUFXLEVBQUMsT0FBaUIsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFO1lBQ2hFLFVBQVUsRUFBRSxJQUFBLDZCQUFXLEVBQUMsVUFBb0IsQ0FBQztZQUM3QyxTQUFTLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFNBQW1CLENBQUM7WUFDM0Msb0JBQW9CLEVBQUUsSUFBQSw4QkFBWSxFQUFDLEVBQVksQ0FBQztZQUNoRCxRQUFRLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFlBQXNCLENBQUM7U0FDOUMsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUFJLGVBQWUsQ0FBQyxVQUFVLENBQUMsdUNBQTBCLENBQUMsRUFBRSxDQUFDO1FBQzNELE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLGFBQWEsQ0FDN0Msb0NBQXVCLEVBQ3ZCLG1CQUFtQixDQUFDLHVDQUEwQixFQUFFLGVBQWUsQ0FBQyxDQUNqRSxDQUFDO1FBRUYsT0FBTztZQUNMLEVBQUUsRUFBRSxJQUFBLDhCQUFZLEVBQUMsUUFBa0IsQ0FBQztZQUNwQyxJQUFJLEVBQUUsSUFBQSw4QkFBWSxFQUFDLElBQWMsQ0FBQztZQUNsQyxVQUFVLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFVBQW9CLENBQUM7WUFDN0MsTUFBTSxFQUFFLElBQUksc0JBQVMsQ0FBQyxJQUFBLDZCQUFXLEVBQUMsTUFBZ0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFO1lBQzlELE9BQU8sRUFBRSxJQUFJLHNCQUFTLENBQUMsSUFBQSw2QkFBVyxFQUFDLE9BQWlCLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRTtZQUNoRSxVQUFVLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFVBQW9CLENBQUM7WUFDN0MsU0FBUyxFQUFFLElBQUEsNkJBQVcsRUFBQyxTQUFtQixDQUFDO1lBQzNDLG9CQUFvQixFQUFFLElBQUEsOEJBQVksRUFBQyxFQUFZLENBQUM7WUFDaEQsUUFBUSxFQUFFLEVBQUU7U0FDYixDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQyw4QkFBOEIsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQsU0FBZ0IseUJBQXlCLENBQUMsSUFBWTtJQUNwRCxJQUFJLElBQUksRUFBRSxRQUFRLEVBQUUsWUFBWSxDQUFDO0lBQ2pDLElBQUksUUFBa0IsQ0FBQztJQUN2QixJQUFJLE1BQWdCLENBQUM7SUFFckIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsaUNBQW9CLENBQUMsRUFBRSxDQUFDO1FBQzNDLE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQyw4QkFBOEIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBRUQsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsU0FBUyxDQUFDLEdBQUcsYUFBYSxDQUNqRiw4QkFBaUIsRUFDakIsbUJBQW1CLENBQUMsaUNBQW9CLEVBQUUsSUFBSSxDQUFDLENBQ2hELENBQUM7SUFFRixNQUFNLGVBQWUsR0FBRyxJQUFBLDZCQUFXLEVBQUMsWUFBc0IsQ0FBQyxDQUFDO0lBQzVELElBQUksZUFBZSxDQUFDLFVBQVUsQ0FBQyw0Q0FBK0IsQ0FBQyxFQUFFLENBQUM7UUFDaEUsSUFBSSxPQUFPLENBQUM7UUFDWixJQUFJLEtBQUssQ0FBQztRQUVWLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLGFBQWEsQ0FDNUQscUNBQXdCLEVBQ3hCLG1CQUFtQixDQUFDLDRDQUErQixFQUFFLGVBQWUsQ0FBQyxDQUN0RSxDQUFDO1FBRUYsUUFBUSxHQUFHLENBQUMsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDM0QsTUFBTSxHQUFHLENBQUMsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDekQsQ0FBQztTQUFNLElBQUksSUFBQSw2QkFBVyxFQUFDLFlBQXNCLENBQUMsQ0FBQyxVQUFVLENBQUMsNkNBQWdDLENBQUMsRUFBRSxDQUFDO1FBQzVGLElBQUksWUFBWSxFQUFFLFVBQVUsQ0FBQztRQUM3QixDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxZQUFZLENBQUMsR0FBRyxhQUFhLENBQ3RFLHNDQUF5QixFQUN6QixtQkFBbUIsQ0FBQyw2Q0FBZ0MsRUFBRSxlQUFlLENBQUMsQ0FDdkUsQ0FBQztRQUNGLFFBQVEsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLHNCQUFTLENBQUMsSUFBQSw2QkFBVyxFQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUM1RSxNQUFNLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDMUUsQ0FBQztTQUFNLENBQUM7UUFDTixNQUFNLElBQUksZ0NBQXFCLENBQUMsOEJBQThCLElBQUksRUFBRSxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVELE9BQU87UUFDTCxFQUFFLEVBQUUsSUFBQSw4QkFBWSxFQUFDLFFBQVEsQ0FBQztRQUMxQixJQUFJLEVBQUUsSUFBQSw4QkFBWSxFQUFDLElBQUksQ0FBQztRQUN4QixVQUFVLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFVBQW9CLENBQUM7UUFDN0MsTUFBTSxFQUFFLElBQUksc0JBQVMsQ0FBQyxJQUFBLDZCQUFXLEVBQUMsTUFBZ0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFO1FBQzlELFFBQVE7UUFDUixNQUFNO1FBQ04sVUFBVSxFQUFFLElBQUEsNkJBQVcsRUFBQyxVQUFvQixDQUFDO1FBQzdDLFNBQVMsRUFBRSxJQUFBLDZCQUFXLEVBQUMsU0FBbUIsQ0FBQztRQUMzQyxvQkFBb0IsRUFBRSxJQUFBLDhCQUFZLEVBQUMsRUFBWSxDQUFDO1FBQ2hELFFBQVEsRUFBRSxZQUFZO0tBQ3ZCLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0Isd0JBQXdCLENBQUMsSUFBWSxFQUFFLGFBQXVCO0lBQzVFLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGlDQUFvQixDQUFDLEVBQUUsQ0FBQztRQUMzQyxNQUFNLElBQUksZ0NBQXFCLENBQUMsOEJBQThCLElBQUksRUFBRSxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVELElBQUksRUFBdUMsQ0FBQztJQUM1QyxJQUFJLE1BQTJDLENBQUM7SUFDaEQsSUFBSSxZQUFpRCxDQUFDO0lBQ3RELElBQUksVUFBK0MsQ0FBQztJQUNwRCxJQUFJLFVBQStDLENBQUM7SUFDcEQsSUFBSSxTQUE4QyxDQUFDO0lBQ25ELElBQUksTUFBMkMsQ0FBQztJQUNoRCxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDbkIsQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQyxHQUFHLGFBQWEsQ0FDM0UsOEJBQWlCLEVBQ2pCLG1CQUFtQixDQUFDLGlDQUFvQixFQUFFLElBQUksQ0FBQyxDQUNoRCxDQUFDO0lBQ0osQ0FBQztTQUFNLENBQUM7UUFDTixDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLEdBQUcsYUFBYSxDQUN4RSx5Q0FBNEIsRUFDNUIsbUJBQW1CLENBQUMsaUNBQW9CLEVBQUUsSUFBSSxDQUFDLENBQ2hELENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTztRQUNMLG1CQUFtQixFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUUsTUFBaUIsQ0FBQyxDQUFDLENBQUMsU0FBUztRQUNuRSxFQUFFLEVBQUUsSUFBQSw4QkFBWSxFQUFDLEVBQVksQ0FBQztRQUM5QixNQUFNLEVBQUUsSUFBSSxzQkFBUyxDQUFDLElBQUEsNkJBQVcsRUFBQyxNQUFnQixDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUU7UUFDOUQsVUFBVSxFQUFFLElBQUEsNkJBQVcsRUFBQyxVQUFvQixDQUFDO1FBQzdDLFVBQVUsRUFBRSxJQUFBLDZCQUFXLEVBQUMsVUFBb0IsQ0FBQztRQUM3QyxTQUFTLEVBQUUsSUFBQSw2QkFBVyxFQUFDLFNBQW1CLENBQUM7UUFDM0MsSUFBSSxFQUFFLElBQUEsNkJBQVcsRUFBQyxZQUFzQixDQUFDO0tBQzFDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IscUJBQXFCLENBQUMsSUFBWSxFQUFFLEVBQVc7SUFDN0QsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLHlDQUE0QixDQUFDLEVBQUUsQ0FBQztRQUNsRCxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLEdBQUcsYUFBYSxDQUNwRCw2QkFBZ0IsRUFDaEIsbUJBQW1CLENBQUMseUNBQTRCLEVBQUUsSUFBSSxDQUFDLENBQ3hELENBQUM7UUFDRixPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsSUFBQSw4QkFBWSxFQUFDLGdCQUEwQixDQUFDO1lBQzFELFlBQVksRUFBRSxJQUFBLDhCQUFZLEVBQUMsWUFBc0IsQ0FBQztTQUNuRCxDQUFDO0lBQ0osQ0FBQztTQUFNLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQywyQ0FBOEIsQ0FBQyxFQUFFLENBQUM7UUFDM0QsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLGFBQWEsQ0FBQywrQkFBa0IsRUFBRSxtQkFBbUIsQ0FBQywyQ0FBOEIsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3BILElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNSLE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQyx1QkFBdUIsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMvRCxDQUFDO1FBQ0QsT0FBTztZQUNMLGdCQUFnQixFQUFFLEVBQUU7WUFDcEIsWUFBWSxFQUFFLElBQUEsOEJBQVksRUFBQyxZQUFzQixDQUFDO1lBQ2xELGdCQUFnQixFQUFFLENBQUM7U0FDcEIsQ0FBQztJQUNKLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxJQUFJLGdDQUFxQixDQUFDLDhCQUE4QixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQUMsSUFBWTtJQUM5QyxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDckIsaUVBQWlFO1FBQ2pFLG9GQUFvRjtRQUNwRixPQUFPLDBCQUFlLENBQUMsYUFBYSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxrRkFBa0Y7SUFDbEYsSUFBSSxlQUFlLEdBQUcsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUMzRSxJQUFJLGVBQWUsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNsQyxlQUFlLEdBQUcsMEJBQWUsQ0FBQyxZQUFZLENBQUM7SUFDakQsQ0FBQztJQUVELE9BQU8sZUFBZSxDQUFDO0FBQ3pCLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sbUJBQW1CLEdBQUc7SUFDMUIsQ0FBQywyQ0FBOEIsQ0FBQyxFQUFFLDBCQUFlLENBQUMsb0JBQW9CO0lBQ3RFLENBQUMsbURBQXNDLENBQUMsRUFBRSwwQkFBZSxDQUFDLHdCQUF3QjtJQUNsRixDQUFDLG1DQUFzQixDQUFDLEVBQUUsMEJBQWUsQ0FBQyxvQkFBb0I7SUFDOUQsQ0FBQyxvQ0FBdUIsQ0FBQyxFQUFFLDBCQUFlLENBQUMscUJBQXFCO0lBQ2hFLENBQUMsc0NBQXlCLENBQUMsRUFBRSwwQkFBZSxDQUFDLHFCQUFxQjtJQUNsRSxDQUFDLHNDQUF5QixDQUFDLEVBQUUsMEJBQWUsQ0FBQyxxQkFBcUI7SUFDbEUsQ0FBQyxpQ0FBb0IsQ0FBQyxFQUFFLDBCQUFlLENBQUMsSUFBSTtJQUM1QyxDQUFDLHlDQUE0QixDQUFDLEVBQUUsMEJBQWUsQ0FBQyxXQUFXO0lBQzNELENBQUMsMkNBQThCLENBQUMsRUFBRSwwQkFBZSxDQUFDLFdBQVc7SUFDN0QsQ0FBQywrQkFBa0IsQ0FBQyxFQUFFLDBCQUFlLENBQUMsVUFBVTtJQUNoRCxDQUFDLCtDQUFrQyxDQUFDLEVBQUUsMEJBQWUsQ0FBQyxXQUFXO0lBQ2pFLENBQUMsaURBQW9DLENBQUMsRUFBRSwwQkFBZSxDQUFDLFdBQVc7SUFDbkUsQ0FBQyxnREFBbUMsQ0FBQyxFQUFFLDBCQUFlLENBQUMsWUFBWTtJQUNuRSxDQUFDLGtEQUFxQyxDQUFDLEVBQUUsMEJBQWUsQ0FBQyxZQUFZO0lBQ3JFLENBQUMsc0NBQXlCLENBQUMsRUFBRSwwQkFBZSxDQUFDLElBQUk7SUFDakQsQ0FBQyx1QkFBWSxDQUFDLEVBQUUsMEJBQWUsQ0FBQyxXQUFXO0lBQzNDLENBQUMsdUJBQVksQ0FBQyxFQUFFLDBCQUFlLENBQUMsV0FBVztJQUMzQyxDQUFDLDJCQUFnQixDQUFDLEVBQUUsMEJBQWUsQ0FBQyxlQUFlO0lBQ25ELENBQUMseUJBQWMsQ0FBQyxFQUFFLDBCQUFlLENBQUMsYUFBYTtJQUMvQyxDQUFDLHlCQUFjLENBQUMsRUFBRSwwQkFBZSxDQUFDLGFBQWE7SUFDL0MsQ0FBQywyQkFBZ0IsQ0FBQyxFQUFFLDBCQUFlLENBQUMsZUFBZTtJQUNuRCw4RUFBOEU7SUFDOUUsbUZBQW1GO0lBQ25GLHlGQUF5RjtJQUN6RixrRkFBa0Y7SUFDbEYsc0ZBQXNGO0lBQ3RGLDZEQUE2RDtJQUM3RCxDQUFDLDZDQUFpQyxDQUFDLEVBQUUsMEJBQWUsQ0FBQyxvQkFBb0I7Q0FDMUUsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxHQUFXO0lBQzNDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0IsT0FBTyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7QUFDekQsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxHQUFXO0lBQzNDLE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFDcEMsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLGVBQXVCLEVBQUUsZUFBdUI7SUFDeEYsTUFBTSxnQkFBZ0IsR0FBRyxJQUFBLGlDQUFlLEVBQ3RDLGVBQU0sQ0FBQyxJQUFJLENBQUMsSUFBQSxnQ0FBYyxFQUFDLGVBQWUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUNuRCxlQUFNLENBQUMsSUFBSSxDQUFDLElBQUEsMkJBQVMsRUFBQyxJQUFBLGdDQUFjLEVBQUMsaUJBQWlCLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUNsRixDQUFDO0lBQ0YsT0FBTyxJQUFBLDhCQUFZLEVBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDeEQsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQiwyQkFBMkIsQ0FBQyxjQUFzQixFQUFFLElBQVksRUFBRSxRQUFnQjtJQUNoRyxNQUFNLGtCQUFrQixHQUFHLElBQUEsa0NBQWdCLEVBQ3pDLGVBQU0sQ0FBQyxJQUFJLENBQUMsSUFBQSxnQ0FBYyxFQUFDLGNBQWMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUNsRCxlQUFNLENBQUMsSUFBSSxDQUFDLElBQUEsZ0NBQWMsRUFBQyxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsRUFDeEMsZUFBTSxDQUFDLElBQUksQ0FBQyxJQUFBLDJCQUFTLEVBQUMsSUFBQSxnQ0FBYyxFQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQ3hELENBQUM7SUFDRixPQUFPLElBQUEsOEJBQVksRUFBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLHFCQUE2QjtJQUM1RCxNQUFNLE1BQU0sR0FBRyxJQUFBLGdDQUFjLEVBQUMscUJBQXFCLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBRXJGLCtCQUErQjtJQUMvQiw0SEFBNEg7SUFDNUgsT0FBTyw2Q0FBNkMsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixXQUFXLENBQUMsR0FBbUI7SUFDN0MsT0FBTyxJQUFBLDZCQUFXLEVBQ2hCLGVBQU0sQ0FBQyxNQUFNLENBQUM7UUFDWixJQUFBLCtCQUFhLEVBQUMsZUFBTSxDQUFDLElBQUksQ0FBQyxJQUFBLGdDQUFjLEVBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM1RCxJQUFBLCtCQUFhLEVBQUMsZUFBTSxDQUFDLElBQUksQ0FBQyxJQUFBLGdDQUFjLEVBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM1RCxJQUFBLDBCQUFRLEVBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztLQUNoQixDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLFlBQVksQ0FBQyxNQUFjO0lBQ3pDLE9BQU8sQ0FDTCxNQUFNLENBQUMsQ0FBQyxLQUFLLFNBQVM7UUFDdEIsTUFBTSxDQUFDLENBQUMsS0FBSyxTQUFTO1FBQ3RCLE1BQU0sQ0FBQyxDQUFDLEtBQUssU0FBUztRQUN0QixNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQ25CLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDbkIsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUNwQixDQUFDO0FBQ0osQ0FBQztBQUlEOzs7Ozs7R0FNRztBQUNILFNBQWdCLGFBQWEsQ0FBQyxLQUFlLEVBQUUsY0FBc0I7SUFDbkUsU0FBUyxTQUFTLENBQUMsQ0FBVSxFQUFFLENBQVM7UUFDdEMsSUFBSSxlQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsQ0FBQztRQUNYLENBQUM7YUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxlQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDdkQsT0FBTyxDQUFDLENBQUM7UUFDWCxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDNUIsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFCLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLFNBQVMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyx3QkFBVyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsY0FBYyxDQUFDLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ3JFLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixtQkFBbUIsQ0FBQyxRQUFnQixFQUFFLE9BQWU7SUFDbkUsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QyxJQUFJLGFBQWEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDL0IsTUFBTSxJQUFJLGdDQUFxQixDQUFDLDBCQUEwQixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFDRCxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3RDLE1BQU0sSUFBSSxnQ0FBcUIsQ0FBQywwQkFBMEIsT0FBTyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFDRCxPQUFPLGVBQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsU0FBZ0IsUUFBUSxDQUN0QixvQkFBNEIsRUFDNUIsT0FBb0IsRUFDcEIsTUFBYztJQUVkLHVHQUF1RztJQUN2RywrR0FBK0c7SUFDL0csTUFBTSxNQUFNLEdBQUcsZUFBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1FBQ25DLElBQUksSUFBSSxZQUFZLHFDQUEyQixFQUFFLENBQUM7WUFDaEQsT0FBTyxDQUNMLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQyxJQUFJO2dCQUNsQyxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU07Z0JBQ3RCLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxFQUFFLEtBQUssb0JBQW9CLENBQUMsV0FBVyxFQUFFLENBQzFFLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDLENBQUMsQ0FBQztJQUVILG9FQUFvRTtJQUNwRSxvRkFBb0Y7SUFDcEYsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakQsSUFBSSxXQUFXLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzVCLDBGQUEwRjtRQUMxRixJQUFBLGdCQUFNLEVBQUMsV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNqQyxPQUFPLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLDZCQUE2QixDQUFDLFlBQXNCLEVBQUUsSUFBWTtJQUNoRixNQUFNLFVBQVUsR0FBRyxJQUFBLCtCQUFhLEVBQUMsSUFBQSwwQkFBUSxFQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELE1BQU0sTUFBTSxHQUFHLENBQUMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzFDLE1BQU0sTUFBTSxHQUFHLHdCQUFXLENBQUMsUUFBUSxDQUFDLGNBQWMsRUFBRSxnQ0FBbUIsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sSUFBSSxHQUFHLHdCQUFXLENBQUMsU0FBUyxDQUFDLGdDQUFtQixFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2hFLE9BQU8sSUFBQSw4QkFBWSxFQUFDLGVBQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUNyRSxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQWdCLDhCQUE4QixDQUFDLFdBQW1CLEVBQUUsSUFBWSxFQUFFLFVBQW1CO0lBQ25HLE1BQU0sVUFBVSxHQUFHLElBQUEsK0JBQWEsRUFBQyxJQUFBLDBCQUFRLEVBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDckQsTUFBTSxFQUFFLHFCQUFxQixFQUFFLG9CQUFvQixFQUFFLEdBQUcsZ0NBQWdDLENBQ3RGLFdBQVcsRUFDWCxVQUFVLEVBQ1YsVUFBVSxDQUNYLENBQUM7SUFFRixNQUFNLE1BQU0sR0FBRyx3QkFBVyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO0lBQzdFLE1BQU0sSUFBSSxHQUFHLHdCQUFXLENBQUMsU0FBUyxDQUFDLG9CQUFvQixFQUFFLHFCQUFxQixDQUFDLENBQUM7SUFDaEYsT0FBTyxJQUFBLDhCQUFZLEVBQUMsZUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3JFLENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxTQUFnQixzQ0FBc0MsQ0FDcEQsZ0JBQXdCLEVBQ3hCLFdBQW1CLEVBQ25CLElBQVksRUFDWixVQUFtQjtJQUVuQixJQUFJLGdCQUFnQixLQUFLLG9DQUF1QixFQUFFLENBQUM7UUFDakQsT0FBTyw0QkFBNEIsRUFBRSxDQUFDO0lBQ3hDLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyw4QkFBOEIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILFNBQWdCLGdDQUFnQyxDQUM5QyxXQUFtQixFQUNuQixVQUFrQixFQUNsQixVQUFtQjtJQUVuQixJQUFJLHFCQUFxQixHQUFHLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RELElBQUksb0JBQW9CLEdBQUcsbUNBQXNCLENBQUM7SUFDbEQsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNmLHFCQUFxQixHQUFHLENBQUMsV0FBVyxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUM5RCxvQkFBb0IsR0FBRyxtQ0FBc0IsQ0FBQztJQUNoRCxDQUFDO0lBQ0QsT0FBTyxFQUFFLHFCQUFxQixFQUFFLG9CQUFvQixFQUFFLENBQUM7QUFDekQsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsMkJBQTJCLENBQUMsSUFBWTtJQUN0RCxJQUNFLENBQUMsQ0FDQyxJQUFJLENBQUMsVUFBVSxDQUFDLHNDQUF5QixDQUFDO1FBQzFDLElBQUksQ0FBQyxVQUFVLENBQUMsc0NBQXlCLENBQUM7UUFDMUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxvQ0FBdUIsQ0FBQyxDQUN6QyxFQUNELENBQUM7UUFDRCxNQUFNLElBQUksZ0NBQXFCLENBQUMsNkJBQTZCLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdkUsQ0FBQztJQUVELElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxvQ0FBdUIsQ0FBQyxFQUFFLENBQUM7UUFDN0MsT0FBTztZQUNMLFdBQVcsRUFBRSxTQUFTO1lBQ3RCLG1CQUFtQixFQUFFLFNBQVM7WUFDOUIsVUFBVSxFQUFFLFNBQVM7U0FDdEIsQ0FBQztJQUNKLENBQUM7U0FBTSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsc0NBQXlCLENBQUMsRUFBRSxDQUFDO1FBQ3RELE1BQU0sQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsYUFBYSxDQUM3QyxtQ0FBc0IsRUFDdEIsbUJBQW1CLENBQUMsc0NBQXlCLEVBQUUsSUFBSSxDQUFDLENBQ3JELENBQUM7UUFFRixPQUFPO1lBQ0wsV0FBVyxFQUFFLElBQUEsOEJBQVksRUFBQyxXQUFxQixDQUFDO1lBQ2hELG1CQUFtQixFQUFFLElBQUEsNkJBQVcsRUFBQyxVQUFvQixDQUFDO1lBQ3RELFVBQVUsRUFBRSxTQUFTO1NBQ2IsQ0FBQztJQUNiLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxDQUFDLFdBQVcsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLEdBQUcsYUFBYSxDQUN6RCxtQ0FBc0IsRUFDdEIsbUJBQW1CLENBQUMsc0NBQXlCLEVBQUUsSUFBSSxDQUFDLENBQ3JELENBQUM7UUFFRixPQUFPO1lBQ0wsV0FBVyxFQUFFLElBQUEsOEJBQVksRUFBQyxXQUFxQixDQUFDO1lBQ2hELG1CQUFtQixFQUFFLElBQUEsNkJBQVcsRUFBQyxVQUFvQixDQUFDO1lBQ3RELFVBQVUsRUFBRSxJQUFBLDhCQUFZLEVBQUMsVUFBb0IsQ0FBQztTQUN0QyxDQUFDO0lBQ2IsQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSSxLQUFLLFVBQVUsK0JBQStCLENBQ25ELEtBQTZCLEVBQzdCLFdBQW1CLEVBQ25CLEtBQWM7SUFFZCxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1YsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDdkIsQ0FBQztJQUNELE1BQU0sUUFBUSxHQUFHLE1BQU0sb0JBQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxXQUFXLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUV0RSxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxHQUFHLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDdEUsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUM7QUFDdkIsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLG9CQUFvQjtJQUNsQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFDcEUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5pbXBvcnQgcmVxdWVzdCBmcm9tICdzdXBlcmFnZW50JztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7XG4gIGFkZEhleFByZWZpeCxcbiAgYnVmZmVyVG9IZXgsXG4gIGJ1ZmZlclRvSW50LFxuICBnZW5lcmF0ZUFkZHJlc3MsXG4gIGlzVmFsaWRBZGRyZXNzLFxuICBzZXRMZW5ndGhMZWZ0LFxuICBzdHJpcEhleFByZWZpeCxcbiAgdG9CdWZmZXIsXG4gIGdlbmVyYXRlQWRkcmVzczIsXG4gIHBhZFRvRXZlbixcbn0gZnJvbSAnZXRoZXJldW1qcy11dGlsJztcbmltcG9ydCB7IEJhc2VDb2luLCBCYXNlTmV0d29yaywgY29pbnMsIENvbnRyYWN0QWRkcmVzc0RlZmluZWRUb2tlbiwgRXRoZXJldW1OZXR3b3JrIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgRXRoZXJldW1BYmkgZnJvbSAnZXRoZXJldW1qcy1hYmknO1xuaW1wb3J0IEV0aGVyZXVtQ29tbW9uIGZyb20gJ0BldGhlcmV1bWpzL2NvbW1vbic7XG5pbXBvcnQgQk4gZnJvbSAnYm4uanMnO1xuaW1wb3J0IEJpZ051bWJlciBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0IHtcbiAgQWN0aXZhdGVNZXRob2RJZCxcbiAgQnVpbGRUcmFuc2FjdGlvbkVycm9yLFxuICBMb2NrTWV0aG9kSWQsXG4gIFNpZ25pbmdFcnJvcixcbiAgVHJhbnNhY3Rpb25UeXBlLFxuICBVbmxvY2tNZXRob2RJZCxcbiAgVW52b3RlTWV0aG9kSWQsXG4gIFZvdGVNZXRob2RJZCxcbiAgV2l0aGRyYXdNZXRob2RJZCxcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuXG5pbXBvcnQge1xuICBFUkMxMTU1VHJhbnNmZXJEYXRhLFxuICBFUkM3MjFUcmFuc2ZlckRhdGEsXG4gIEZsdXNoVG9rZW5zRGF0YSxcbiAgTmF0aXZlVHJhbnNmZXJEYXRhLFxuICBTaWduYXR1cmVQYXJ0cyxcbiAgVG9rZW5UcmFuc2ZlckRhdGEsXG4gIFRyYW5zZmVyRGF0YSxcbiAgVHhEYXRhLFxuICBXYWxsZXRJbml0aWFsaXphdGlvbkRhdGEsXG4gIEZvcndhcmRlckluaXRpYWxpemF0aW9uRGF0YSxcbn0gZnJvbSAnLi9pZmFjZSc7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCB7XG4gIGNyZWF0ZUZvcndhcmRlck1ldGhvZElkLFxuICBFUkMxMTU1QmF0Y2hUcmFuc2ZlclR5cGVNZXRob2RJZCxcbiAgRVJDMTE1NUJhdGNoVHJhbnNmZXJUeXBlcyxcbiAgRVJDMTE1NVNhZmVUcmFuc2ZlclR5cGVNZXRob2RJZCxcbiAgRVJDMTE1NVNhZmVUcmFuc2ZlclR5cGVzLFxuICBFUkM3MjFTYWZlVHJhbnNmZXJUeXBlTWV0aG9kSWQsXG4gIEVSQzcyMVNhZmVUcmFuc2ZlclR5cGVzLFxuICBFUkM3MjFUcmFuc2ZlckZyb21NZXRob2RJZCxcbiAgRVJDNzIxVHJhbnNmZXJGcm9tVHlwZXMsXG4gIGZsdXNoQ29pbnNNZXRob2RJZCxcbiAgZmx1c2hDb2luc1R5cGVzLFxuICBmbHVzaEZvcndhcmRlclRva2Vuc01ldGhvZElkLFxuICBmbHVzaFRva2Vuc1R5cGVzLFxuICBmbHVzaEVSQzcyMUZvcndhcmRlclRva2Vuc01ldGhvZElkLFxuICBmbHVzaEVSQzcyMUZvcndhcmRlclRva2Vuc01ldGhvZElkVjQsXG4gIGZsdXNoRVJDNzIxVG9rZW5zVHlwZXMsXG4gIGZsdXNoRVJDNzIxVG9rZW5zVHlwZXN2NCxcbiAgZmx1c2hFUkMxMTU1Rm9yd2FyZGVyVG9rZW5zTWV0aG9kSWQsXG4gIGZsdXNoRVJDMTE1NUZvcndhcmRlclRva2Vuc01ldGhvZElkVjQsXG4gIGZsdXNoRVJDMTE1NVRva2Vuc1R5cGVzLFxuICBmbHVzaEVSQzExNTVUb2tlbnNUeXBlc3Y0LFxuICBzZW5kTXVsdGlzaWdNZXRob2RJZCxcbiAgc2VuZE11bHRpc2lnVG9rZW5NZXRob2RJZCxcbiAgc2VuZE11bHRpU2lnVG9rZW5UeXBlcyxcbiAgc2VuZE11bHRpU2lnVHlwZXMsXG4gIHdhbGxldEluaXRpYWxpemF0aW9uRmlyc3RCeXRlcyxcbiAgdjFDcmVhdGVGb3J3YXJkZXJNZXRob2RJZCxcbiAgd2FsbGV0U2ltcGxlQ29uc3RydWN0b3IsXG4gIGNyZWF0ZVYxV2FsbGV0VHlwZXMsXG4gIHYxQ3JlYXRlV2FsbGV0TWV0aG9kSWQsXG4gIGNyZWF0ZVYxRm9yd2FyZGVyVHlwZXMsXG4gIHJlY292ZXJ5V2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzLFxuICBkZWZhdWx0Rm9yd2FyZGVyVmVyc2lvbixcbiAgY3JlYXRlVjRGb3J3YXJkZXJUeXBlcyxcbiAgdjRDcmVhdGVGb3J3YXJkZXJNZXRob2RJZCxcbiAgZmx1c2hUb2tlbnNUeXBlc3Y0LFxuICBmbHVzaEZvcndhcmRlclRva2Vuc01ldGhvZElkVjQsXG4gIHNlbmRNdWx0aVNpZ1Rva2VuVHlwZXNGaXJzdFNpZ25lcixcbiAgc2VuZE11bHRpU2lnVHlwZXNGaXJzdFNpZ25lcixcbn0gZnJvbSAnLi93YWxsZXRVdGlsJztcbmltcG9ydCB7IEV0aFRyYW5zYWN0aW9uRGF0YSB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgZGVsZWdhdGVGb3JVc2VyRGVjcnlwdGlvbk1ldGhvZElkIH0gZnJvbSAnLi96YW1hVXRpbHMnO1xuXG4vKipcbiAqIEBwYXJhbSBuZXR3b3JrXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb21tb24obmV0d29yazogRXRoZXJldW1OZXR3b3JrKTogRXRoZXJldW1Db21tb24ge1xuICByZXR1cm4gRXRoZXJldW1Db21tb24uZm9yQ3VzdG9tQ2hhaW4oXG4gICAgLy8gdXNlIHRoZSBtYWlubmV0IGNvbmZpZyBhcyBhIGJhc2UsIG92ZXJyaWRlIGNoYWluIGlkcyBhbmQgbmV0d29yayBuYW1lXG4gICAgJ21haW5uZXQnLFxuICAgIHtcbiAgICAgIG5hbWU6IG5ldHdvcmsudHlwZSxcbiAgICAgIG5ldHdvcmtJZDogbmV0d29yay5jaGFpbklkLFxuICAgICAgY2hhaW5JZDogbmV0d29yay5jaGFpbklkLFxuICAgIH0sXG4gICAgJ2xvbmRvbidcbiAgKTtcbn1cblxuLyoqXG4gKiBTaWducyB0aGUgdHJhbnNhY3Rpb24gdXNpbmcgdGhlIGFwcHJvcHJpYXRlIGFsZ29yaXRobVxuICogYW5kIHRoZSBwcm92aWRlZCBjb21tb24gZm9yIHRoZSBibG9ja2NoYWluXG4gKlxuICogQHBhcmFtIHtUeERhdGF9IHRyYW5zYWN0aW9uRGF0YSB0aGUgdHJhbnNhY3Rpb24gZGF0YSB0byBzaWduXG4gKiBAcGFyYW0ge0tleVBhaXJ9IGtleVBhaXIgdGhlIHNpZ25lcidzIGtleXBhaXJcbiAqIEBwYXJhbSB7RXRoZXJldW1Db21tb259IGN1c3RvbUNvbW1vbiB0aGUgbmV0d29yaydzIGN1c3RvbSBjb21tb25cbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0cmFuc2FjdGlvbiBzaWduZWQgYW5kIGVuY29kZWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ25JbnRlcm5hbChcbiAgdHJhbnNhY3Rpb25EYXRhOiBUeERhdGEsXG4gIGtleVBhaXI6IEtleVBhaXIsXG4gIGN1c3RvbUNvbW1vbjogRXRoZXJldW1Db21tb25cbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmICgha2V5UGFpci5nZXRLZXlzKCkucHJ2KSB7XG4gICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignTWlzc2luZyBwcml2YXRlIGtleScpO1xuICB9XG4gIGNvbnN0IGV0aFR4ID0gRXRoVHJhbnNhY3Rpb25EYXRhLmZyb21Kc29uKHRyYW5zYWN0aW9uRGF0YSwgY3VzdG9tQ29tbW9uKTtcbiAgZXRoVHguc2lnbihrZXlQYWlyKTtcbiAgcmV0dXJuIGV0aFR4LnRvU2VyaWFsaXplZCgpO1xufVxuXG4vKipcbiAqIFNpZ25zIHRoZSB0cmFuc2FjdGlvbiB1c2luZyB0aGUgYXBwcm9wcmlhdGUgYWxnb3JpdGhtXG4gKlxuICogQHBhcmFtIHtUeERhdGF9IHRyYW5zYWN0aW9uRGF0YSB0aGUgdHJhbnNhY3Rpb24gZGF0YSB0byBzaWduXG4gKiBAcGFyYW0ge0tleVBhaXJ9IGtleVBhaXIgdGhlIHNpZ25lcidzIGtleXBhaXJcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSB0cmFuc2FjdGlvbiBzaWduZWQgYW5kIGVuY29kZWRcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ24odHJhbnNhY3Rpb25EYXRhOiBUeERhdGEsIGtleVBhaXI6IEtleVBhaXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICByZXR1cm4gc2lnbkludGVybmFsKHRyYW5zYWN0aW9uRGF0YSwga2V5UGFpciwgZ2V0Q29tbW9uKGNvaW5zLmdldCgndGV0aCcpLm5ldHdvcmsgYXMgRXRoZXJldW1OZXR3b3JrKSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY29udHJhY3QgbWV0aG9kIGVuY29kZWQgZGF0YVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0byBkZXN0aW5hdGlvbiBhZGRyZXNzXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgQW1vdW50IHRvIHRyYW5mZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIGFkaXRpb25hbCBtZXRob2QgY2FsbCBkYXRhXG4gKiBAcGFyYW0ge251bWJlcn0gZXhwaXJlVGltZSBleHBpcmF0aW9uIHRpbWUgZm9yIHRoZSB0cmFuc2FjdGlvbiBpbiBzZWNvbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gc2VxdWVuY2VJZCBzZXF1ZW5jZSBpZFxuICogQHBhcmFtIHtzdHJpbmd9IHNpZ25hdHVyZSBzaWduYXR1cmUgb2YgdGhlIGNhbGxcbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0tIHRoZSBjb250cmFjdCBtZXRob2QgZW5jb2RlZCBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZW5kTXVsdGlTaWdEYXRhKFxuICB0bzogc3RyaW5nLFxuICB2YWx1ZTogc3RyaW5nLFxuICBkYXRhOiBzdHJpbmcsXG4gIGV4cGlyZVRpbWU6IG51bWJlcixcbiAgc2VxdWVuY2VJZDogbnVtYmVyLFxuICBzaWduYXR1cmU6IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgY29uc3QgcGFyYW1zID0gW3RvLCB2YWx1ZSwgdG9CdWZmZXIoZGF0YSksIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWQsIHRvQnVmZmVyKHNpZ25hdHVyZSldO1xuICBjb25zdCBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnc2VuZE11bHRpU2lnJywgc2VuZE11bHRpU2lnVHlwZXMpO1xuICBjb25zdCBhcmdzID0gRXRoZXJldW1BYmkucmF3RW5jb2RlKHNlbmRNdWx0aVNpZ1R5cGVzLCBwYXJhbXMpO1xuICByZXR1cm4gYWRkSGV4UHJlZml4KEJ1ZmZlci5jb25jYXQoW21ldGhvZCwgYXJnc10pLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY29udHJhY3QgbWV0aG9kIGVuY29kZWQgZGF0YVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0byBkZXN0aW5hdGlvbiBhZGRyZXNzXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgQW1vdW50IHRvIHRyYW5mZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSB0b2tlbkNvbnRyYWN0QWRkcmVzcyB0aGUgYWRkcmVzcyBvZiB0aGUgZXJjMjAgdG9rZW4gY29udHJhY3RcbiAqIEBwYXJhbSB7bnVtYmVyfSBleHBpcmVUaW1lIGV4cGlyYXRpb24gdGltZSBmb3IgdGhlIHRyYW5zYWN0aW9uIGluIHNlY29uZHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBzZXF1ZW5jZUlkIHNlcXVlbmNlIGlkXG4gKiBAcGFyYW0ge3N0cmluZ30gc2lnbmF0dXJlIHNpZ25hdHVyZSBvZiB0aGUgY2FsbFxuICogQHJldHVybnMge3N0cmluZ30gLS0gdGhlIGNvbnRyYWN0IG1ldGhvZCBlbmNvZGVkIGRhdGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRNdWx0aVNpZ1Rva2VuRGF0YShcbiAgdG86IHN0cmluZyxcbiAgdmFsdWU6IHN0cmluZyxcbiAgdG9rZW5Db250cmFjdEFkZHJlc3M6IHN0cmluZyxcbiAgZXhwaXJlVGltZTogbnVtYmVyLFxuICBzZXF1ZW5jZUlkOiBudW1iZXIsXG4gIHNpZ25hdHVyZTogc3RyaW5nXG4pOiBzdHJpbmcge1xuICBjb25zdCBwYXJhbXMgPSBbdG8sIHZhbHVlLCB0b2tlbkNvbnRyYWN0QWRkcmVzcywgZXhwaXJlVGltZSwgc2VxdWVuY2VJZCwgdG9CdWZmZXIoc2lnbmF0dXJlKV07XG5cbiAgY29uc3QgbWV0aG9kID0gRXRoZXJldW1BYmkubWV0aG9kSUQoJ3NlbmRNdWx0aVNpZ1Rva2VuJywgc2VuZE11bHRpU2lnVG9rZW5UeXBlcyk7XG4gIGNvbnN0IGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoc2VuZE11bHRpU2lnVG9rZW5UeXBlcywgcGFyYW1zKTtcbiAgcmV0dXJuIGFkZEhleFByZWZpeChCdWZmZXIuY29uY2F0KFttZXRob2QsIGFyZ3NdKS50b1N0cmluZygnaGV4JykpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgZGF0YSByZXF1aXJlZCB0byBtYWtlIGEgZmx1c2ggdG9rZW5zIGNvbnRyYWN0IGNhbGxcbiAqXG4gKiBAcGFyYW0gZm9yd2FyZGVyQWRkcmVzcyBUaGUgZm9yd2FyZGVyIGFkZHJlc3MgdG8gZmx1c2hcbiAqIEBwYXJhbSB0b2tlbkFkZHJlc3MgVGhlIHRva2VuIGFkZHJlc3MgdG8gZmx1c2ggZnJvbVxuICovXG5leHBvcnQgZnVuY3Rpb24gZmx1c2hUb2tlbnNEYXRhKGZvcndhcmRlckFkZHJlc3M6IHN0cmluZywgdG9rZW5BZGRyZXNzOiBzdHJpbmcsIGZvcndhcmRlclZlcnNpb246IG51bWJlcik6IHN0cmluZyB7XG4gIGxldCBwYXJhbXM6IHN0cmluZ1tdO1xuICBsZXQgbWV0aG9kOiBVaW50OEFycmF5O1xuICBsZXQgYXJnczogVWludDhBcnJheTtcblxuICBpZiAoZm9yd2FyZGVyVmVyc2lvbiA+PSA0KSB7XG4gICAgcGFyYW1zID0gW3Rva2VuQWRkcmVzc107XG4gICAgbWV0aG9kID0gRXRoZXJldW1BYmkubWV0aG9kSUQoJ2ZsdXNoVG9rZW5zJywgZmx1c2hUb2tlbnNUeXBlc3Y0KTtcbiAgICBhcmdzID0gRXRoZXJldW1BYmkucmF3RW5jb2RlKGZsdXNoVG9rZW5zVHlwZXN2NCwgcGFyYW1zKTtcbiAgfSBlbHNlIHtcbiAgICBwYXJhbXMgPSBbZm9yd2FyZGVyQWRkcmVzcywgdG9rZW5BZGRyZXNzXTtcbiAgICBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnZmx1c2hGb3J3YXJkZXJUb2tlbnMnLCBmbHVzaFRva2Vuc1R5cGVzKTtcbiAgICBhcmdzID0gRXRoZXJldW1BYmkucmF3RW5jb2RlKGZsdXNoVG9rZW5zVHlwZXMsIHBhcmFtcyk7XG4gIH1cbiAgcmV0dXJuIGFkZEhleFByZWZpeChCdWZmZXIuY29uY2F0KFttZXRob2QsIGFyZ3NdKS50b1N0cmluZygnaGV4JykpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgZGF0YSByZXF1aXJlZCB0byBtYWtlIGEgZmx1c2ggbmF0aXZlIGNvaW5zIGNvbnRyYWN0IGNhbGxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsdXNoQ29pbnNEYXRhKCk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcmFtcyA9IFtdO1xuICBjb25zdCBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnZmx1c2gnLCBmbHVzaENvaW5zVHlwZXMpO1xuICBjb25zdCBhcmdzID0gRXRoZXJldW1BYmkucmF3RW5jb2RlKGZsdXNoQ29pbnNUeXBlcywgcGFyYW1zKTtcbiAgcmV0dXJuIGFkZEhleFByZWZpeChCdWZmZXIuY29uY2F0KFttZXRob2QsIGFyZ3NdKS50b1N0cmluZygnaGV4JykpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgZGF0YSByZXF1aXJlZCB0byBtYWtlIGEgZmx1c2ggRVJDNzIxIHRva2VucyBjb250cmFjdCBjYWxsXG4gKiBAcGFyYW0gZm9yd2FyZGVyQWRkcmVzcyAtIFRoZSBmb3J3YXJkZXIgYWRkcmVzcyAoZm9yIHYwLXYzKVxuICogQHBhcmFtIHRva2VuQWRkcmVzcyAtIFRoZSBFUkM3MjEgdG9rZW4gY29udHJhY3QgYWRkcmVzc1xuICogQHBhcmFtIHRva2VuSWQgLSBUaGUgdG9rZW4gSUQgdG8gZmx1c2hcbiAqIEBwYXJhbSBmb3J3YXJkZXJWZXJzaW9uIC0gVGhlIGZvcndhcmRlciB2ZXJzaW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbHVzaEVSQzcyMVRva2Vuc0RhdGEoXG4gIGZvcndhcmRlckFkZHJlc3M6IHN0cmluZyxcbiAgdG9rZW5BZGRyZXNzOiBzdHJpbmcsXG4gIHRva2VuSWQ6IHN0cmluZyxcbiAgZm9yd2FyZGVyVmVyc2lvbjogbnVtYmVyXG4pOiBzdHJpbmcge1xuICBsZXQgcGFyYW1zOiAoc3RyaW5nIHwgQnVmZmVyKVtdO1xuICBsZXQgbWV0aG9kOiBVaW50OEFycmF5O1xuICBsZXQgYXJnczogVWludDhBcnJheTtcblxuICBpZiAoZm9yd2FyZGVyVmVyc2lvbiA+PSA0KSB7XG4gICAgcGFyYW1zID0gW3Rva2VuQWRkcmVzcywgdG9rZW5JZF07XG4gICAgbWV0aG9kID0gRXRoZXJldW1BYmkubWV0aG9kSUQoJ2ZsdXNoRVJDNzIxVG9rZW4nLCBmbHVzaEVSQzcyMVRva2Vuc1R5cGVzdjQpO1xuICAgIGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoZmx1c2hFUkM3MjFUb2tlbnNUeXBlc3Y0LCBwYXJhbXMpO1xuICB9IGVsc2Uge1xuICAgIHBhcmFtcyA9IFtmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3MsIHRva2VuSWRdO1xuICAgIG1ldGhvZCA9IEV0aGVyZXVtQWJpLm1ldGhvZElEKCdmbHVzaEVSQzcyMUZvcndhcmRlclRva2VucycsIGZsdXNoRVJDNzIxVG9rZW5zVHlwZXMpO1xuICAgIGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoZmx1c2hFUkM3MjFUb2tlbnNUeXBlcywgcGFyYW1zKTtcbiAgfVxuICByZXR1cm4gYWRkSGV4UHJlZml4KEJ1ZmZlci5jb25jYXQoW21ldGhvZCwgYXJnc10pLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogRGVjb2RlIHRoZSBnaXZlbiBBQkktZW5jb2RlZCBmbHVzaCBFUkM3MjEgdG9rZW5zIGRhdGFcbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGRlY29kZVxuICogQHBhcmFtIHRvIFRoZSB0byBhZGRyZXNzIChjb250cmFjdCBhZGRyZXNzIGZvciB2NCspXG4gKiBAcmV0dXJucyBwYXJzZWQgZmx1c2ggZGF0YSB3aXRoIGZvcndhcmRlckFkZHJlc3MsIHRva2VuQWRkcmVzcywgdG9rZW5JZCBhbmQgZm9yd2FyZGVyVmVyc2lvblxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRmx1c2hFUkM3MjFUb2tlbnNEYXRhKFxuICBkYXRhOiBzdHJpbmcsXG4gIHRvPzogc3RyaW5nXG4pOiB7XG4gIGZvcndhcmRlckFkZHJlc3M6IHN0cmluZztcbiAgdG9rZW5BZGRyZXNzOiBzdHJpbmc7XG4gIHRva2VuSWQ6IHN0cmluZztcbiAgZm9yd2FyZGVyVmVyc2lvbj86IG51bWJlcjtcbn0ge1xuICBpZiAoZGF0YS5zdGFydHNXaXRoKGZsdXNoRVJDNzIxRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRWNCkpIHtcbiAgICBpZiAoIXRvKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBNaXNzaW5nIHRvIGFkZHJlc3M6ICR7dG99YCk7XG4gICAgfVxuICAgIGNvbnN0IFt0b2tlbkFkZHJlc3MsIHRva2VuSWRdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGZsdXNoRVJDNzIxVG9rZW5zVHlwZXN2NCxcbiAgICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoZmx1c2hFUkM3MjFGb3J3YXJkZXJUb2tlbnNNZXRob2RJZFY0LCBkYXRhKVxuICAgICk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZvcndhcmRlckFkZHJlc3M6IHRvLFxuICAgICAgdG9rZW5BZGRyZXNzOiBhZGRIZXhQcmVmaXgodG9rZW5BZGRyZXNzIGFzIHN0cmluZyksXG4gICAgICB0b2tlbklkOiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHRva2VuSWQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgICAgZm9yd2FyZGVyVmVyc2lvbjogNCxcbiAgICB9O1xuICB9IGVsc2UgaWYgKGRhdGEuc3RhcnRzV2l0aChmbHVzaEVSQzcyMUZvcndhcmRlclRva2Vuc01ldGhvZElkKSkge1xuICAgIGNvbnN0IFtmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3MsIHRva2VuSWRdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGZsdXNoRVJDNzIxVG9rZW5zVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKGZsdXNoRVJDNzIxRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWQsIGRhdGEpXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAgZm9yd2FyZGVyQWRkcmVzczogYWRkSGV4UHJlZml4KGZvcndhcmRlckFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgICAgIHRva2VuQWRkcmVzczogYWRkSGV4UHJlZml4KHRva2VuQWRkcmVzcyBhcyBzdHJpbmcpLFxuICAgICAgdG9rZW5JZDogbmV3IEJpZ051bWJlcihidWZmZXJUb0hleCh0b2tlbklkIGFzIEJ1ZmZlcikpLnRvRml4ZWQoKSxcbiAgICB9O1xuICB9XG4gIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgZmx1c2ggRVJDNzIxIGJ5dGVjb2RlOiAke2RhdGF9YCk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBkYXRhIHJlcXVpcmVkIHRvIG1ha2UgYSBmbHVzaCBFUkMxMTU1IHRva2VucyBjb250cmFjdCBjYWxsXG4gKiBAcGFyYW0gZm9yd2FyZGVyQWRkcmVzcyAtIFRoZSBmb3J3YXJkZXIgYWRkcmVzcyAoZm9yIHYwLXYzKVxuICogQHBhcmFtIHRva2VuQWRkcmVzcyAtIFRoZSBFUkMxMTU1IHRva2VuIGNvbnRyYWN0IGFkZHJlc3NcbiAqIEBwYXJhbSB0b2tlbklkIC0gVGhlIHRva2VuIElEIHRvIGZsdXNoXG4gKiBAcGFyYW0gZm9yd2FyZGVyVmVyc2lvbiAtIFRoZSBmb3J3YXJkZXIgdmVyc2lvblxuICovXG5leHBvcnQgZnVuY3Rpb24gZmx1c2hFUkMxMTU1VG9rZW5zRGF0YShcbiAgZm9yd2FyZGVyQWRkcmVzczogc3RyaW5nLFxuICB0b2tlbkFkZHJlc3M6IHN0cmluZyxcbiAgdG9rZW5JZDogc3RyaW5nLFxuICBmb3J3YXJkZXJWZXJzaW9uOiBudW1iZXJcbik6IHN0cmluZyB7XG4gIGxldCBwYXJhbXM6IChzdHJpbmcgfCBCdWZmZXIpW107XG4gIGxldCBtZXRob2Q6IFVpbnQ4QXJyYXk7XG4gIGxldCBhcmdzOiBVaW50OEFycmF5O1xuXG4gIGlmIChmb3J3YXJkZXJWZXJzaW9uID49IDQpIHtcbiAgICBwYXJhbXMgPSBbdG9rZW5BZGRyZXNzLCB0b2tlbklkXTtcbiAgICBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnZmx1c2hFUkMxMTU1VG9rZW5zJywgZmx1c2hFUkMxMTU1VG9rZW5zVHlwZXN2NCk7XG4gICAgYXJncyA9IEV0aGVyZXVtQWJpLnJhd0VuY29kZShmbHVzaEVSQzExNTVUb2tlbnNUeXBlc3Y0LCBwYXJhbXMpO1xuICB9IGVsc2Uge1xuICAgIHBhcmFtcyA9IFtmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3MsIHRva2VuSWRdO1xuICAgIG1ldGhvZCA9IEV0aGVyZXVtQWJpLm1ldGhvZElEKCdmbHVzaEVSQzExNTVGb3J3YXJkZXJUb2tlbnMnLCBmbHVzaEVSQzExNTVUb2tlbnNUeXBlcyk7XG4gICAgYXJncyA9IEV0aGVyZXVtQWJpLnJhd0VuY29kZShmbHVzaEVSQzExNTVUb2tlbnNUeXBlcywgcGFyYW1zKTtcbiAgfVxuICByZXR1cm4gYWRkSGV4UHJlZml4KEJ1ZmZlci5jb25jYXQoW21ldGhvZCwgYXJnc10pLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogRGVjb2RlIHRoZSBnaXZlbiBBQkktZW5jb2RlZCBmbHVzaCBFUkMxMTU1IHRva2VucyBkYXRhXG4gKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBkZWNvZGVcbiAqIEBwYXJhbSB0byBUaGUgdG8gYWRkcmVzcyAoY29udHJhY3QgYWRkcmVzcyBmb3IgdjQrKVxuICogQHJldHVybnMgcGFyc2VkIGZsdXNoIGRhdGEgd2l0aCBmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3MsIHRva2VuSWQgYW5kIGZvcndhcmRlclZlcnNpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUZsdXNoRVJDMTE1NVRva2Vuc0RhdGEoXG4gIGRhdGE6IHN0cmluZyxcbiAgdG8/OiBzdHJpbmdcbik6IHtcbiAgZm9yd2FyZGVyQWRkcmVzczogc3RyaW5nO1xuICB0b2tlbkFkZHJlc3M6IHN0cmluZztcbiAgdG9rZW5JZDogc3RyaW5nO1xuICBmb3J3YXJkZXJWZXJzaW9uPzogbnVtYmVyO1xufSB7XG4gIGlmIChkYXRhLnN0YXJ0c1dpdGgoZmx1c2hFUkMxMTU1Rm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRWNCkpIHtcbiAgICBpZiAoIXRvKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBNaXNzaW5nIHRvIGFkZHJlc3M6ICR7dG99YCk7XG4gICAgfVxuICAgIGNvbnN0IFt0b2tlbkFkZHJlc3MsIHRva2VuSWRdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGZsdXNoRVJDMTE1NVRva2Vuc1R5cGVzdjQsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKGZsdXNoRVJDMTE1NUZvcndhcmRlclRva2Vuc01ldGhvZElkVjQsIGRhdGEpXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAgZm9yd2FyZGVyQWRkcmVzczogdG8sXG4gICAgICB0b2tlbkFkZHJlc3M6IGFkZEhleFByZWZpeCh0b2tlbkFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgICAgIHRva2VuSWQ6IG5ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgodG9rZW5JZCBhcyBCdWZmZXIpKS50b0ZpeGVkKCksXG4gICAgICBmb3J3YXJkZXJWZXJzaW9uOiA0LFxuICAgIH07XG4gIH0gZWxzZSBpZiAoZGF0YS5zdGFydHNXaXRoKGZsdXNoRVJDMTE1NUZvcndhcmRlclRva2Vuc01ldGhvZElkKSkge1xuICAgIGNvbnN0IFtmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3MsIHRva2VuSWRdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGZsdXNoRVJDMTE1NVRva2Vuc1R5cGVzLFxuICAgICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShmbHVzaEVSQzExNTVGb3J3YXJkZXJUb2tlbnNNZXRob2RJZCwgZGF0YSlcbiAgICApO1xuICAgIHJldHVybiB7XG4gICAgICBmb3J3YXJkZXJBZGRyZXNzOiBhZGRIZXhQcmVmaXgoZm9yd2FyZGVyQWRkcmVzcyBhcyBzdHJpbmcpLFxuICAgICAgdG9rZW5BZGRyZXNzOiBhZGRIZXhQcmVmaXgodG9rZW5BZGRyZXNzIGFzIHN0cmluZyksXG4gICAgICB0b2tlbklkOiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHRva2VuSWQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgIH07XG4gIH1cbiAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBmbHVzaCBFUkMxMTU1IGJ5dGVjb2RlOiAke2RhdGF9YCk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgY3JlYXRlIGZvcndhcmRlciBtZXRob2QgY2FsbGluZyBkYXRhXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gLSB0aGUgY3JlYXRlRm9yd2FyZGVyIG1ldGhvZCBlbmNvZGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRyZXNzSW5pdGlhbGl6YXRpb25EYXRhKCk6IHN0cmluZyB7XG4gIHJldHVybiBjcmVhdGVGb3J3YXJkZXJNZXRob2RJZDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBFdGggYWRkcmVzc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIC0gdGhlIHR4IGhhc2ggdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEV0aEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBhbW91bnQgbnVtYmVyXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGFtb3VudCAtIHRoZSBzdHJpbmcgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIHRoZSB2YWxpZGF0aW9uIHJlc3VsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEFtb3VudChhbW91bnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBiaWdOdW1iZXJBbW91bnQgPSBuZXcgQmlnTnVtYmVyKGFtb3VudCk7XG4gIHJldHVybiBiaWdOdW1iZXJBbW91bnQuaXNJbnRlZ2VyKCkgJiYgYmlnTnVtYmVyQW1vdW50LmlzR3JlYXRlclRoYW5PckVxdWFsVG8oMCk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc21hcnQgY29udHJhY3QgZW5jb2RlZCBkYXRhXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgVGhlIHdhbGxldCBjcmVhdGlvbiBkYXRhIHRvIGRlY29kZVxuICogQHJldHVybnMge3N0cmluZ1tdfSAtIFRoZSBsaXN0IG9mIHNpZ25lciBhZGRyZXNzZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVdhbGxldENyZWF0aW9uRGF0YShkYXRhOiBzdHJpbmcpOiBXYWxsZXRJbml0aWFsaXphdGlvbkRhdGEge1xuICBpZiAoIShkYXRhLnN0YXJ0c1dpdGgod2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzKSB8fCBkYXRhLnN0YXJ0c1dpdGgodjFDcmVhdGVXYWxsZXRNZXRob2RJZCkpKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB3YWxsZXQgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGlmIChkYXRhLnN0YXJ0c1dpdGgod2FsbGV0SW5pdGlhbGl6YXRpb25GaXJzdEJ5dGVzKSkge1xuICAgIGNvbnN0IGRhdGFCdWZmZXIgPSBCdWZmZXIuZnJvbShkYXRhLnNsaWNlKDIpLCAnaGV4Jyk7XG5cbiAgICAvLyB0aGUgbGFzdCAxNjAgYnl0ZXMgY29udGFpbiB0aGUgc2VyaWFsaXplZCBhZGRyZXNzIGFycmF5XG4gICAgY29uc3Qgc2VyaWFsaXplZFNpZ25lcnMgPSBkYXRhQnVmZmVyLnNsaWNlKC0xNjApO1xuXG4gICAgY29uc3QgcmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMgPSBFdGhlcmV1bUFiaS5yYXdEZWNvZGUod2FsbGV0U2ltcGxlQ29uc3RydWN0b3IsIHNlcmlhbGl6ZWRTaWduZXJzKTtcbiAgICBpZiAocmVzdWx0RW5jb2RlZFBhcmFtZXRlcnMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBDb3VsZCBub3QgZGVjb2RlIHdhbGxldCBjb25zdHJ1Y3RvciBieXRlY29kZTogJHtyZXN1bHRFbmNvZGVkUGFyYW1ldGVyc31gKTtcbiAgICB9XG5cbiAgICBjb25zdCBhZGRyZXNzZXM6IEJOW10gPSByZXN1bHRFbmNvZGVkUGFyYW1ldGVyc1swXTtcbiAgICBpZiAoYWRkcmVzc2VzLmxlbmd0aCAhPT0gMykge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgaW52YWxpZCBudW1iZXIgb2YgYWRkcmVzc2VzIGluIHBhcnNlZCBjb25zdHJ1Y3RvcjogJHthZGRyZXNzZXN9YCk7XG4gICAgfVxuXG4gICAgLy8gc29tZXRpbWVzIGV0aGVyZXVtanMtYWJpIHJlbW92ZXMgMCBwYWRkaW5nIGF0IHRoZSBzdGFydCBvZiBhZGRyZXNzZXMsXG4gICAgLy8gc28gd2Ugc2hvdWxkIHBhZCB1bnRpbCB0aGV5IGFyZSB0aGUgc3RhbmRhcmQgMjAgYnl0ZXNcbiAgICBjb25zdCBwYWRkZWRBZGRyZXNzZXMgPSBhZGRyZXNzZXMubWFwKChhZGRyZXNzKSA9PiBzdHJpcEhleFByZWZpeChhZGRyZXNzLnRvU3RyaW5nKCdoZXgnKSkucGFkU3RhcnQoNDAsICcwJykpO1xuXG4gICAgcmV0dXJuIHsgb3duZXJzOiBwYWRkZWRBZGRyZXNzZXMubWFwKChhZGRyZXNzKSA9PiBhZGRIZXhQcmVmaXgoYWRkcmVzcykpIH07XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgZGVjb2RlZERhdGFGb3JXYWxsZXRDcmVhdGlvbiA9IGdldFJhd0RlY29kZWQoXG4gICAgICBjcmVhdGVWMVdhbGxldFR5cGVzLFxuICAgICAgZ2V0QnVmZmVyZWRCeXRlQ29kZSh2MUNyZWF0ZVdhbGxldE1ldGhvZElkLCBkYXRhKVxuICAgICk7XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlZERhdGFGb3JXYWxsZXRDcmVhdGlvblswXSBhcyBzdHJpbmdbXTtcbiAgICBjb25zdCBzYWx0QnVmZmVyID0gZGVjb2RlZERhdGFGb3JXYWxsZXRDcmVhdGlvblsxXTtcbiAgICBjb25zdCBzYWx0ID0gYnVmZmVyVG9IZXgoc2FsdEJ1ZmZlciBhcyBCdWZmZXIpO1xuICAgIGNvbnN0IHBhZGRlZEFkZHJlc3NlcyA9IGFkZHJlc3Nlcy5tYXAoKGFkZHJlc3MpID0+IHN0cmlwSGV4UHJlZml4KGFkZHJlc3MudG9TdHJpbmcoKSkucGFkU3RhcnQoNDAsICcwJykpO1xuICAgIGNvbnN0IG93bmVycyA9IHBhZGRlZEFkZHJlc3Nlcy5tYXAoKGFkZHJlc3MpID0+IGFkZEhleFByZWZpeChhZGRyZXNzKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIG93bmVycyxcbiAgICAgIHNhbHQsXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIERlY29kZSB0aGUgZ2l2ZW4gQUJJLWVuY29kZWQgdHJhbnNmZXIgZGF0YSBhbmQgcmV0dXJuIHBhcnNlZCBmaWVsZHNcbiAqXG4gKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBkZWNvZGVcbiAqIEBwYXJhbSBpc0ZpcnN0U2lnbmVyIHdoZXRoZXIgdHJhbnNhY3Rpb24gaXMgYmVpbmcgYnVpbHQgZm9yIGEgZmlyc3Qgc2lnbmVyXG4gKiBAcmV0dXJucyBwYXJzZWQgdHJhbnNmZXIgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlVHJhbnNmZXJEYXRhKGRhdGE6IHN0cmluZywgaXNGaXJzdFNpZ25lcj86IGJvb2xlYW4pOiBUcmFuc2ZlckRhdGEge1xuICBpZiAoZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ01ldGhvZElkKSkge1xuICAgIHJldHVybiBkZWNvZGVOYXRpdmVUcmFuc2ZlckRhdGEoZGF0YSwgaXNGaXJzdFNpZ25lcik7XG4gIH0gZWxzZSBpZiAoZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ1Rva2VuTWV0aG9kSWQpKSB7XG4gICAgcmV0dXJuIGRlY29kZVRva2VuVHJhbnNmZXJEYXRhKGRhdGEsIGlzRmlyc3RTaWduZXIpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxufVxuXG4vKipcbiAqIERlY29kZSB0aGUgZ2l2ZW4gQUJJLWVuY29kZWQgdHJhbnNmZXIgZGF0YSBmb3IgdGhlIHNlbmRNdWx0aXNpZ1Rva2VuIGZ1bmN0aW9uIGFuZCByZXR1cm4gcGFyc2VkIGZpZWxkc1xuICpcbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGRlY29kZVxuICogQHBhcmFtIGlzRmlyc3RTaWduZXIgd2hldGhlciB0cmFuc2FjdGlvbiBpcyBiZWluZyBidWlsdCBmb3IgYSBmaXJzdCBzaWduZXJcbiAqIEByZXR1cm5zIHBhcnNlZCB0b2tlbiB0cmFuc2ZlciBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVUb2tlblRyYW5zZmVyRGF0YShkYXRhOiBzdHJpbmcsIGlzRmlyc3RTaWduZXI/OiBib29sZWFuKTogVG9rZW5UcmFuc2ZlckRhdGEge1xuICBpZiAoIWRhdGEuc3RhcnRzV2l0aChzZW5kTXVsdGlzaWdUb2tlbk1ldGhvZElkKSkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuICBsZXQgdG86IFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgYW1vdW50OiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IHRva2VuQ29udHJhY3RBZGRyZXNzOiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IGV4cGlyZVRpbWU6IFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgc2VxdWVuY2VJZDogUmVjdXJzaXZlQnVmZmVyT3JTdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBzaWduYXR1cmU6IFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgcHJlZml4OiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZyB8IHVuZGVmaW5lZDtcbiAgaWYgKCFpc0ZpcnN0U2lnbmVyKSB7XG4gICAgW3RvLCBhbW91bnQsIHRva2VuQ29udHJhY3RBZGRyZXNzLCBleHBpcmVUaW1lLCBzZXF1ZW5jZUlkLCBzaWduYXR1cmVdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIHNlbmRNdWx0aVNpZ1Rva2VuVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKHNlbmRNdWx0aXNpZ1Rva2VuTWV0aG9kSWQsIGRhdGEpXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBbcHJlZml4LCB0bywgYW1vdW50LCB0b2tlbkNvbnRyYWN0QWRkcmVzcywgZXhwaXJlVGltZSwgc2VxdWVuY2VJZF0gPSBnZXRSYXdEZWNvZGVkKFxuICAgICAgc2VuZE11bHRpU2lnVG9rZW5UeXBlc0ZpcnN0U2lnbmVyLFxuICAgICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShzZW5kTXVsdGlzaWdUb2tlbk1ldGhvZElkLCBkYXRhKVxuICAgICk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG9wZXJhdGlvbkhhc2hQcmVmaXg6IGlzRmlyc3RTaWduZXIgPyAocHJlZml4IGFzIHN0cmluZykgOiB1bmRlZmluZWQsXG4gICAgdG86IGFkZEhleFByZWZpeCh0byBhcyBzdHJpbmcpLFxuICAgIGFtb3VudDogbmV3IEJpZ051bWJlcihidWZmZXJUb0hleChhbW91bnQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgIGV4cGlyZVRpbWU6IGJ1ZmZlclRvSW50KGV4cGlyZVRpbWUgYXMgQnVmZmVyKSxcbiAgICBzZXF1ZW5jZUlkOiBidWZmZXJUb0ludChzZXF1ZW5jZUlkIGFzIEJ1ZmZlciksXG4gICAgc2lnbmF0dXJlOiBidWZmZXJUb0hleChzaWduYXR1cmUgYXMgQnVmZmVyKSxcbiAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogYWRkSGV4UHJlZml4KHRva2VuQ29udHJhY3RBZGRyZXNzIGFzIHN0cmluZyksXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVFUkM3MjFUcmFuc2ZlckRhdGEoZGF0YTogc3RyaW5nKTogRVJDNzIxVHJhbnNmZXJEYXRhIHtcbiAgaWYgKCFkYXRhLnN0YXJ0c1dpdGgoc2VuZE11bHRpc2lnTWV0aG9kSWQpKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG5cbiAgY29uc3QgW3RvLCBhbW91bnQsIGludGVybmFsRGF0YSwgZXhwaXJlVGltZSwgc2VxdWVuY2VJZCwgc2lnbmF0dXJlXSA9IGdldFJhd0RlY29kZWQoXG4gICAgc2VuZE11bHRpU2lnVHlwZXMsXG4gICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShzZW5kTXVsdGlzaWdNZXRob2RJZCwgZGF0YSlcbiAgKTtcblxuICBjb25zdCBpbnRlcm5hbERhdGFIZXggPSBidWZmZXJUb0hleChpbnRlcm5hbERhdGEgYXMgQnVmZmVyKTtcblxuICBpZiAoaW50ZXJuYWxEYXRhSGV4LnN0YXJ0c1dpdGgoRVJDNzIxU2FmZVRyYW5zZmVyVHlwZU1ldGhvZElkKSkge1xuICAgIGNvbnN0IFtmcm9tLCByZWNlaXZlciwgdG9rZW5JZCwgdXNlclNlbnREYXRhXSA9IGdldFJhd0RlY29kZWQoXG4gICAgICBFUkM3MjFTYWZlVHJhbnNmZXJUeXBlcyxcbiAgICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoRVJDNzIxU2FmZVRyYW5zZmVyVHlwZU1ldGhvZElkLCBpbnRlcm5hbERhdGFIZXgpXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0bzogYWRkSGV4UHJlZml4KHJlY2VpdmVyIGFzIHN0cmluZyksXG4gICAgICBmcm9tOiBhZGRIZXhQcmVmaXgoZnJvbSBhcyBzdHJpbmcpLFxuICAgICAgZXhwaXJlVGltZTogYnVmZmVyVG9JbnQoZXhwaXJlVGltZSBhcyBCdWZmZXIpLFxuICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KGFtb3VudCBhcyBCdWZmZXIpKS50b0ZpeGVkKCksXG4gICAgICB0b2tlbklkOiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHRva2VuSWQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgICAgc2VxdWVuY2VJZDogYnVmZmVyVG9JbnQoc2VxdWVuY2VJZCBhcyBCdWZmZXIpLFxuICAgICAgc2lnbmF0dXJlOiBidWZmZXJUb0hleChzaWduYXR1cmUgYXMgQnVmZmVyKSxcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBhZGRIZXhQcmVmaXgodG8gYXMgc3RyaW5nKSxcbiAgICAgIHVzZXJEYXRhOiBidWZmZXJUb0hleCh1c2VyU2VudERhdGEgYXMgQnVmZmVyKSxcbiAgICB9O1xuICB9XG5cbiAgaWYgKGludGVybmFsRGF0YUhleC5zdGFydHNXaXRoKEVSQzcyMVRyYW5zZmVyRnJvbU1ldGhvZElkKSkge1xuICAgIGNvbnN0IFtmcm9tLCByZWNlaXZlciwgdG9rZW5JZF0gPSBnZXRSYXdEZWNvZGVkKFxuICAgICAgRVJDNzIxVHJhbnNmZXJGcm9tVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKEVSQzcyMVRyYW5zZmVyRnJvbU1ldGhvZElkLCBpbnRlcm5hbERhdGFIZXgpXG4gICAgKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0bzogYWRkSGV4UHJlZml4KHJlY2VpdmVyIGFzIHN0cmluZyksXG4gICAgICBmcm9tOiBhZGRIZXhQcmVmaXgoZnJvbSBhcyBzdHJpbmcpLFxuICAgICAgZXhwaXJlVGltZTogYnVmZmVyVG9JbnQoZXhwaXJlVGltZSBhcyBCdWZmZXIpLFxuICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KGFtb3VudCBhcyBCdWZmZXIpKS50b0ZpeGVkKCksXG4gICAgICB0b2tlbklkOiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHRva2VuSWQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgICAgc2VxdWVuY2VJZDogYnVmZmVyVG9JbnQoc2VxdWVuY2VJZCBhcyBCdWZmZXIpLFxuICAgICAgc2lnbmF0dXJlOiBidWZmZXJUb0hleChzaWduYXR1cmUgYXMgQnVmZmVyKSxcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBhZGRIZXhQcmVmaXgodG8gYXMgc3RyaW5nKSxcbiAgICAgIHVzZXJEYXRhOiAnJyxcbiAgICB9O1xuICB9XG5cbiAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRVJDMTE1NVRyYW5zZmVyRGF0YShkYXRhOiBzdHJpbmcpOiBFUkMxMTU1VHJhbnNmZXJEYXRhIHtcbiAgbGV0IGZyb20sIHJlY2VpdmVyLCB1c2VyU2VudERhdGE7XG4gIGxldCB0b2tlbklkczogc3RyaW5nW107XG4gIGxldCB2YWx1ZXM6IHN0cmluZ1tdO1xuXG4gIGlmICghZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ01ldGhvZElkKSkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGNvbnN0IFt0bywgYW1vdW50LCBpbnRlcm5hbERhdGEsIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWQsIHNpZ25hdHVyZV0gPSBnZXRSYXdEZWNvZGVkKFxuICAgIHNlbmRNdWx0aVNpZ1R5cGVzLFxuICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoc2VuZE11bHRpc2lnTWV0aG9kSWQsIGRhdGEpXG4gICk7XG5cbiAgY29uc3QgaW50ZXJuYWxEYXRhSGV4ID0gYnVmZmVyVG9IZXgoaW50ZXJuYWxEYXRhIGFzIEJ1ZmZlcik7XG4gIGlmIChpbnRlcm5hbERhdGFIZXguc3RhcnRzV2l0aChFUkMxMTU1U2FmZVRyYW5zZmVyVHlwZU1ldGhvZElkKSkge1xuICAgIGxldCB0b2tlbklkO1xuICAgIGxldCB2YWx1ZTtcblxuICAgIFtmcm9tLCByZWNlaXZlciwgdG9rZW5JZCwgdmFsdWUsIHVzZXJTZW50RGF0YV0gPSBnZXRSYXdEZWNvZGVkKFxuICAgICAgRVJDMTE1NVNhZmVUcmFuc2ZlclR5cGVzLFxuICAgICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShFUkMxMTU1U2FmZVRyYW5zZmVyVHlwZU1ldGhvZElkLCBpbnRlcm5hbERhdGFIZXgpXG4gICAgKTtcblxuICAgIHRva2VuSWRzID0gW25ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgodG9rZW5JZCkpLnRvRml4ZWQoKV07XG4gICAgdmFsdWVzID0gW25ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgodmFsdWUpKS50b0ZpeGVkKCldO1xuICB9IGVsc2UgaWYgKGJ1ZmZlclRvSGV4KGludGVybmFsRGF0YSBhcyBCdWZmZXIpLnN0YXJ0c1dpdGgoRVJDMTE1NUJhdGNoVHJhbnNmZXJUeXBlTWV0aG9kSWQpKSB7XG4gICAgbGV0IHRlbXBUb2tlbklkcywgdGVtcFZhbHVlcztcbiAgICBbZnJvbSwgcmVjZWl2ZXIsIHRlbXBUb2tlbklkcywgdGVtcFZhbHVlcywgdXNlclNlbnREYXRhXSA9IGdldFJhd0RlY29kZWQoXG4gICAgICBFUkMxMTU1QmF0Y2hUcmFuc2ZlclR5cGVzLFxuICAgICAgZ2V0QnVmZmVyZWRCeXRlQ29kZShFUkMxMTU1QmF0Y2hUcmFuc2ZlclR5cGVNZXRob2RJZCwgaW50ZXJuYWxEYXRhSGV4KVxuICAgICk7XG4gICAgdG9rZW5JZHMgPSB0ZW1wVG9rZW5JZHMubWFwKCh4KSA9PiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHgpKS50b0ZpeGVkKCkpO1xuICAgIHZhbHVlcyA9IHRlbXBWYWx1ZXMubWFwKCh4KSA9PiBuZXcgQmlnTnVtYmVyKGJ1ZmZlclRvSGV4KHgpKS50b0ZpeGVkKCkpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdG86IGFkZEhleFByZWZpeChyZWNlaXZlciksXG4gICAgZnJvbTogYWRkSGV4UHJlZml4KGZyb20pLFxuICAgIGV4cGlyZVRpbWU6IGJ1ZmZlclRvSW50KGV4cGlyZVRpbWUgYXMgQnVmZmVyKSxcbiAgICBhbW91bnQ6IG5ldyBCaWdOdW1iZXIoYnVmZmVyVG9IZXgoYW1vdW50IGFzIEJ1ZmZlcikpLnRvRml4ZWQoKSxcbiAgICB0b2tlbklkcyxcbiAgICB2YWx1ZXMsXG4gICAgc2VxdWVuY2VJZDogYnVmZmVyVG9JbnQoc2VxdWVuY2VJZCBhcyBCdWZmZXIpLFxuICAgIHNpZ25hdHVyZTogYnVmZmVyVG9IZXgoc2lnbmF0dXJlIGFzIEJ1ZmZlciksXG4gICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IGFkZEhleFByZWZpeCh0byBhcyBzdHJpbmcpLFxuICAgIHVzZXJEYXRhOiB1c2VyU2VudERhdGEsXG4gIH07XG59XG5cbi8qKlxuICogRGVjb2RlIHRoZSBnaXZlbiBBQkktZW5jb2RlZCB0cmFuc2ZlciBkYXRhIGZvciB0aGUgc2VuZE11bHRpc2lnIGZ1bmN0aW9uIGFuZCByZXR1cm4gcGFyc2VkIGZpZWxkc1xuICpcbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGRlY29kZVxuICogQHBhcmFtIGlzRmlyc3RTaWduZXIgd2hldGhlciB0cmFuc2FjdGlvbiBpcyBiZWluZyBidWlsdCBmb3IgYSBmaXJzdCBzaWduZXJcbiAqIEByZXR1cm5zIHBhcnNlZCB0cmFuc2ZlciBkYXRhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVOYXRpdmVUcmFuc2ZlckRhdGEoZGF0YTogc3RyaW5nLCBpc0ZpcnN0U2lnbmVyPzogYm9vbGVhbik6IE5hdGl2ZVRyYW5zZmVyRGF0YSB7XG4gIGlmICghZGF0YS5zdGFydHNXaXRoKHNlbmRNdWx0aXNpZ01ldGhvZElkKSkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgdHJhbnNmZXIgYnl0ZWNvZGU6ICR7ZGF0YX1gKTtcbiAgfVxuXG4gIGxldCB0bzogUmVjdXJzaXZlQnVmZmVyT3JTdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBhbW91bnQ6IFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgaW50ZXJuYWxEYXRhOiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IGV4cGlyZVRpbWU6IFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgc2VxdWVuY2VJZDogUmVjdXJzaXZlQnVmZmVyT3JTdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBzaWduYXR1cmU6IFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nIHwgdW5kZWZpbmVkO1xuICBsZXQgcHJlZml4OiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZyB8IHVuZGVmaW5lZDtcbiAgaWYgKCFpc0ZpcnN0U2lnbmVyKSB7XG4gICAgW3RvLCBhbW91bnQsIGludGVybmFsRGF0YSwgZXhwaXJlVGltZSwgc2VxdWVuY2VJZCwgc2lnbmF0dXJlXSA9IGdldFJhd0RlY29kZWQoXG4gICAgICBzZW5kTXVsdGlTaWdUeXBlcyxcbiAgICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUoc2VuZE11bHRpc2lnTWV0aG9kSWQsIGRhdGEpXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBbcHJlZml4LCB0bywgYW1vdW50LCBpbnRlcm5hbERhdGEsIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWRdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIHNlbmRNdWx0aVNpZ1R5cGVzRmlyc3RTaWduZXIsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKHNlbmRNdWx0aXNpZ01ldGhvZElkLCBkYXRhKVxuICAgICk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG9wZXJhdGlvbkhhc2hQcmVmaXg6IGlzRmlyc3RTaWduZXIgPyAocHJlZml4IGFzIHN0cmluZykgOiB1bmRlZmluZWQsXG4gICAgdG86IGFkZEhleFByZWZpeCh0byBhcyBzdHJpbmcpLFxuICAgIGFtb3VudDogbmV3IEJpZ051bWJlcihidWZmZXJUb0hleChhbW91bnQgYXMgQnVmZmVyKSkudG9GaXhlZCgpLFxuICAgIGV4cGlyZVRpbWU6IGJ1ZmZlclRvSW50KGV4cGlyZVRpbWUgYXMgQnVmZmVyKSxcbiAgICBzZXF1ZW5jZUlkOiBidWZmZXJUb0ludChzZXF1ZW5jZUlkIGFzIEJ1ZmZlciksXG4gICAgc2lnbmF0dXJlOiBidWZmZXJUb0hleChzaWduYXR1cmUgYXMgQnVmZmVyKSxcbiAgICBkYXRhOiBidWZmZXJUb0hleChpbnRlcm5hbERhdGEgYXMgQnVmZmVyKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBEZWNvZGUgdGhlIGdpdmVuIEFCSS1lbmNvZGVkIGZsdXNoIHRva2VucyBkYXRhIGFuZCByZXR1cm4gcGFyc2VkIGZpZWxkc1xuICpcbiAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGRlY29kZVxuICogQHBhcmFtIHRvIE9wdGlvbmFsIHRvIHBhcmFtZXRlciBvZiB0eFxuICogQHJldHVybnMgcGFyc2VkIHRyYW5zZmVyIGRhdGFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUZsdXNoVG9rZW5zRGF0YShkYXRhOiBzdHJpbmcsIHRvPzogc3RyaW5nKTogRmx1c2hUb2tlbnNEYXRhIHtcbiAgaWYgKGRhdGEuc3RhcnRzV2l0aChmbHVzaEZvcndhcmRlclRva2Vuc01ldGhvZElkKSkge1xuICAgIGNvbnN0IFtmb3J3YXJkZXJBZGRyZXNzLCB0b2tlbkFkZHJlc3NdID0gZ2V0UmF3RGVjb2RlZChcbiAgICAgIGZsdXNoVG9rZW5zVHlwZXMsXG4gICAgICBnZXRCdWZmZXJlZEJ5dGVDb2RlKGZsdXNoRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWQsIGRhdGEpXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAgZm9yd2FyZGVyQWRkcmVzczogYWRkSGV4UHJlZml4KGZvcndhcmRlckFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgICAgIHRva2VuQWRkcmVzczogYWRkSGV4UHJlZml4KHRva2VuQWRkcmVzcyBhcyBzdHJpbmcpLFxuICAgIH07XG4gIH0gZWxzZSBpZiAoZGF0YS5zdGFydHNXaXRoKGZsdXNoRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRWNCkpIHtcbiAgICBjb25zdCBbdG9rZW5BZGRyZXNzXSA9IGdldFJhd0RlY29kZWQoZmx1c2hUb2tlbnNUeXBlc3Y0LCBnZXRCdWZmZXJlZEJ5dGVDb2RlKGZsdXNoRm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRWNCwgZGF0YSkpO1xuICAgIGlmICghdG8pIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYE1pc3NpbmcgdG8gYWRkcmVzczogJHt0b31gKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGZvcndhcmRlckFkZHJlc3M6IHRvLFxuICAgICAgdG9rZW5BZGRyZXNzOiBhZGRIZXhQcmVmaXgodG9rZW5BZGRyZXNzIGFzIHN0cmluZyksXG4gICAgICBmb3J3YXJkZXJWZXJzaW9uOiA0LFxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCB0cmFuc2ZlciBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG59XG5cbi8qKlxuICogQ2xhc3NpZnkgdGhlIGdpdmVuIHRyYW5zYWN0aW9uIGRhdGEgYmFzZWQgYXMgYSB0cmFuc2FjdGlvbiB0eXBlLlxuICogRVRIIHRyYW5zYWN0aW9ucyBhcmUgZGVmaW5lZCBieSB0aGUgZmlyc3QgOCBieXRlcyBvZiB0aGUgdHJhbnNhY3Rpb24gZGF0YSwgYWxzbyBrbm93biBhcyB0aGUgbWV0aG9kIGlkXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgVGhlIGRhdGEgdG8gY2xhc3NpZnkgdGhlIHRyYW5zYWN0aW9uIHdpdGhcbiAqIEByZXR1cm5zIHtUcmFuc2FjdGlvblR5cGV9IFRoZSBjbGFzc2lmaWVkIHRyYW5zYWN0aW9uIHR5cGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsYXNzaWZ5VHJhbnNhY3Rpb24oZGF0YTogc3RyaW5nKTogVHJhbnNhY3Rpb25UeXBlIHtcbiAgaWYgKGRhdGEubGVuZ3RoIDwgMTApIHtcbiAgICAvLyBjb250cmFjdCBjYWxscyBtdXN0IGhhdmUgYXQgbGVhc3QgNCBieXRlcyAobWV0aG9kIGlkKSBhbmQgJzB4J1xuICAgIC8vIGlmIGl0IGRvZXNuJ3QgaGF2ZSBlbm91Z2ggZGF0YSB0byBiZSBhIGNvbnRyYWN0IGNhbGwgaXQgbXVzdCBiZSBhIHNpbmdsZSBzaWcgc2VuZFxuICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGUuU2luZ2xlU2lnU2VuZDtcbiAgfVxuXG4gIC8vIFRPRE8oU1RMWC0xOTcwKTogdmFsaWRhdGUgaWYgd2UgYXJlIGdvaW5nIHRvIGNvbnN0cmFpbnQgdG8gc29tZSBtZXRob2RzIGFsbG93ZWRcbiAgbGV0IHRyYW5zYWN0aW9uVHlwZSA9IHRyYW5zYWN0aW9uVHlwZXNNYXBbZGF0YS5zbGljZSgwLCAxMCkudG9Mb3dlckNhc2UoKV07XG4gIGlmICh0cmFuc2FjdGlvblR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgIHRyYW5zYWN0aW9uVHlwZSA9IFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGw7XG4gIH1cblxuICByZXR1cm4gdHJhbnNhY3Rpb25UeXBlO1xufVxuXG4vKipcbiAqIEEgdHJhbnNhY3Rpb24gdHlwZXMgbWFwIGFjY29yZGluZyB0byB0aGUgc3RhcnRpbmcgcGFydCBvZiB0aGUgZW5jb2RlZCBkYXRhXG4gKi9cbmNvbnN0IHRyYW5zYWN0aW9uVHlwZXNNYXAgPSB7XG4gIFt3YWxsZXRJbml0aWFsaXphdGlvbkZpcnN0Qnl0ZXNdOiBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb24sXG4gIFtyZWNvdmVyeVdhbGxldEluaXRpYWxpemF0aW9uRmlyc3RCeXRlc106IFRyYW5zYWN0aW9uVHlwZS5SZWNvdmVyeVdhbGxldERlcGxveW1lbnQsXG4gIFt2MUNyZWF0ZVdhbGxldE1ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLldhbGxldEluaXRpYWxpemF0aW9uLFxuICBbY3JlYXRlRm9yd2FyZGVyTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuQWRkcmVzc0luaXRpYWxpemF0aW9uLFxuICBbdjFDcmVhdGVGb3J3YXJkZXJNZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5BZGRyZXNzSW5pdGlhbGl6YXRpb24sXG4gIFt2NENyZWF0ZUZvcndhcmRlck1ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLkFkZHJlc3NJbml0aWFsaXphdGlvbixcbiAgW3NlbmRNdWx0aXNpZ01ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLlNlbmQsXG4gIFtmbHVzaEZvcndhcmRlclRva2Vuc01ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLkZsdXNoVG9rZW5zLFxuICBbZmx1c2hGb3J3YXJkZXJUb2tlbnNNZXRob2RJZFY0XTogVHJhbnNhY3Rpb25UeXBlLkZsdXNoVG9rZW5zLFxuICBbZmx1c2hDb2luc01ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLkZsdXNoQ29pbnMsXG4gIFtmbHVzaEVSQzcyMUZvcndhcmRlclRva2Vuc01ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLkZsdXNoRVJDNzIxLFxuICBbZmx1c2hFUkM3MjFGb3J3YXJkZXJUb2tlbnNNZXRob2RJZFY0XTogVHJhbnNhY3Rpb25UeXBlLkZsdXNoRVJDNzIxLFxuICBbZmx1c2hFUkMxMTU1Rm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuRmx1c2hFUkMxMTU1LFxuICBbZmx1c2hFUkMxMTU1Rm9yd2FyZGVyVG9rZW5zTWV0aG9kSWRWNF06IFRyYW5zYWN0aW9uVHlwZS5GbHVzaEVSQzExNTUsXG4gIFtzZW5kTXVsdGlzaWdUb2tlbk1ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLlNlbmQsXG4gIFtMb2NrTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0xvY2ssXG4gIFtWb3RlTWV0aG9kSWRdOiBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1ZvdGUsXG4gIFtBY3RpdmF0ZU1ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZSxcbiAgW1Vudm90ZU1ldGhvZElkXTogVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbnZvdGUsXG4gIFtVbmxvY2tNZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nVW5sb2NrLFxuICBbV2l0aGRyYXdNZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXcsXG4gIC8vIGFjbE11bHRpY2FsbE1ldGhvZElkIChtdWx0aWNhbGwoYnl0ZXNbXSkpIGlzIGludGVudGlvbmFsbHkgTk9UIG1hcHBlZCBoZXJlLlxuICAvLyBjbGFzc2lmeVRyYW5zYWN0aW9uKCkgb25seSBzZWVzIGNhbGxkYXRhLCBub3QgYHRvYCwgc28gMHhhYzk2NTBkOCB3b3VsZCBtaXNsYWJlbFxuICAvLyBhbnkgT3BlblplcHBlbGluIE11bHRpY2FsbFVwZ3JhZGVhYmxlIGNhbGwgKHJvdXRlcnMsIGFnZ3JlZ2F0b3JzLCB1bnJlbGF0ZWQgY29udHJhY3RzKVxuICAvLyBhcyBEZWNyeXB0aW9uRGVsZWdhdGlvbi4gQnVpbGRlciBvdXRwdXQgKHdoaWNoIGFsd2F5cyB1c2VzIG11bHRpY2FsbCkgdGhlcmVmb3JlXG4gIC8vIGNsYXNzaWZpZXMgYXMgQ29udHJhY3RDYWxsOyBjYWxsZXJzIHNob3VsZCBzZXQgVHJhbnNhY3Rpb25UeXBlLkRlY3J5cHRpb25EZWxlZ2F0aW9uXG4gIC8vIGV4cGxpY2l0bHkgd2hlbiBidWlsZGluZyBmcm9tIGEga25vd24gZGVsZWdhdGlvbiB0ZW1wbGF0ZS5cbiAgW2RlbGVnYXRlRm9yVXNlckRlY3J5cHRpb25NZXRob2RJZF06IFRyYW5zYWN0aW9uVHlwZS5EZWNyeXB0aW9uRGVsZWdhdGlvbixcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBudW0gbnVtYmVyIHRvIGJlIGNvbnZlcnRlZCB0byBoZXhcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBoZXggbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJUb0hleFN0cmluZyhudW06IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGhleCA9IG51bS50b1N0cmluZygxNik7XG4gIHJldHVybiBoZXgubGVuZ3RoICUgMiA9PT0gMCA/ICcweCcgKyBoZXggOiAnMHgwJyArIGhleDtcbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGhleCBUaGUgaGV4IHN0cmluZyB0byBiZSBjb252ZXJ0ZWRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IHRoZSByZXN1bHRpbmcgbnVtYmVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoZXhTdHJpbmdUb051bWJlcihoZXg6IHN0cmluZyk6IG51bWJlciB7XG4gIHJldHVybiBwYXJzZUludChoZXguc2xpY2UoMiksIDE2KTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYW4gYWRkcmVzcyBvZiB0aGUgZm9yd2FyZGVyIGFkZHJlc3MgdG8gYmUgZGVwbG95ZWRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udHJhY3RBZGRyZXNzIHRoZSBhZGRyZXNzIHdoaWNoIGlzIGNyZWF0aW5nIHRoaXMgbmV3IGFkZHJlc3NcbiAqIEBwYXJhbSB7bnVtYmVyfSBjb250cmFjdENvdW50ZXIgdGhlIG5vbmNlIG9mIHRoZSBjb250cmFjdCBhZGRyZXNzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB0aGUgY2FsY3VsYXRlZCBmb3J3YXJkZXIgY29udHJhY3QgYWRkcmVzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlRm9yd2FyZGVyQWRkcmVzcyhjb250cmFjdEFkZHJlc3M6IHN0cmluZywgY29udHJhY3RDb3VudGVyOiBudW1iZXIpOiBzdHJpbmcge1xuICBjb25zdCBmb3J3YXJkZXJBZGRyZXNzID0gZ2VuZXJhdGVBZGRyZXNzKFxuICAgIEJ1ZmZlci5mcm9tKHN0cmlwSGV4UHJlZml4KGNvbnRyYWN0QWRkcmVzcyksICdoZXgnKSxcbiAgICBCdWZmZXIuZnJvbShwYWRUb0V2ZW4oc3RyaXBIZXhQcmVmaXgobnVtYmVyVG9IZXhTdHJpbmcoY29udHJhY3RDb3VudGVyKSkpLCAnaGV4JylcbiAgKTtcbiAgcmV0dXJuIGFkZEhleFByZWZpeChmb3J3YXJkZXJBZGRyZXNzLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSBmb3J3YXJkZXIgdjEgYWRkcmVzcyB0aGF0IHdpbGwgYmUgZ2VuZXJhdGVkIGlmIGBjcmVhdG9yQWRkcmVzc2AgY3JlYXRlcyBpdCB3aXRoIHNhbHQgYHNhbHRgXG4gKiBhbmQgaW5pdGNvZGUgYGluaWNvZGUgdXNpbmcgdGhlIGNyZWF0ZTIgb3Bjb2RlXG4gKiBAcGFyYW0ge3N0cmluZ30gY3JlYXRvckFkZHJlc3MgVGhlIGFkZHJlc3MgdGhhdCBpcyBzZW5kaW5nIHRoZSB0eCB0byBjcmVhdGUgYSBuZXcgYWRkcmVzcywgaGV4IHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHNhbHQgVGhlIHNhbHQgdG8gY3JlYXRlIHRoZSBhZGRyZXNzIHdpdGggdXNpbmcgY3JlYXRlMiwgaGV4IHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IGluaXRjb2RlIFRoZSBpbml0Y29kZSB0aGF0IHdpbGwgYmUgZGVwbG95ZWQgdG8gdGhlIGFkZHJlc3MsIGhleCBzdHJpbmdcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGNhbGN1bGF0ZWQgYWRkcmVzc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlRm9yd2FyZGVyVjFBZGRyZXNzKGNyZWF0b3JBZGRyZXNzOiBzdHJpbmcsIHNhbHQ6IHN0cmluZywgaW5pdGNvZGU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGZvcndhcmRlclYxQWRkcmVzcyA9IGdlbmVyYXRlQWRkcmVzczIoXG4gICAgQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoY3JlYXRvckFkZHJlc3MpLCAnaGV4JyksXG4gICAgQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoc2FsdCksICdoZXgnKSxcbiAgICBCdWZmZXIuZnJvbShwYWRUb0V2ZW4oc3RyaXBIZXhQcmVmaXgoaW5pdGNvZGUpKSwgJ2hleCcpXG4gICk7XG4gIHJldHVybiBhZGRIZXhQcmVmaXgoZm9yd2FyZGVyVjFBZGRyZXNzLnRvU3RyaW5nKCdoZXgnKSk7XG59XG5cbi8qKlxuICogVGFrZSB0aGUgaW1wbGVtZW50YXRpb24gYWRkcmVzcyBmb3IgdGhlIHByb3h5IGNvbnRyYWN0LCBhbmQgZ2V0IHRoZSBiaW5hcnkgaW5pdGNvZGUgZm9yIHRoZSBhc3NvY2lhdGVkIHByb3h5XG4gKiBAcGFyYW0ge3N0cmluZ30gaW1wbGVtZW50YXRpb25BZGRyZXNzIFRoZSBhZGRyZXNzIG9mIHRoZSBpbXBsZW1lbnRhdGlvbiBjb250cmFjdCBmb3IgdGhlIHByb3h5XG4gKiBAcmV0dXJuIHtzdHJpbmd9IEJpbmFyeSBoZXggc3RyaW5nIG9mIHRoZSBwcm94eVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJveHlJbml0Y29kZShpbXBsZW1lbnRhdGlvbkFkZHJlc3M6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHRhcmdldCA9IHN0cmlwSGV4UHJlZml4KGltcGxlbWVudGF0aW9uQWRkcmVzcy50b0xvd2VyQ2FzZSgpKS5wYWRTdGFydCg0MCwgJzAnKTtcblxuICAvLyBieXRlY29kZSBvZiB0aGUgcHJveHksIGZyb206XG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9CaXRHby9ldGgtbXVsdGlzaWctdjQvYmxvYi9kNTQ2YTkzN2Y5MGY5M2U4M2IzNDIzYTViZjkzM2QxZDc3YzY3N2MzL2NvbnRyYWN0cy9DbG9uZUZhY3Rvcnkuc29sI0w0Mi1MNTZcbiAgcmV0dXJuIGAweDNkNjAyZDgwNjAwYTNkMzk4MWYzMzYzZDNkMzczZDNkM2QzNjNkNzMke3RhcmdldH01YWY0M2Q4MjgwM2U5MDNkOTE2MDJiNTdmZDViZjNgO1xufVxuXG4vKipcbiAqIENvbnZlcnQgdGhlIGdpdmVuIHNpZ25hdHVyZSBwYXJ0cyB0byBhIHN0cmluZyByZXByZXNlbnRhdGlvblxuICpcbiAqIEBwYXJhbSB7U2lnbmF0dXJlUGFydHN9IHNpZyBUaGUgc2lnbmF0dXJlIHRvIGNvbnZlcnQgdG8gc3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHNpZ25hdHVyZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TdHJpbmdTaWcoc2lnOiBTaWduYXR1cmVQYXJ0cyk6IHN0cmluZyB7XG4gIHJldHVybiBidWZmZXJUb0hleChcbiAgICBCdWZmZXIuY29uY2F0KFtcbiAgICAgIHNldExlbmd0aExlZnQoQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoc2lnLnIpLCAnaGV4JyksIDMyKSxcbiAgICAgIHNldExlbmd0aExlZnQoQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgoc2lnLnMpLCAnaGV4JyksIDMyKSxcbiAgICAgIHRvQnVmZmVyKHNpZy52KSxcbiAgICBdKVxuICApO1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIG9yIG5vdCB0aGUgZ2l2ZW4gdHggZGF0YSBoYXMgYSBzaWduYXR1cmVcbiAqXG4gKiBAcGFyYW0ge1R4RGF0YX0gdHhEYXRhIFRoZSB0cmFuc2FjdGlvbiBkYXRhIHRvIGNoZWNrIGZvciBzaWduYXR1cmVcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSB0eCBoYXMgYSBzaWduYXR1cmUsIGVsc2UgZmFsc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1NpZ25hdHVyZSh0eERhdGE6IFR4RGF0YSk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIHR4RGF0YS52ICE9PSB1bmRlZmluZWQgJiZcbiAgICB0eERhdGEuciAhPT0gdW5kZWZpbmVkICYmXG4gICAgdHhEYXRhLnMgIT09IHVuZGVmaW5lZCAmJlxuICAgIHR4RGF0YS52Lmxlbmd0aCA+IDAgJiZcbiAgICB0eERhdGEuci5sZW5ndGggPiAwICYmXG4gICAgdHhEYXRhLnMubGVuZ3RoID4gMFxuICApO1xufVxuXG50eXBlIFJlY3Vyc2l2ZUJ1ZmZlck9yU3RyaW5nID0gc3RyaW5nIHwgQnVmZmVyIHwgQk4gfCBSZWN1cnNpdmVCdWZmZXJPclN0cmluZ1tdO1xuXG4vKipcbiAqIEdldCB0aGUgcmF3IGRhdGEgZGVjb2RlZCBmb3Igc29tZSB0eXBlc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nW119IHR5cGVzIEFCSSB0eXBlcyBkZWZpbml0aW9uXG4gKiBAcGFyYW0ge0J1ZmZlcn0gc2VyaWFsaXplZEFyZ3MgZW5jb2RlZCBhcmdzXG4gKiBAcmV0dXJucyB7QnVmZmVyW119IHRoZSBkZWNvZGVkIHJhd1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UmF3RGVjb2RlZCh0eXBlczogc3RyaW5nW10sIHNlcmlhbGl6ZWRBcmdzOiBCdWZmZXIpOiBSZWN1cnNpdmVCdWZmZXJPclN0cmluZ1tdIHtcbiAgZnVuY3Rpb24gbm9ybWFsaXplKHY6IHVua25vd24sIGk6IG51bWJlcik6IHVua25vd24ge1xuICAgIGlmIChCTi5pc0JOKHYpKSB7XG4gICAgICByZXR1cm4gdjtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2ID09PSAnc3RyaW5nJyB8fCBCdWZmZXIuaXNCdWZmZXIodikpIHtcbiAgICAgIHJldHVybiB2O1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2KSkge1xuICAgICAgcmV0dXJuIHYubWFwKG5vcm1hbGl6ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm9yICR7dHlwZXN9WyR7aX1dIGdvdCAke3R5cGVvZiB2fWApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBFdGhlcmV1bUFiaS5yYXdEZWNvZGUodHlwZXMsIHNlcmlhbGl6ZWRBcmdzKS5tYXAobm9ybWFsaXplKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGJ1ZmZlcmVkIGJ5dGVjb2RlIGZyb20gcmF3RGF0YSB1c2luZyBhIG1ldGhvZElkIGFzIGRlbGltaXRlclxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RJZCB0aGUgaGV4IGVuY29kZWQgbWV0aG9kIElkXG4gKiBAcGFyYW0ge3N0cmluZ30gcmF3RGF0YSB0aGUgaGV4IGVuY29kZWQgcmF3IGRhdGFcbiAqIEByZXR1cm5zIHtCdWZmZXJ9IGRhdGEgYnVmZmVyZWQgYnl0ZWNvZGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEJ1ZmZlcmVkQnl0ZUNvZGUobWV0aG9kSWQ6IHN0cmluZywgcmF3RGF0YTogc3RyaW5nKTogQnVmZmVyIHtcbiAgY29uc3Qgc3BsaXRCeXRlY29kZSA9IHJhd0RhdGEuc3BsaXQobWV0aG9kSWQpO1xuICBpZiAoc3BsaXRCeXRlY29kZS5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKGBJbnZhbGlkIHNlbmQgYnl0ZWNvZGU6ICR7cmF3RGF0YX1gKTtcbiAgfVxuICBpZiAoc3BsaXRCeXRlY29kZVsxXS5sZW5ndGggJSAyICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcihgSW52YWxpZCBzZW5kIGJ5dGVjb2RlOiAke3Jhd0RhdGF9ICh3cm9uZyBsZW5naHQpYCk7XG4gIH1cbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKHNwbGl0Qnl0ZWNvZGVbMV0sICdoZXgnKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHN0YXRpY3MgY29pbiBvYmplY3QgbWF0Y2hpbmcgYSBnaXZlbiBjb250cmFjdCBhZGRyZXNzIGlmIGl0IGV4aXN0c1xuICpcbiAqIEBwYXJhbSB0b2tlbkNvbnRyYWN0QWRkcmVzcyBUaGUgY29udHJhY3QgYWRkcmVzcyB0byBtYXRjaCBhZ2FpbnN0XG4gKiBAcGFyYW0gbmV0d29yayAtIHRoZSBjb2luIG5ldHdvcmtcbiAqIEBwYXJhbSBmYW1pbHkgLSB0aGUgY29pbiBmYW1pbHlcbiAqIEByZXR1cm5zIHN0YXRpY3MgQmFzZUNvaW4gb2JqZWN0IGZvciB0aGUgbWF0Y2hpbmcgdG9rZW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRva2VuKFxuICB0b2tlbkNvbnRyYWN0QWRkcmVzczogc3RyaW5nLFxuICBuZXR3b3JrOiBCYXNlTmV0d29yayxcbiAgZmFtaWx5OiBzdHJpbmdcbik6IFJlYWRvbmx5PEJhc2VDb2luPiB8IHVuZGVmaW5lZCB7XG4gIC8vIGZpbHRlciB0aGUgY29pbnMgYXJyYXkgdG8gZmluZCB0aGUgdG9rZW4gd2l0aCB0aGUgbWF0Y2hpbmcgY29udHJhY3QgYWRkcmVzcywgbmV0d29yayBhbmQgY29pbiBmYW1pbHlcbiAgLy8gY29pbiBmYW1pbHkgaXMgbmVlZGVkIHRvIGF2b2lkIGNhdXNpbmcgaXNzdWVzIHdoZW4gYSB0b2tlbiBoYXMgc2FtZSBjb250cmFjdCBhZGRyZXNzIG9uIHR3byBkaWZmZXJlbnQgY2hhaW5zXG4gIGNvbnN0IHRva2VucyA9IGNvaW5zLmZpbHRlcigoY29pbikgPT4ge1xuICAgIGlmIChjb2luIGluc3RhbmNlb2YgQ29udHJhY3RBZGRyZXNzRGVmaW5lZFRva2VuKSB7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBjb2luLm5ldHdvcmsudHlwZSA9PT0gbmV0d29yay50eXBlICYmXG4gICAgICAgIGNvaW4uZmFtaWx5ID09PSBmYW1pbHkgJiZcbiAgICAgICAgY29pbi5jb250cmFjdEFkZHJlc3MudG9Mb3dlckNhc2UoKSA9PT0gdG9rZW5Db250cmFjdEFkZHJlc3MudG9Mb3dlckNhc2UoKVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KTtcblxuICAvLyBpZiBsZW5ndGggb2YgdG9rZW5zIGlzIDEsIHJldHVybiB0aGUgZmlyc3QsIGVsc2UgcmV0dXJuIHVuZGVmaW5lZFxuICAvLyBDYW4ndCBkaXJlY3RseSBpbmRleCBpbnRvIHRva2Vucywgb3IgY2FsbCBgbGVuZ3RoYCwgc28gd2UgdXNlIG1hcCB0byBnZXQgYW4gYXJyYXlcbiAgY29uc3QgdG9rZW5zQXJyYXkgPSB0b2tlbnMubWFwKCh0b2tlbikgPT4gdG9rZW4pO1xuICBpZiAodG9rZW5zQXJyYXkubGVuZ3RoID49IDEpIHtcbiAgICAvLyB0aGVyZSBzaG91bGQgbmV2ZXIgYmUgdHdvIHRva2VucyB3aXRoIHRoZSBzYW1lIGNvbnRyYWN0IGFkZHJlc3MsIHNvIHdlIGFzc2VydCB0aGF0IGhlcmVcbiAgICBhc3NlcnQodG9rZW5zQXJyYXkubGVuZ3RoID09PSAxKTtcbiAgICByZXR1cm4gdG9rZW5zQXJyYXlbMF07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjcmVhdGUgd2FsbGV0IG1ldGhvZCBjYWxsaW5nIGRhdGEgZm9yIHYxIHdhbGxldHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSB3YWxsZXRPd25lcnMgLSB3YWxsZXQgb3duZXIgYWRkcmVzc2VzIGZvciB3YWxsZXQgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25zXG4gKiBAcGFyYW0ge3N0cmluZ30gc2FsdCAtIFRoZSBzYWx0IGZvciB3YWxsZXQgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25zXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIHRoZSBjcmVhdGVXYWxsZXQgbWV0aG9kIGVuY29kZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFYxV2FsbGV0SW5pdGlhbGl6YXRpb25EYXRhKHdhbGxldE93bmVyczogc3RyaW5nW10sIHNhbHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHNhbHRCdWZmZXIgPSBzZXRMZW5ndGhMZWZ0KHRvQnVmZmVyKHNhbHQpLCAzMik7XG4gIGNvbnN0IHBhcmFtcyA9IFt3YWxsZXRPd25lcnMsIHNhbHRCdWZmZXJdO1xuICBjb25zdCBtZXRob2QgPSBFdGhlcmV1bUFiaS5tZXRob2RJRCgnY3JlYXRlV2FsbGV0JywgY3JlYXRlVjFXYWxsZXRUeXBlcyk7XG4gIGNvbnN0IGFyZ3MgPSBFdGhlcmV1bUFiaS5yYXdFbmNvZGUoY3JlYXRlVjFXYWxsZXRUeXBlcywgcGFyYW1zKTtcbiAgcmV0dXJuIGFkZEhleFByZWZpeChCdWZmZXIuY29uY2F0KFttZXRob2QsIGFyZ3NdKS50b1N0cmluZygnaGV4JykpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGNyZWF0ZSBhZGRyZXNzIG1ldGhvZCBjYWxsaW5nIGRhdGEgZm9yIHYxLCB2MiwgdjQgZm9yd2FyZGVyc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlQWRkcmVzcyAtIFRoZSBhZGRyZXNzIG9mIHRoZSB3YWxsZXQgY29udHJhY3RcbiAqIEBwYXJhbSB7c3RyaW5nfSBzYWx0IC0gVGhlIHNhbHQgZm9yIGFkZHJlc3MgaW5pdGlhbGl6YXRpb24gdHJhbnNhY3Rpb25zXG4gKiBAcGFyYW0ge3N0cmluZ30gZmVlQWRkcmVzcyAtIFRoZSBmZWUgYWRkcmVzcyBmb3IgdGhlIGVudGVycHJpc2VcbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gdGhlIGNyZWF0ZUZvcndhcmRlciBtZXRob2QgZW5jb2RlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VjFBZGRyZXNzSW5pdGlhbGl6YXRpb25EYXRhKGJhc2VBZGRyZXNzOiBzdHJpbmcsIHNhbHQ6IHN0cmluZywgZmVlQWRkcmVzcz86IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHNhbHRCdWZmZXIgPSBzZXRMZW5ndGhMZWZ0KHRvQnVmZmVyKHNhbHQpLCAzMik7XG4gIGNvbnN0IHsgY3JlYXRlRm9yd2FyZGVyUGFyYW1zLCBjcmVhdGVGb3J3YXJkZXJUeXBlcyB9ID0gZ2V0Q3JlYXRlRm9yd2FyZGVyUGFyYW1zQW5kVHlwZXMoXG4gICAgYmFzZUFkZHJlc3MsXG4gICAgc2FsdEJ1ZmZlcixcbiAgICBmZWVBZGRyZXNzXG4gICk7XG5cbiAgY29uc3QgbWV0aG9kID0gRXRoZXJldW1BYmkubWV0aG9kSUQoJ2NyZWF0ZUZvcndhcmRlcicsIGNyZWF0ZUZvcndhcmRlclR5cGVzKTtcbiAgY29uc3QgYXJncyA9IEV0aGVyZXVtQWJpLnJhd0VuY29kZShjcmVhdGVGb3J3YXJkZXJUeXBlcywgY3JlYXRlRm9yd2FyZGVyUGFyYW1zKTtcbiAgcmV0dXJuIGFkZEhleFByZWZpeChCdWZmZXIuY29uY2F0KFttZXRob2QsIGFyZ3NdKS50b1N0cmluZygnaGV4JykpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGNyZWF0ZSBhZGRyZXNzIG1ldGhvZCBjYWxsaW5nIGRhdGEgZm9yIGFsbCBmb3J3YXJkZXIgdmVyc2lvbnNcbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gZm9yd2FyZGVyVmVyc2lvbiAtIFRoZSB2ZXJzaW9uIG9mIHRoZSBmb3J3YXJkZXIgdG8gY3JlYXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gYmFzZUFkZHJlc3MgLSBUaGUgYWRkcmVzcyBvZiB0aGUgd2FsbGV0IGNvbnRyYWN0XG4gKiBAcGFyYW0ge3N0cmluZ30gc2FsdCAtIFRoZSBzYWx0IGZvciBhZGRyZXNzIGluaXRpYWxpemF0aW9uIHRyYW5zYWN0aW9uc1xuICogQHBhcmFtIHtzdHJpbmd9IGZlZUFkZHJlc3MgLSBUaGUgZmVlIGFkZHJlc3MgZm9yIHRoZSBlbnRlcnByaXNlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIHRoZSBjcmVhdGVGb3J3YXJkZXIgbWV0aG9kIGVuY29kZWRcbiAqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBZGRyZXNzSW5pdERhdGFBbGxGb3J3YXJkZXJWZXJzaW9ucyhcbiAgZm9yd2FyZGVyVmVyc2lvbjogbnVtYmVyLFxuICBiYXNlQWRkcmVzczogc3RyaW5nLFxuICBzYWx0OiBzdHJpbmcsXG4gIGZlZUFkZHJlc3M/OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGlmIChmb3J3YXJkZXJWZXJzaW9uID09PSBkZWZhdWx0Rm9yd2FyZGVyVmVyc2lvbikge1xuICAgIHJldHVybiBnZXRBZGRyZXNzSW5pdGlhbGl6YXRpb25EYXRhKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGdldFYxQWRkcmVzc0luaXRpYWxpemF0aW9uRGF0YShiYXNlQWRkcmVzcywgc2FsdCwgZmVlQWRkcmVzcyk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjcmVhdGVGb3J3YXJkZXJUeXBlcyBhbmQgY3JlYXRlRm9yd2FyZGVyUGFyYW1zIGZvciBhbGwgZm9yd2FyZGVyIHZlcnNpb25zXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2VBZGRyZXNzIC0gVGhlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldCBjb250cmFjdFxuICogQHBhcmFtIHtCdWZmZXJ9IHNhbHRCdWZmZXIgLSBUaGUgc2FsdCBmb3IgYWRkcmVzcyBpbml0aWFsaXphdGlvbiB0cmFuc2FjdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IGZlZUFkZHJlc3MgLSBUaGUgZmVlIGFkZHJlc3MgZm9yIHRoZSBlbnRlcnByaXNlXG4gKiBAcmV0dXJucyB7Y3JlYXRlRm9yd2FyZGVyUGFyYW1zOiAoc3RyaW5nIHwgQnVmZmVyKVtdLCBjcmVhdGVGb3J3YXJkZXJUeXBlczogc3RyaW5nW119XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRDcmVhdGVGb3J3YXJkZXJQYXJhbXNBbmRUeXBlcyhcbiAgYmFzZUFkZHJlc3M6IHN0cmluZyxcbiAgc2FsdEJ1ZmZlcjogQnVmZmVyLFxuICBmZWVBZGRyZXNzPzogc3RyaW5nXG4pOiB7IGNyZWF0ZUZvcndhcmRlclBhcmFtczogKHN0cmluZyB8IEJ1ZmZlcilbXTsgY3JlYXRlRm9yd2FyZGVyVHlwZXM6IHN0cmluZ1tdIH0ge1xuICBsZXQgY3JlYXRlRm9yd2FyZGVyUGFyYW1zID0gW2Jhc2VBZGRyZXNzLCBzYWx0QnVmZmVyXTtcbiAgbGV0IGNyZWF0ZUZvcndhcmRlclR5cGVzID0gY3JlYXRlVjFGb3J3YXJkZXJUeXBlcztcbiAgaWYgKGZlZUFkZHJlc3MpIHtcbiAgICBjcmVhdGVGb3J3YXJkZXJQYXJhbXMgPSBbYmFzZUFkZHJlc3MsIGZlZUFkZHJlc3MsIHNhbHRCdWZmZXJdO1xuICAgIGNyZWF0ZUZvcndhcmRlclR5cGVzID0gY3JlYXRlVjRGb3J3YXJkZXJUeXBlcztcbiAgfVxuICByZXR1cm4geyBjcmVhdGVGb3J3YXJkZXJQYXJhbXMsIGNyZWF0ZUZvcndhcmRlclR5cGVzIH07XG59XG5cbi8qKlxuICogRGVjb2RlIHRoZSBnaXZlbiBBQkktZW5jb2RlZCBjcmVhdGUgZm9yd2FyZGVyIGRhdGEgYW5kIHJldHVybiBwYXJzZWQgZmllbGRzXG4gKlxuICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyBwYXJzZWQgdHJhbnNmZXIgZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlRm9yd2FyZGVyQ3JlYXRpb25EYXRhKGRhdGE6IHN0cmluZyk6IEZvcndhcmRlckluaXRpYWxpemF0aW9uRGF0YSB7XG4gIGlmIChcbiAgICAhKFxuICAgICAgZGF0YS5zdGFydHNXaXRoKHY0Q3JlYXRlRm9yd2FyZGVyTWV0aG9kSWQpIHx8XG4gICAgICBkYXRhLnN0YXJ0c1dpdGgodjFDcmVhdGVGb3J3YXJkZXJNZXRob2RJZCkgfHxcbiAgICAgIGRhdGEuc3RhcnRzV2l0aChjcmVhdGVGb3J3YXJkZXJNZXRob2RJZClcbiAgICApXG4gICkge1xuICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoYEludmFsaWQgYWRkcmVzcyBieXRlY29kZTogJHtkYXRhfWApO1xuICB9XG5cbiAgaWYgKGRhdGEuc3RhcnRzV2l0aChjcmVhdGVGb3J3YXJkZXJNZXRob2RJZCkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYmFzZUFkZHJlc3M6IHVuZGVmaW5lZCxcbiAgICAgIGFkZHJlc3NDcmVhdGlvblNhbHQ6IHVuZGVmaW5lZCxcbiAgICAgIGZlZUFkZHJlc3M6IHVuZGVmaW5lZCxcbiAgICB9O1xuICB9IGVsc2UgaWYgKGRhdGEuc3RhcnRzV2l0aCh2MUNyZWF0ZUZvcndhcmRlck1ldGhvZElkKSkge1xuICAgIGNvbnN0IFtiYXNlQWRkcmVzcywgc2FsdEJ1ZmZlcl0gPSBnZXRSYXdEZWNvZGVkKFxuICAgICAgY3JlYXRlVjFGb3J3YXJkZXJUeXBlcyxcbiAgICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUodjFDcmVhdGVGb3J3YXJkZXJNZXRob2RJZCwgZGF0YSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJhc2VBZGRyZXNzOiBhZGRIZXhQcmVmaXgoYmFzZUFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgICAgIGFkZHJlc3NDcmVhdGlvblNhbHQ6IGJ1ZmZlclRvSGV4KHNhbHRCdWZmZXIgYXMgQnVmZmVyKSxcbiAgICAgIGZlZUFkZHJlc3M6IHVuZGVmaW5lZCxcbiAgICB9IGFzIGNvbnN0O1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IFtiYXNlQWRkcmVzcywgZmVlQWRkcmVzcywgc2FsdEJ1ZmZlcl0gPSBnZXRSYXdEZWNvZGVkKFxuICAgICAgY3JlYXRlVjRGb3J3YXJkZXJUeXBlcyxcbiAgICAgIGdldEJ1ZmZlcmVkQnl0ZUNvZGUodjRDcmVhdGVGb3J3YXJkZXJNZXRob2RJZCwgZGF0YSlcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJhc2VBZGRyZXNzOiBhZGRIZXhQcmVmaXgoYmFzZUFkZHJlc3MgYXMgc3RyaW5nKSxcbiAgICAgIGFkZHJlc3NDcmVhdGlvblNhbHQ6IGJ1ZmZlclRvSGV4KHNhbHRCdWZmZXIgYXMgQnVmZmVyKSxcbiAgICAgIGZlZUFkZHJlc3M6IGFkZEhleFByZWZpeChmZWVBZGRyZXNzIGFzIHN0cmluZyksXG4gICAgfSBhcyBjb25zdDtcbiAgfVxufVxuXG4vKipcbiAqIE1ha2UgYSBxdWVyeSB0byBleHBsb3JlciBmb3IgaW5mb3JtYXRpb24gc3VjaCBhcyBiYWxhbmNlLCB0b2tlbiBiYWxhbmNlLCBzb2xpZGl0eSBjYWxsc1xuICogQHBhcmFtIHtPYmplY3R9IHF1ZXJ5IGtleS12YWx1ZSBwYWlycyBvZiBwYXJhbWV0ZXJzIHRvIGFwcGVuZCBhZnRlciAvYXBpXG4gKiBAcGFyYW0ge3N0cmluZ30gdG9rZW4gdGhlIEFQSSB0b2tlbiB0byB1c2UgZm9yIHRoZSByZXF1ZXN0XG4gKiBAcGFyYW0ge3N0cmluZ30gZXhwbG9yZXJVcmwgdGhlIFVSTCBvZiB0aGUgZXhwbG9yZXJcbiAqIEByZXR1cm5zIHtQcm9taXNlPE9iamVjdD59IHJlc3BvbnNlIGZyb20gZXhwbG9yZXJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnkoXG4gIHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICBleHBsb3JlclVybDogc3RyaW5nLFxuICB0b2tlbj86IHN0cmluZ1xuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICBpZiAodG9rZW4pIHtcbiAgICBxdWVyeS5hcGlrZXkgPSB0b2tlbjtcbiAgfVxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3QuZ2V0KGAke2V4cGxvcmVyVXJsfS9hcGlgKS5xdWVyeShxdWVyeSk7XG5cbiAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWNoIGV4cGxvcmVyJyk7XG4gIH1cblxuICBpZiAocmVzcG9uc2UuYm9keS5zdGF0dXMgPT09ICcwJyAmJiByZXNwb25zZS5ib2R5Lm1lc3NhZ2UgPT09ICdOT1RPSycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGxvcmVyIHJhdGUgbGltaXQgcmVhY2hlZCcpO1xuICB9XG4gIHJldHVybiByZXNwb25zZS5ib2R5O1xufVxuXG4vKipcbiAqIERlZmF1bHQgZXhwaXJlIHRpbWUgZm9yIGEgY29udHJhY3QgY2FsbCAoMSB3ZWVrKVxuICogQHJldHVybnMge251bWJlcn0gVGltZSBpbiBzZWNvbmRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREZWZhdWx0RXhwaXJlVGltZSgpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5mbG9vcihuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApICsgNjAgKiA2MCAqIDI0ICogNztcbn1cbiJdfQ==