@bitgo-beta/abstract-eth 1.2.3-alpha.400 → 1.2.3-alpha.402

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