@bitgo-beta/sdk-coin-tempo 1.0.1-beta.31 → 1.0.1-beta.310

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 (51) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +2 -1
  4. package/dist/src/lib/constants.d.ts +21 -1
  5. package/dist/src/lib/constants.d.ts.map +1 -1
  6. package/dist/src/lib/constants.js +25 -5
  7. package/dist/src/lib/index.d.ts +4 -0
  8. package/dist/src/lib/index.d.ts.map +1 -1
  9. package/dist/src/lib/index.js +5 -1
  10. package/dist/src/lib/keyPair.d.ts +5 -25
  11. package/dist/src/lib/keyPair.d.ts.map +1 -1
  12. package/dist/src/lib/keyPair.js +9 -97
  13. package/dist/src/lib/tip20Abi.d.ts +98 -0
  14. package/dist/src/lib/tip20Abi.d.ts.map +1 -0
  15. package/dist/src/lib/tip20Abi.js +62 -0
  16. package/dist/src/lib/transaction.d.ts +144 -0
  17. package/dist/src/lib/transaction.d.ts.map +1 -0
  18. package/dist/src/lib/transaction.js +216 -0
  19. package/dist/src/lib/transactionBuilder.d.ts +139 -0
  20. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  21. package/dist/src/lib/transactionBuilder.js +408 -0
  22. package/dist/src/lib/types.d.ts +27 -0
  23. package/dist/src/lib/types.d.ts.map +1 -0
  24. package/dist/src/lib/types.js +3 -0
  25. package/dist/src/lib/utils.d.ts +70 -7
  26. package/dist/src/lib/utils.d.ts.map +1 -1
  27. package/dist/src/lib/utils.js +148 -16
  28. package/dist/src/register.d.ts.map +1 -1
  29. package/dist/src/register.js +5 -1
  30. package/dist/src/tempo.d.ts +95 -41
  31. package/dist/src/tempo.d.ts.map +1 -1
  32. package/dist/src/tempo.js +447 -76
  33. package/dist/src/tip20Token.d.ts +83 -0
  34. package/dist/src/tip20Token.d.ts.map +1 -0
  35. package/dist/src/tip20Token.js +202 -0
  36. package/dist/test/integration/tip20.d.ts +7 -0
  37. package/dist/test/integration/tip20.d.ts.map +1 -0
  38. package/dist/test/integration/tip20.js +178 -0
  39. package/dist/test/resources/tempo.d.ts +61 -0
  40. package/dist/test/resources/tempo.d.ts.map +1 -0
  41. package/dist/test/resources/tempo.js +79 -0
  42. package/dist/test/unit/index.js +172 -3
  43. package/dist/test/unit/tempo.d.ts +2 -0
  44. package/dist/test/unit/tempo.d.ts.map +1 -0
  45. package/dist/test/unit/tempo.js +207 -0
  46. package/dist/test/unit/transactionBuilder.d.ts +2 -0
  47. package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
  48. package/dist/test/unit/transactionBuilder.js +858 -0
  49. package/dist/test/unit/utils.js +6 -5
  50. package/dist/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +12 -7
package/dist/src/tempo.js CHANGED
@@ -1,130 +1,501 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
5
35
  Object.defineProperty(exports, "__esModule", { value: true });
6
36
  exports.Tempo = void 0;
37
+ /**
38
+ * @prettier
39
+ */
40
+ const abstract_eth_1 = require("@bitgo-beta/abstract-eth");
7
41
  const sdk_core_1 = require("@bitgo-beta/sdk-core");
8
- const keyPair_1 = require("./lib/keyPair");
9
- const utils_1 = __importDefault(require("./lib/utils"));
10
- class Tempo extends sdk_core_1.BaseCoin {
42
+ const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
43
+ const statics_1 = require("@bitgo-beta/statics");
44
+ const ethers_1 = require("ethers");
45
+ const lib_1 = require("./lib");
46
+ const utils_1 = require("./lib/utils");
47
+ const constants_1 = require("./lib/constants");
48
+ const url = __importStar(require("url"));
49
+ const querystring = __importStar(require("querystring"));
50
+ class Tempo extends abstract_eth_1.AbstractEthLikeNewCoins {
11
51
  constructor(bitgo, staticsCoin) {
12
- super(bitgo);
13
- if (!staticsCoin) {
14
- throw new Error('missing required constructor parameter staticsCoin');
15
- }
16
- this._staticsCoin = staticsCoin;
52
+ super(bitgo, staticsCoin);
17
53
  }
54
+ /**
55
+ * Factory method to create Tempo instance
56
+ */
18
57
  static createInstance(bitgo, staticsCoin) {
19
58
  return new Tempo(bitgo, staticsCoin);
20
59
  }
21
60
  /**
22
- * Factor between the coin's base unit and its smallest subdivision
61
+ * Get the chain identifier
23
62
  */
24
- getBaseFactor() {
25
- return 1e18;
26
- }
27
63
  getChain() {
28
- return 'tempo';
29
- }
30
- getFamily() {
31
- return 'tempo';
64
+ return this._staticsCoin?.name || 'tempo';
32
65
  }
66
+ /**
67
+ * Get the full chain name
68
+ */
33
69
  getFullName() {
34
70
  return 'Tempo';
35
71
  }
72
+ /** @inheritdoc */
73
+ getBaseFactor() {
74
+ return 1e6;
75
+ }
36
76
  /**
37
- * Flag for sending value of 0
38
- * @returns {boolean} True if okay to send 0 value, false otherwise
77
+ * Check if value-less transfers are allowed
78
+ * EVM-based chains allow zero-value transfers for smart contract interactions
39
79
  */
40
80
  valuelessTransferAllowed() {
41
- return false;
81
+ return true;
82
+ }
83
+ /**
84
+ * Check if TSS is supported
85
+ */
86
+ supportsTss() {
87
+ return true;
42
88
  }
43
89
  /**
44
- * Checks if this is a valid base58 or hex address
45
- * @param address
90
+ * Get the MPC algorithm (ECDSA for EVM chains)
91
+ */
92
+ getMPCAlgorithm() {
93
+ return 'ecdsa';
94
+ }
95
+ /**
96
+ * Evaluates whether an address string is valid for Tempo
97
+ * Supports addresses with optional memoId query parameter (e.g., 0x...?memoId=123)
98
+ * @param address - The address to validate
99
+ * @returns true if address is valid
46
100
  */
47
101
  isValidAddress(address) {
48
- return utils_1.default.isValidAddress(address);
102
+ if (typeof address !== 'string') {
103
+ return false;
104
+ }
105
+ try {
106
+ const { baseAddress } = this.getAddressDetails(address);
107
+ return abstract_eth_1.optionalDeps.ethUtil.isValidAddress(abstract_eth_1.optionalDeps.ethUtil.addHexPrefix(baseAddress));
108
+ }
109
+ catch (e) {
110
+ return false;
111
+ }
49
112
  }
50
113
  /**
51
- * Generate ed25519 key pair
52
- *
53
- * @param seed
54
- * @returns {Object} object with generated pub, prv
114
+ * Parse address into base address and optional memoId
115
+ * Throws InvalidAddressError for invalid address formats
116
+ * @param address - Address string, potentially with ?memoId=X suffix
117
+ * @returns Object containing address, baseAddress, and memoId (null if not present)
118
+ * @throws InvalidAddressError if address format is invalid
55
119
  */
56
- generateKeyPair(seed) {
57
- const keyPair = seed ? new keyPair_1.KeyPair({ seed }) : new keyPair_1.KeyPair();
58
- const keys = keyPair.getKeys();
59
- if (!keys.prv) {
60
- throw new Error('Missing prv in key generation.');
120
+ getAddressDetails(address) {
121
+ if (typeof address !== 'string') {
122
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
123
+ }
124
+ const destinationDetails = url.parse(address);
125
+ const baseAddress = destinationDetails.pathname || '';
126
+ // No query string - just a plain address
127
+ if (destinationDetails.pathname === address) {
128
+ return {
129
+ address,
130
+ baseAddress: address,
131
+ memoId: null,
132
+ };
133
+ }
134
+ // Has query string - must contain memoId
135
+ if (!destinationDetails.query) {
136
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
137
+ }
138
+ const queryDetails = querystring.parse(destinationDetails.query);
139
+ // Query string must contain memoId
140
+ if (!queryDetails.memoId) {
141
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}, unknown query parameters`);
142
+ }
143
+ // Only one memoId allowed
144
+ if (Array.isArray(queryDetails.memoId)) {
145
+ throw new sdk_core_1.InvalidAddressError(`memoId may only be given at most once, but found ${queryDetails.memoId.length} instances in address ${address}`);
146
+ }
147
+ // Reject if there are other query parameters besides memoId
148
+ const queryKeys = Object.keys(queryDetails);
149
+ if (queryKeys.length !== 1) {
150
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}, only memoId query parameter is allowed`);
151
+ }
152
+ // Validate memoId format
153
+ if (!this.isValidMemoId(queryDetails.memoId)) {
154
+ throw new sdk_core_1.InvalidMemoIdError(`invalid address: '${address}', memoId is not valid`);
61
155
  }
62
156
  return {
63
- pub: keys.pub,
64
- prv: keys.prv,
157
+ address,
158
+ baseAddress,
159
+ memoId: queryDetails.memoId,
65
160
  };
66
161
  }
67
162
  /**
68
- * Return boolean indicating whether input is valid public key for the coin.
69
- *
70
- * @param {String} pub the pub to be checked
71
- * @returns {Boolean} is it valid?
163
+ * Validate that a memoId is a valid non-negative integer string
164
+ * @param memoId - The memoId to validate
165
+ * @returns true if valid
166
+ */
167
+ isValidMemoId(memoId) {
168
+ return (0, utils_1.isValidMemoId)(memoId);
169
+ }
170
+ /**
171
+ * Tempo uses memoId-based addresses rather than forwarder contracts.
172
+ * Verify that the address belongs to this wallet by checking that the
173
+ * base (EVM) portion matches the wallet's base address.
174
+ */
175
+ async isWalletAddress(params) {
176
+ const { address, baseAddress } = params;
177
+ const rootAddress = params.rootAddress;
178
+ if (!address) {
179
+ throw new sdk_core_1.InvalidAddressError('address is required');
180
+ }
181
+ if (!this.isValidAddress(address)) {
182
+ throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
183
+ }
184
+ const { baseAddress: addressBase } = this.getAddressDetails(address);
185
+ const walletBaseAddress = baseAddress || rootAddress;
186
+ if (!walletBaseAddress) {
187
+ throw new sdk_core_1.InvalidAddressError('baseAddress or rootAddress is required for verification');
188
+ }
189
+ const { baseAddress: walletBase } = this.getAddressDetails(walletBaseAddress);
190
+ if (addressBase.toLowerCase() !== walletBase.toLowerCase()) {
191
+ throw new sdk_core_1.UnexpectedAddressError(`address validation failure: expected ${walletBase} but got ${addressBase}`);
192
+ }
193
+ return true;
194
+ }
195
+ /**
196
+ * Parse a serialised Tempo transaction and return its operations as SDK outputs.
197
+ * @inheritdoc
72
198
  */
73
- isValidPub(pub) {
74
- return utils_1.default.isValidPublicKey(pub);
199
+ async parseTransaction(params) {
200
+ const txHex = (params.txHex || params.halfSigned?.txHex);
201
+ if (!txHex) {
202
+ return {};
203
+ }
204
+ if (!(0, utils_1.isTip20Transaction)(txHex)) {
205
+ return {};
206
+ }
207
+ const txBuilder = this.getTransactionBuilder();
208
+ txBuilder.from(txHex);
209
+ const tx = (await txBuilder.build());
210
+ return {
211
+ inputs: tx.inputs.map((input) => ({
212
+ address: input.address,
213
+ amount: input.value,
214
+ coin: this.getChain(),
215
+ })),
216
+ outputs: tx.outputs.map((output) => ({
217
+ address: output.address,
218
+ amount: output.value,
219
+ coin: this.getChain(),
220
+ })),
221
+ };
75
222
  }
76
223
  /**
77
- * Verify that a transaction prebuild complies with the original intention
78
- * @param params
79
- * @param params.txPrebuild
80
- * @param params.txParams
81
- * @returns {boolean}
224
+ * Verify that a Tempo transaction matches the intended recipients and amounts.
225
+ * @inheritdoc
82
226
  */
83
227
  async verifyTransaction(params) {
84
- // TODO: Implement transaction verification
85
- return false;
228
+ const { txParams, txPrebuild } = params;
229
+ if (!txPrebuild?.txHex) {
230
+ return true;
231
+ }
232
+ // signableHex may arrive without the 0x prefix (e.g. from the TSS signing flow).
233
+ const txHex = txPrebuild.txHex.startsWith('0x') ? txPrebuild.txHex : '0x' + txPrebuild.txHex;
234
+ if (!(0, utils_1.isTip20Transaction)(txHex)) {
235
+ throw new Error(`Invalid Tempo transaction hex: expected a 0x76 TIP-20 transaction`);
236
+ }
237
+ const txBuilder = this.getTransactionBuilder();
238
+ txBuilder.from(txHex);
239
+ const tx = (await txBuilder.build());
240
+ const operations = tx.getOperations();
241
+ const rawCalls = tx.getRawCalls();
242
+ // If the caller specified explicit recipients, verify they match the transaction.
243
+ // A transaction is either all token transfer operations OR a single raw contract call — never mixed.
244
+ const recipients = txParams?.recipients;
245
+ if (recipients && recipients.length > 0) {
246
+ if (rawCalls.length > 0) {
247
+ // Contract call transaction — single raw call, single recipient with data
248
+ if (rawCalls.length !== recipients.length) {
249
+ throw new Error(`Transaction has ${rawCalls.length} call(s) but ${recipients.length} recipient(s) were requested`);
250
+ }
251
+ for (let i = 0; i < rawCalls.length; i++) {
252
+ const rawCall = rawCalls[i];
253
+ const recipient = recipients[i];
254
+ if (rawCall.to.toLowerCase() !== recipient.address.split('?')[0].toLowerCase()) {
255
+ throw new Error(`Raw call ${i} address mismatch: expected ${recipient.address}, got ${rawCall.to}`);
256
+ }
257
+ if (!recipient.data || rawCall.data.toLowerCase() !== recipient.data.toLowerCase()) {
258
+ throw new Error(`Raw call ${i} calldata mismatch`);
259
+ }
260
+ }
261
+ }
262
+ else {
263
+ // Token transfer transaction — operations matched 1-to-1 against recipients
264
+ if (operations.length !== recipients.length) {
265
+ throw new Error(`Transaction has ${operations.length} operation(s) but ${recipients.length} recipient(s) were requested`);
266
+ }
267
+ for (let i = 0; i < operations.length; i++) {
268
+ const op = operations[i];
269
+ const recipient = recipients[i];
270
+ const recipientBaseAddress = recipient.address.split('?')[0];
271
+ if (op.to.toLowerCase() !== recipientBaseAddress.toLowerCase()) {
272
+ throw new Error(`Operation ${i} recipient mismatch: expected ${recipient.address}, got ${op.to}`);
273
+ }
274
+ const opAmountBaseUnits = (0, utils_1.amountToTip20Units)(op.amount).toString();
275
+ if (opAmountBaseUnits !== recipient.amount.toString()) {
276
+ throw new Error(`Operation ${i} amount mismatch: expected ${recipient.amount}, got ${opAmountBaseUnits}`);
277
+ }
278
+ }
279
+ }
280
+ }
281
+ // Verify fee token if specified
282
+ if (txParams?.feeToken) {
283
+ const txFeeToken = tx.getFeeToken();
284
+ if (txFeeToken?.toLowerCase() !== txParams.feeToken.toLowerCase()) {
285
+ throw new Error(`Fee token mismatch: expected ${txParams.feeToken}, got ${txFeeToken || 'none'}`);
286
+ }
287
+ }
288
+ return true;
86
289
  }
87
290
  /**
88
- * Check if address is a wallet address
89
- * @param params
291
+ * Set coin-specific fields in the intent for Tempo TSS transactions.
292
+ * Ensures feeToken is properly wired through the intent for Tempo transactions.
293
+ * @param intent - The populated intent to modify
294
+ * @param params - The parameters containing feeToken
90
295
  */
91
- async isWalletAddress(params) {
92
- // TODO: Implement address verification
93
- return false;
296
+ setCoinSpecificFieldsInIntent(intent, params) {
297
+ if (params.feeToken) {
298
+ intent.feeOptions = intent.feeOptions
299
+ ? { ...intent.feeOptions, feeToken: params.feeToken }
300
+ : { feeToken: params.feeToken };
301
+ }
94
302
  }
95
303
  /**
96
- * Audit a decrypted private key for security purposes
97
- * @param params
304
+ * Query the Tempo Alchemy RPC for recovery balance/nonce information.
305
+ * Routes through queryTempoRpc using the URL from environments.ts.
98
306
  */
99
- async auditDecryptedKey(params) {
100
- // TODO: Implement key auditing logic if needed
101
- // This method is typically used for security compliance
102
- return Promise.resolve();
307
+ async recoveryBlockchainExplorerQuery(query, apiKey) {
308
+ const evmConfig = sdk_core_1.common.Environments[this.bitgo.getEnv()].evm;
309
+ const coinFamily = this.getFamily();
310
+ if (!evmConfig || !(coinFamily in evmConfig)) {
311
+ throw new Error(`env config missing for ${coinFamily} in ${this.bitgo.getEnv()}`);
312
+ }
313
+ const token = apiKey || evmConfig[coinFamily].apiToken;
314
+ const rpcUrl = evmConfig[coinFamily].baseUrl;
315
+ return this.queryTempoRpc(query, rpcUrl, token);
103
316
  }
104
317
  /**
105
- * Parse a transaction from the raw transaction hex
106
- * @param params
318
+ * Translates Etherscan-style recovery queries into Tempo Alchemy JSON-RPC calls.
319
+ *
320
+ * Supported:
321
+ * account/balance → returns { result: '0' } (no native coin on Tempo)
322
+ * account/tokenbalance → eth_call (balanceOf selector 0x70a08231) → { result: decimalString }
323
+ * account/txlist → eth_getTransactionCount → { nonce: number }
107
324
  */
108
- async parseTransaction(params) {
109
- // TODO: Implement transaction parsing
110
- return {};
325
+ async queryTempoRpc(query, rpcUrl, apiKey) {
326
+ const endpoint = apiKey ? `${rpcUrl}${apiKey}` : rpcUrl;
327
+ const { module, action, address, contractaddress, tag } = query;
328
+ let method;
329
+ let params;
330
+ if (module === 'account' && action === 'balance') {
331
+ return { result: '0' };
332
+ }
333
+ else if (module === 'account' && action === 'tokenbalance') {
334
+ const paddedAddr = (address ?? '').replace(/^0x/, '').padStart(64, '0');
335
+ method = 'eth_call';
336
+ params = [{ to: contractaddress, data: '0x70a08231' + paddedAddr }, tag ?? 'latest'];
337
+ }
338
+ else if (module === 'account' && action === 'txlist') {
339
+ method = 'eth_getTransactionCount';
340
+ params = [address, 'latest'];
341
+ }
342
+ else {
343
+ throw new Error(`queryTempoRpc: unsupported module=${module} action=${action}`);
344
+ }
345
+ const res = await fetch(endpoint, {
346
+ method: 'POST',
347
+ headers: { 'Content-Type': 'application/json' },
348
+ body: JSON.stringify({ jsonrpc: '2.0', method, params, id: 1 }),
349
+ });
350
+ if (!res.ok) {
351
+ throw new Error(`Could not reach Tempo RPC endpoint (HTTP ${res.status})`);
352
+ }
353
+ const body = (await res.json());
354
+ if (body.error) {
355
+ throw new Error(`Tempo RPC error: ${body.error.message}`);
356
+ }
357
+ if (module === 'account' && action === 'txlist') {
358
+ return { nonce: parseInt(body.result, 16) };
359
+ }
360
+ try {
361
+ return { result: BigInt(body.result).toString() };
362
+ }
363
+ catch {
364
+ return { result: '0' };
365
+ }
111
366
  }
112
367
  /**
113
- * Explain a transaction
114
- * @param params
368
+ * Shared helper: queries the token balance, computes sweep amount, and builds
369
+ * an unsigned TIP-20 transfer transaction. Used by both recovery paths.
370
+ *
371
+ * - tokenContractAddress: the token to sweep (defaults to pathUSD)
372
+ * - feeToken: always pathUSD
373
+ * - If sweeping pathUSD itself, reserves gasLimit × maxFeePerGas / 10^12 pathUSD units for fees.
115
374
  */
116
- async explainTransaction(params) {
117
- // TODO: Implement transaction explanation
118
- return {};
375
+ async buildTempoSweepTx(walletAddress, params) {
376
+ if (!params.tokenContractAddress) {
377
+ throw new Error('tokenContractAddress is required for sweep');
378
+ }
379
+ const tokenAddress = params.tokenContractAddress;
380
+ const pathUsdTokenName = this.getChain() === constants_1.MAINNET_COIN ? constants_1.PATH_USD_TOKEN_MAINNET : constants_1.PATH_USD_TOKEN_TESTNET;
381
+ const pathUsdAddress = statics_1.coins.get(pathUsdTokenName).contractAddress;
382
+ const rawBalance = await this.queryAddressTokenBalance(tokenAddress, walletAddress, params.apiKey);
383
+ const balance = BigInt(rawBalance.toString());
384
+ const isPathUsd = tokenAddress.toLowerCase() === pathUsdAddress.toLowerCase();
385
+ const gasLimitBig = BigInt(params.gasLimit ?? 700000);
386
+ const maxFeePerGasBig = BigInt(params.eip1559?.maxFeePerGas ?? 20000000000);
387
+ // 75% buffer on top of gasLimit × maxFeePerGas to cover actual on-chain gas variance
388
+ const gasMarginUnits = (gasLimitBig * maxFeePerGasBig * 175n) / (10n ** 12n * 100n);
389
+ const sweepAmount = isPathUsd ? balance - gasMarginUnits : balance;
390
+ if (sweepAmount <= 0n) {
391
+ throw new Error(`Insufficient balance in ${tokenAddress}: ${balance} units (minimum required: ${isPathUsd ? gasMarginUnits + 1n : 1n})`);
392
+ }
393
+ const sweepAmountHuman = (0, utils_1.tip20UnitsToAmount)(sweepAmount);
394
+ const nonce = await this.getAddressNonce(walletAddress, params.apiKey);
395
+ const txBuilder = this.getTransactionBuilder();
396
+ txBuilder
397
+ .addOperation({ token: tokenAddress, to: params.recoveryDestination, amount: sweepAmountHuman })
398
+ .feeToken(pathUsdAddress)
399
+ .nonce(nonce)
400
+ .gas(gasLimitBig)
401
+ .maxFeePerGas(maxFeePerGasBig)
402
+ .maxPriorityFeePerGas(BigInt(params.eip1559?.maxPriorityFeePerGas ?? 10000000000));
403
+ const tx = (await txBuilder.build());
404
+ return { tx, nonce, sweepAmount, gasMarginUnits };
405
+ }
406
+ /**
407
+ * Overrides the base-class recoverTSS to use TIP-20 transactions instead of standard ETH.
408
+ *
409
+ * Two paths:
410
+ * - Unsigned sweep (plain public key shares): delegates to buildUnsignedSweepTxnTSS
411
+ * - Signed sweep (encrypted keys + passphrase): builds and signs a TIP-20 tx via MPC
412
+ */
413
+ async recoverTSS(params) {
414
+ this.validateRecoveryParams(params);
415
+ const userKey = params.userKey.replace(/\s/g, '');
416
+ const backupKey = params.backupKey.replace(/\s/g, '');
417
+ if ((0, sdk_core_1.getIsUnsignedSweep)({ userKey, backupKey, isTss: params.isTss })) {
418
+ return this.buildUnsignedSweepTxnTSS(params);
419
+ }
420
+ // Signed sweep: decrypt MPC v2 key shares
421
+ const { userKeyShare, backupKeyShare, commonKeyChain } = await sdk_core_1.ECDSAUtils.getMpcV2RecoveryKeyShares(userKey, backupKey, params.walletPassphrase);
422
+ const MPC = new sdk_core_1.Ecdsa();
423
+ const derivedCommonKeyChain = MPC.deriveUnhardened(commonKeyChain, 'm/0');
424
+ const backupKeyPair = new abstract_eth_1.KeyPair({ pub: derivedCommonKeyChain.slice(0, 66) });
425
+ const baseAddress = backupKeyPair.getAddress();
426
+ const { tx: unsignedTx } = await this.buildTempoSweepTx(baseAddress, params);
427
+ const serializedHex = await unsignedTx.serialize();
428
+ // Hash the unsigned 0x76 tx — matches Tip20TransactionBuilder's own signing logic
429
+ const msgHashHex = ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.arrayify(serializedHex));
430
+ const messageHash = Buffer.from(msgHashHex.replace('0x', ''), 'hex');
431
+ const signature = await sdk_core_1.ECDSAUtils.signRecoveryMpcV2(messageHash, userKeyShare, backupKeyShare, commonKeyChain);
432
+ // ECDSAMethodTypes.Signature.r/s are 64-char hex WITHOUT 0x prefix
433
+ unsignedTx.setSignature({
434
+ r: `0x${signature.r}`,
435
+ s: `0x${signature.s}`,
436
+ yParity: signature.recid,
437
+ });
438
+ const signedHex = await unsignedTx.serialize();
439
+ const txId = ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.arrayify(signedHex));
440
+ return { id: txId, tx: signedHex };
441
+ }
442
+ /**
443
+ * Builds an unsigned TIP-20 sweep transaction for the offline vault (unsigned sweep path).
444
+ * Called by recoverTSS when plain public key shares are provided.
445
+ */
446
+ async buildUnsignedSweepTxnTSS(params) {
447
+ const backupKey = params.backupKey.replace(/\s/g, '');
448
+ const derivationPath = params.derivationSeed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.derivationSeed) : 'm/0';
449
+ const MPC = new sdk_core_1.Ecdsa();
450
+ const derivedCommonKeyChain = MPC.deriveUnhardened(backupKey, derivationPath);
451
+ const backupKeyPair = new abstract_eth_1.KeyPair({ pub: derivedCommonKeyChain.slice(0, 66) });
452
+ const baseAddress = backupKeyPair.getAddress();
453
+ const { tx, nonce, sweepAmount, gasMarginUnits } = await this.buildTempoSweepTx(baseAddress, params);
454
+ const serializedHex = await tx.serialize();
455
+ const serializedTxHex = serializedHex.replace('0x', '');
456
+ const signableHex = ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.arrayify(serializedHex)).replace('0x', '');
457
+ return {
458
+ txRequests: [
459
+ {
460
+ walletCoin: this.getChain(),
461
+ transactions: [
462
+ {
463
+ unsignedTx: {
464
+ serializedTxHex,
465
+ signableHex,
466
+ derivationPath,
467
+ feeInfo: {
468
+ fee: Number(gasMarginUnits),
469
+ feeString: (0, utils_1.tip20UnitsToAmount)(gasMarginUnits),
470
+ },
471
+ parsedTx: {
472
+ spendAmount: (0, utils_1.tip20UnitsToAmount)(sweepAmount),
473
+ outputs: [
474
+ {
475
+ coinName: this.getChain(),
476
+ address: params.recoveryDestination,
477
+ valueString: (0, utils_1.tip20UnitsToAmount)(sweepAmount),
478
+ },
479
+ ],
480
+ },
481
+ coinSpecific: { commonKeyChain: backupKey },
482
+ eip1559: params.eip1559,
483
+ replayProtectionOptions: params.replayProtectionOptions,
484
+ },
485
+ nonce,
486
+ signatureShares: [],
487
+ },
488
+ ],
489
+ },
490
+ ],
491
+ };
119
492
  }
120
493
  /**
121
- * Sign a transaction
122
- * @param params
494
+ * Get transaction builder for Tempo.
123
495
  */
124
- async signTransaction(params) {
125
- // TODO: Implement transaction signing
126
- return {};
496
+ getTransactionBuilder(common) {
497
+ return new lib_1.Tip20TransactionBuilder(statics_1.coins.get(this.getBaseChain()));
127
498
  }
128
499
  }
129
500
  exports.Tempo = Tempo;
130
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcG8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVtcG8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsbURBWThCO0FBRTlCLDJDQUF3RDtBQUN4RCx3REFBZ0M7QUFFaEMsTUFBYSxLQUFNLFNBQVEsbUJBQVE7SUFHakMsWUFBc0IsS0FBZ0IsRUFBRSxXQUF1QztRQUM3RSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFYixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztJQUNsQyxDQUFDO0lBRUQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFnQixFQUFFLFdBQXVDO1FBQzdFLE9BQU8sSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7T0FFRztJQUNJLGFBQWE7UUFDbEIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sUUFBUTtRQUNiLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFTSxTQUFTO1FBQ2QsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVNLFdBQVc7UUFDaEIsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7T0FHRztJQUNILHdCQUF3QjtRQUN0QixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsT0FBZTtRQUM1QixPQUFPLGVBQUssQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZUFBZSxDQUFDLElBQWE7UUFDM0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLGlCQUFZLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLGlCQUFZLEVBQUUsQ0FBQztRQUN2RSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBRUQsT0FBTztZQUNMLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztZQUNiLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztTQUNkLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxVQUFVLENBQUMsR0FBVztRQUNwQixPQUFPLGVBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQWdDO1FBQ3RELDJDQUEyQztRQUMzQyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLE1BQTRCO1FBQ2hELHVDQUF1QztRQUN2QyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsaUJBQWlCLENBQUMsTUFBK0I7UUFDckQsK0NBQStDO1FBQy9DLHdEQUF3RDtRQUN4RCxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLE1BQStCO1FBQ3BELHNDQUFzQztRQUN0QyxPQUFPLEVBQXVCLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUErQjtRQUN0RCwwQ0FBMEM7UUFDMUMsT0FBTyxFQUE0QixDQUFDO0lBQ3RDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLE1BQThCO1FBQ2xELHNDQUFzQztRQUN0QyxPQUFPLEVBQXVCLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBM0lELHNCQTJJQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEF1ZGl0RGVjcnlwdGVkS2V5UGFyYW1zLFxuICBCYXNlQ29pbixcbiAgQml0R29CYXNlLFxuICBLZXlQYWlyLFxuICBQYXJzZWRUcmFuc2FjdGlvbixcbiAgUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFNpZ25lZFRyYW5zYWN0aW9uLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBWZXJpZnlBZGRyZXNzT3B0aW9ucyxcbiAgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zLFxuICBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4gfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7IEtleVBhaXIgYXMgVGVtcG9LZXlQYWlyIH0gZnJvbSAnLi9saWIva2V5UGFpcic7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi9saWIvdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgVGVtcG8gZXh0ZW5kcyBCYXNlQ29pbiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBfc3RhdGljc0NvaW46IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj47XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGJpdGdvOiBCaXRHb0Jhc2UsIHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPikge1xuICAgIHN1cGVyKGJpdGdvKTtcblxuICAgIGlmICghc3RhdGljc0NvaW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyByZXF1aXJlZCBjb25zdHJ1Y3RvciBwYXJhbWV0ZXIgc3RhdGljc0NvaW4nKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zdGF0aWNzQ29pbiA9IHN0YXRpY3NDb2luO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZUluc3RhbmNlKGJpdGdvOiBCaXRHb0Jhc2UsIHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPik6IEJhc2VDb2luIHtcbiAgICByZXR1cm4gbmV3IFRlbXBvKGJpdGdvLCBzdGF0aWNzQ29pbik7XG4gIH1cblxuICAvKipcbiAgICogRmFjdG9yIGJldHdlZW4gdGhlIGNvaW4ncyBiYXNlIHVuaXQgYW5kIGl0cyBzbWFsbGVzdCBzdWJkaXZpc2lvblxuICAgKi9cbiAgcHVibGljIGdldEJhc2VGYWN0b3IoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gMWUxODtcbiAgfVxuXG4gIHB1YmxpYyBnZXRDaGFpbigpOiBzdHJpbmcge1xuICAgIHJldHVybiAndGVtcG8nO1xuICB9XG5cbiAgcHVibGljIGdldEZhbWlseSgpOiBzdHJpbmcge1xuICAgIHJldHVybiAndGVtcG8nO1xuICB9XG5cbiAgcHVibGljIGdldEZ1bGxOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdUZW1wbyc7XG4gIH1cblxuICAvKipcbiAgICogRmxhZyBmb3Igc2VuZGluZyB2YWx1ZSBvZiAwXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG9rYXkgdG8gc2VuZCAwIHZhbHVlLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHZhbHVlbGVzc1RyYW5zZmVyQWxsb3dlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoaXMgaXMgYSB2YWxpZCBiYXNlNTggb3IgaGV4IGFkZHJlc3NcbiAgICogQHBhcmFtIGFkZHJlc3NcbiAgICovXG4gIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB1dGlscy5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBlZDI1NTE5IGtleSBwYWlyXG4gICAqXG4gICAqIEBwYXJhbSBzZWVkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IG9iamVjdCB3aXRoIGdlbmVyYXRlZCBwdWIsIHBydlxuICAgKi9cbiAgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIpOiBLZXlQYWlyIHtcbiAgICBjb25zdCBrZXlQYWlyID0gc2VlZCA/IG5ldyBUZW1wb0tleVBhaXIoeyBzZWVkIH0pIDogbmV3IFRlbXBvS2V5UGFpcigpO1xuICAgIGNvbnN0IGtleXMgPSBrZXlQYWlyLmdldEtleXMoKTtcblxuICAgIGlmICgha2V5cy5wcnYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBwcnYgaW4ga2V5IGdlbmVyYXRpb24uJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHB1Yjoga2V5cy5wdWIsXG4gICAgICBwcnY6IGtleXMucHJ2LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIGlucHV0IGlzIHZhbGlkIHB1YmxpYyBrZXkgZm9yIHRoZSBjb2luLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHViIHRoZSBwdWIgdG8gYmUgY2hlY2tlZFxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gaXMgaXQgdmFsaWQ/XG4gICAqL1xuICBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHV0aWxzLmlzVmFsaWRQdWJsaWNLZXkocHViKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZnkgdGhhdCBhIHRyYW5zYWN0aW9uIHByZWJ1aWxkIGNvbXBsaWVzIHdpdGggdGhlIG9yaWdpbmFsIGludGVudGlvblxuICAgKiBAcGFyYW0gcGFyYW1zXG4gICAqIEBwYXJhbSBwYXJhbXMudHhQcmVidWlsZFxuICAgKiBAcGFyYW0gcGFyYW1zLnR4UGFyYW1zXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgYXN5bmMgdmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgdHJhbnNhY3Rpb24gdmVyaWZpY2F0aW9uXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGFkZHJlc3MgaXMgYSB3YWxsZXQgYWRkcmVzc1xuICAgKiBAcGFyYW0gcGFyYW1zXG4gICAqL1xuICBhc3luYyBpc1dhbGxldEFkZHJlc3MocGFyYW1zOiBWZXJpZnlBZGRyZXNzT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIFRPRE86IEltcGxlbWVudCBhZGRyZXNzIHZlcmlmaWNhdGlvblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdWRpdCBhIGRlY3J5cHRlZCBwcml2YXRlIGtleSBmb3Igc2VjdXJpdHkgcHVycG9zZXNcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgYXVkaXREZWNyeXB0ZWRLZXkocGFyYW1zOiBBdWRpdERlY3J5cHRlZEtleVBhcmFtcyk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIFRPRE86IEltcGxlbWVudCBrZXkgYXVkaXRpbmcgbG9naWMgaWYgbmVlZGVkXG4gICAgLy8gVGhpcyBtZXRob2QgaXMgdHlwaWNhbGx5IHVzZWQgZm9yIHNlY3VyaXR5IGNvbXBsaWFuY2VcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvKipcbiAgICogUGFyc2UgYSB0cmFuc2FjdGlvbiBmcm9tIHRoZSByYXcgdHJhbnNhY3Rpb24gaGV4XG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICovXG4gIGFzeW5jIHBhcnNlVHJhbnNhY3Rpb24ocGFyYW1zOiBQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8UGFyc2VkVHJhbnNhY3Rpb24+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgdHJhbnNhY3Rpb24gcGFyc2luZ1xuICAgIHJldHVybiB7fSBhcyBQYXJzZWRUcmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBsYWluIGEgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgZXhwbGFpblRyYW5zYWN0aW9uKHBhcmFtczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQcm9taXNlPFRyYW5zYWN0aW9uRXhwbGFuYXRpb24+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgdHJhbnNhY3Rpb24gZXhwbGFuYXRpb25cbiAgICByZXR1cm4ge30gYXMgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIGEgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgc2lnblRyYW5zYWN0aW9uKHBhcmFtczogU2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICAvLyBUT0RPOiBJbXBsZW1lbnQgdHJhbnNhY3Rpb24gc2lnbmluZ1xuICAgIHJldHVybiB7fSBhcyBTaWduZWRUcmFuc2FjdGlvbjtcbiAgfVxufVxuIl19
501
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcG8uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVtcG8udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0dBRUc7QUFDSCwyREFZa0M7QUFFbEMsbURBZThCO0FBQzlCLHlEQUE0RDtBQUM1RCxpREFBeUU7QUFDekUsbUNBQWdDO0FBQ2hDLCtCQUFrRTtBQUNsRSx1Q0FLcUI7QUFDckIsK0NBQStGO0FBQy9GLHlDQUEyQjtBQUMzQix5REFBMkM7QUFFM0MsTUFBYSxLQUFNLFNBQVEsc0NBQXVCO0lBQ2hELFlBQXNCLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsS0FBSyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsT0FBTyxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUTtRQUNOLE9BQU8sSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLElBQUksT0FBTyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVc7UUFDVCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGFBQWE7UUFDWCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRDs7O09BR0c7SUFDSCx3QkFBd0I7UUFDdEIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxlQUFlO1FBQ2IsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsY0FBYyxDQUFDLE9BQWU7UUFDNUIsSUFBSSxPQUFPLE9B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Z0NBQzNDLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztnQ0FDdkIsdUJBQXVCLEVBQUUsTUFBTSxDQUFDLHVCQUF1Qjs2QkFDeEQ7NEJBQ0QsS0FBSzs0QkFDTCxlQUFlLEVBQUUsRUFBRTt5QkFDcEI7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDTyxxQkFBcUIsQ0FBQyxNQUE4QjtRQUM1RCxPQUFPLElBQUksNkJBQXVCLENBQUMsZUFBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBa0MsQ0FBQztJQUN0RyxDQUFDO0NBQ0Y7QUF4aEJELHNCQXdoQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwcmV0dGllclxuICovXG5pbXBvcnQge1xuICBBYnN0cmFjdEV0aExpa2VOZXdDb2lucyxcbiAgUmVjb3Zlck9wdGlvbnMsXG4gIE9mZmxpbmVWYXVsdFR4SW5mbyxcbiAgVW5zaWduZWRTd2VlcFR4TVBDdjIsXG4gIFJlY292ZXJ5SW5mbyxcbiAgVHJhbnNhY3Rpb25CdWlsZGVyLFxuICBWZXJpZnlFdGhUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFZlcmlmeUV0aEFkZHJlc3NPcHRpb25zLFxuICBUc3NWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucyxcbiAgb3B0aW9uYWxEZXBzLFxuICBLZXlQYWlyLFxufSBmcm9tICdAYml0Z28tYmV0YS9hYnN0cmFjdC1ldGgnO1xuaW1wb3J0IHR5cGUgKiBhcyBFdGhMaWtlQ29tbW9uIGZyb20gJ0BldGhlcmV1bWpzL2NvbW1vbic7XG5pbXBvcnQge1xuICBCYXNlQ29pbixcbiAgQml0R29CYXNlLFxuICBJbnZhbGlkQWRkcmVzc0Vycm9yLFxuICBJbnZhbGlkTWVtb0lkRXJyb3IsXG4gIE1QQ0FsZ29yaXRobSxcbiAgUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFBhcnNlZFRyYW5zYWN0aW9uLFxuICBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yLFxuICBQb3B1bGF0ZWRJbnRlbnQsXG4gIFByZWJ1aWxkVHJhbnNhY3Rpb25XaXRoSW50ZW50T3B0aW9ucyxcbiAgY29tbW9uLFxuICBFY2RzYSxcbiAgRUNEU0FVdGlscyxcbiAgZ2V0SXNVbnNpZ25lZFN3ZWVwLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBnZXREZXJpdmF0aW9uUGF0aCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1saWItbXBjJztcbmltcG9ydCB7IEJhc2VDb2luIGFzIFN0YXRpY3NCYXNlQ29pbiwgY29pbnMgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7IGV0aGVycyB9IGZyb20gJ2V0aGVycyc7XG5pbXBvcnQgeyBUaXAyMFRyYW5zYWN0aW9uLCBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlciB9IGZyb20gJy4vbGliJztcbmltcG9ydCB7XG4gIGFtb3VudFRvVGlwMjBVbml0cyxcbiAgdGlwMjBVbml0c1RvQW1vdW50LFxuICBpc1RpcDIwVHJhbnNhY3Rpb24sXG4gIGlzVmFsaWRNZW1vSWQgYXMgaXNWYWxpZE1lbW9JZFV0aWwsXG59IGZyb20gJy4vbGliL3V0aWxzJztcbmltcG9ydCB7IE1BSU5ORVRfQ09JTiwgUEFUSF9VU0RfVE9LRU5fTUFJTk5FVCwgUEFUSF9VU0RfVE9LRU5fVEVTVE5FVCB9IGZyb20gJy4vbGliL2NvbnN0YW50cyc7XG5pbXBvcnQgKiBhcyB1cmwgZnJvbSAndXJsJztcbmltcG9ydCAqIGFzIHF1ZXJ5c3RyaW5nIGZyb20gJ3F1ZXJ5c3RyaW5nJztcblxuZXhwb3J0IGNsYXNzIFRlbXBvIGV4dGVuZHMgQWJzdHJhY3RFdGhMaWtlTmV3Q29pbnMge1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28sIHN0YXRpY3NDb2luKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGYWN0b3J5IG1ldGhvZCB0byBjcmVhdGUgVGVtcG8gaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBjcmVhdGVJbnN0YW5jZShiaXRnbzogQml0R29CYXNlLCBzdGF0aWNzQ29pbj86IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj4pOiBCYXNlQ29pbiB7XG4gICAgcmV0dXJuIG5ldyBUZW1wbyhiaXRnbywgc3RhdGljc0NvaW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY2hhaW4gaWRlbnRpZmllclxuICAgKi9cbiAgZ2V0Q2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGljc0NvaW4/Lm5hbWUgfHwgJ3RlbXBvJztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGZ1bGwgY2hhaW4gbmFtZVxuICAgKi9cbiAgZ2V0RnVsbE5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ1RlbXBvJztcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBnZXRCYXNlRmFjdG9yKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIDFlNjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB2YWx1ZS1sZXNzIHRyYW5zZmVycyBhcmUgYWxsb3dlZFxuICAgKiBFVk0tYmFzZWQgY2hhaW5zIGFsbG93IHplcm8tdmFsdWUgdHJhbnNmZXJzIGZvciBzbWFydCBjb250cmFjdCBpbnRlcmFjdGlvbnNcbiAgICovXG4gIHZhbHVlbGVzc1RyYW5zZmVyQWxsb3dlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBUU1MgaXMgc3VwcG9ydGVkXG4gICAqL1xuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIE1QQyBhbGdvcml0aG0gKEVDRFNBIGZvciBFVk0gY2hhaW5zKVxuICAgKi9cbiAgZ2V0TVBDQWxnb3JpdGhtKCk6IE1QQ0FsZ29yaXRobSB7XG4gICAgcmV0dXJuICdlY2RzYSc7XG4gIH1cblxuICAvKipcbiAgICogRXZhbHVhdGVzIHdoZXRoZXIgYW4gYWRkcmVzcyBzdHJpbmcgaXMgdmFsaWQgZm9yIFRlbXBvXG4gICAqIFN1cHBvcnRzIGFkZHJlc3NlcyB3aXRoIG9wdGlvbmFsIG1lbW9JZCBxdWVyeSBwYXJhbWV0ZXIgKGUuZy4sIDB4Li4uP21lbW9JZD0xMjMpXG4gICAqIEBwYXJhbSBhZGRyZXNzIC0gVGhlIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMgdHJ1ZSBpZiBhZGRyZXNzIGlzIHZhbGlkXG4gICAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAodHlwZW9mIGFkZHJlc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgYmFzZUFkZHJlc3MgfSA9IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMoYWRkcmVzcyk7XG4gICAgICByZXR1cm4gb3B0aW9uYWxEZXBzLmV0aFV0aWwuaXNWYWxpZEFkZHJlc3Mob3B0aW9uYWxEZXBzLmV0aFV0aWwuYWRkSGV4UHJlZml4KGJhc2VBZGRyZXNzKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBhZGRyZXNzIGludG8gYmFzZSBhZGRyZXNzIGFuZCBvcHRpb25hbCBtZW1vSWRcbiAgICogVGhyb3dzIEludmFsaWRBZGRyZXNzRXJyb3IgZm9yIGludmFsaWQgYWRkcmVzcyBmb3JtYXRzXG4gICAqIEBwYXJhbSBhZGRyZXNzIC0gQWRkcmVzcyBzdHJpbmcsIHBvdGVudGlhbGx5IHdpdGggP21lbW9JZD1YIHN1ZmZpeFxuICAgKiBAcmV0dXJucyBPYmplY3QgY29udGFpbmluZyBhZGRyZXNzLCBiYXNlQWRkcmVzcywgYW5kIG1lbW9JZCAobnVsbCBpZiBub3QgcHJlc2VudClcbiAgICogQHRocm93cyBJbnZhbGlkQWRkcmVzc0Vycm9yIGlmIGFkZHJlc3MgZm9ybWF0IGlzIGludmFsaWRcbiAgICovXG4gIGdldEFkZHJlc3NEZXRhaWxzKGFkZHJlc3M6IHN0cmluZyk6IHsgYWRkcmVzczogc3RyaW5nOyBiYXNlQWRkcmVzczogc3RyaW5nOyBtZW1vSWQ6IHN0cmluZyB8IG51bGwgfSB7XG4gICAgaWYgKHR5cGVvZiBhZGRyZXNzICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgYWRkcmVzczogJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGRlc3RpbmF0aW9uRGV0YWlscyA9IHVybC5wYXJzZShhZGRyZXNzKTtcbiAgICBjb25zdCBiYXNlQWRkcmVzcyA9IGRlc3RpbmF0aW9uRGV0YWlscy5wYXRobmFtZSB8fCAnJztcblxuICAgIC8vIE5vIHF1ZXJ5IHN0cmluZyAtIGp1c3QgYSBwbGFpbiBhZGRyZXNzXG4gICAgaWYgKGRlc3RpbmF0aW9uRGV0YWlscy5wYXRobmFtZSA9PT0gYWRkcmVzcykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgYmFzZUFkZHJlc3M6IGFkZHJlc3MsXG4gICAgICAgIG1lbW9JZDogbnVsbCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gSGFzIHF1ZXJ5IHN0cmluZyAtIG11c3QgY29udGFpbiBtZW1vSWRcbiAgICBpZiAoIWRlc3RpbmF0aW9uRGV0YWlscy5xdWVyeSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgYWRkcmVzczogJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHF1ZXJ5RGV0YWlscyA9IHF1ZXJ5c3RyaW5nLnBhcnNlKGRlc3RpbmF0aW9uRGV0YWlscy5xdWVyeSk7XG5cbiAgICAvLyBRdWVyeSBzdHJpbmcgbXVzdCBjb250YWluIG1lbW9JZFxuICAgIGlmICghcXVlcnlEZXRhaWxzLm1lbW9JZCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgYWRkcmVzczogJHthZGRyZXNzfSwgdW5rbm93biBxdWVyeSBwYXJhbWV0ZXJzYCk7XG4gICAgfVxuXG4gICAgLy8gT25seSBvbmUgbWVtb0lkIGFsbG93ZWRcbiAgICBpZiAoQXJyYXkuaXNBcnJheShxdWVyeURldGFpbHMubWVtb0lkKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoXG4gICAgICAgIGBtZW1vSWQgbWF5IG9ubHkgYmUgZ2l2ZW4gYXQgbW9zdCBvbmNlLCBidXQgZm91bmQgJHtxdWVyeURldGFpbHMubWVtb0lkLmxlbmd0aH0gaW5zdGFuY2VzIGluIGFkZHJlc3MgJHthZGRyZXNzfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gUmVqZWN0IGlmIHRoZXJlIGFyZSBvdGhlciBxdWVyeSBwYXJhbWV0ZXJzIGJlc2lkZXMgbWVtb0lkXG4gICAgY29uc3QgcXVlcnlLZXlzID0gT2JqZWN0LmtleXMocXVlcnlEZXRhaWxzKTtcbiAgICBpZiAocXVlcnlLZXlzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzRXJyb3IoYGludmFsaWQgYWRkcmVzczogJHthZGRyZXNzfSwgb25seSBtZW1vSWQgcXVlcnkgcGFyYW1ldGVyIGlzIGFsbG93ZWRgKTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBtZW1vSWQgZm9ybWF0XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRNZW1vSWQocXVlcnlEZXRhaWxzLm1lbW9JZCkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkTWVtb0lkRXJyb3IoYGludmFsaWQgYWRkcmVzczogJyR7YWRkcmVzc30nLCBtZW1vSWQgaXMgbm90IHZhbGlkYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGFkZHJlc3MsXG4gICAgICBiYXNlQWRkcmVzcyxcbiAgICAgIG1lbW9JZDogcXVlcnlEZXRhaWxzLm1lbW9JZCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgYSBtZW1vSWQgaXMgYSB2YWxpZCBub24tbmVnYXRpdmUgaW50ZWdlciBzdHJpbmdcbiAgICogQHBhcmFtIG1lbW9JZCAtIFRoZSBtZW1vSWQgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB2YWxpZFxuICAgKi9cbiAgaXNWYWxpZE1lbW9JZChtZW1vSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc1ZhbGlkTWVtb0lkVXRpbChtZW1vSWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRlbXBvIHVzZXMgbWVtb0lkLWJhc2VkIGFkZHJlc3NlcyByYXRoZXIgdGhhbiBmb3J3YXJkZXIgY29udHJhY3RzLlxuICAgKiBWZXJpZnkgdGhhdCB0aGUgYWRkcmVzcyBiZWxvbmdzIHRvIHRoaXMgd2FsbGV0IGJ5IGNoZWNraW5nIHRoYXQgdGhlXG4gICAqIGJhc2UgKEVWTSkgcG9ydGlvbiBtYXRjaGVzIHRoZSB3YWxsZXQncyBiYXNlIGFkZHJlc3MuXG4gICAqL1xuICBhc3luYyBpc1dhbGxldEFkZHJlc3MocGFyYW1zOiBWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucyB8IFRzc1ZlcmlmeUV0aEFkZHJlc3NPcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgeyBhZGRyZXNzLCBiYXNlQWRkcmVzcyB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IHJvb3RBZGRyZXNzID0gKHBhcmFtcyBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5yb290QWRkcmVzcyBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAoIWFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKCdhZGRyZXNzIGlzIHJlcXVpcmVkJyk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAke2FkZHJlc3N9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBiYXNlQWRkcmVzczogYWRkcmVzc0Jhc2UgfSA9IHRoaXMuZ2V0QWRkcmVzc0RldGFpbHMoYWRkcmVzcyk7XG5cbiAgICBjb25zdCB3YWxsZXRCYXNlQWRkcmVzcyA9IGJhc2VBZGRyZXNzIHx8IHJvb3RBZGRyZXNzO1xuICAgIGlmICghd2FsbGV0QmFzZUFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQWRkcmVzc0Vycm9yKCdiYXNlQWRkcmVzcyBvciByb290QWRkcmVzcyBpcyByZXF1aXJlZCBmb3IgdmVyaWZpY2F0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBiYXNlQWRkcmVzczogd2FsbGV0QmFzZSB9ID0gdGhpcy5nZXRBZGRyZXNzRGV0YWlscyh3YWxsZXRCYXNlQWRkcmVzcyk7XG5cbiAgICBpZiAoYWRkcmVzc0Jhc2UudG9Mb3dlckNhc2UoKSAhPT0gd2FsbGV0QmFzZS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICB0aHJvdyBuZXcgVW5leHBlY3RlZEFkZHJlc3NFcnJvcihgYWRkcmVzcyB2YWxpZGF0aW9uIGZhaWx1cmU6IGV4cGVjdGVkICR7d2FsbGV0QmFzZX0gYnV0IGdvdCAke2FkZHJlc3NCYXNlfWApO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIGEgc2VyaWFsaXNlZCBUZW1wbyB0cmFuc2FjdGlvbiBhbmQgcmV0dXJuIGl0cyBvcGVyYXRpb25zIGFzIFNESyBvdXRwdXRzLlxuICAgKiBAaW5oZXJpdGRvY1xuICAgKi9cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIGNvbnN0IHR4SGV4ID0gKHBhcmFtcy50eEhleCB8fCAocGFyYW1zIGFzIGFueSkuaGFsZlNpZ25lZD8udHhIZXgpIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIXR4SGV4KSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIGlmICghaXNUaXAyMFRyYW5zYWN0aW9uKHR4SGV4KSkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBjb25zdCB0eEJ1aWxkZXIgPSB0aGlzLmdldFRyYW5zYWN0aW9uQnVpbGRlcigpO1xuICAgIHR4QnVpbGRlci5mcm9tKHR4SGV4KTtcbiAgICBjb25zdCB0eCA9IChhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICByZXR1cm4ge1xuICAgICAgaW5wdXRzOiB0eC5pbnB1dHMubWFwKChpbnB1dCkgPT4gKHtcbiAgICAgICAgYWRkcmVzczogaW5wdXQuYWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiBpbnB1dC52YWx1ZSxcbiAgICAgICAgY29pbjogdGhpcy5nZXRDaGFpbigpLFxuICAgICAgfSkpLFxuICAgICAgb3V0cHV0czogdHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4gKHtcbiAgICAgICAgYWRkcmVzczogb3V0cHV0LmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogb3V0cHV0LnZhbHVlLFxuICAgICAgICBjb2luOiB0aGlzLmdldENoYWluKCksXG4gICAgICB9KSksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZnkgdGhhdCBhIFRlbXBvIHRyYW5zYWN0aW9uIG1hdGNoZXMgdGhlIGludGVuZGVkIHJlY2lwaWVudHMgYW5kIGFtb3VudHMuXG4gICAqIEBpbmhlcml0ZG9jXG4gICAqL1xuICBhc3luYyB2ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXM6IFZlcmlmeUV0aFRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSA9IHBhcmFtcztcblxuICAgIGlmICghdHhQcmVidWlsZD8udHhIZXgpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIHNpZ25hYmxlSGV4IG1heSBhcnJpdmUgd2l0aG91dCB0aGUgMHggcHJlZml4IChlLmcuIGZyb20gdGhlIFRTUyBzaWduaW5nIGZsb3cpLlxuICAgIGNvbnN0IHR4SGV4ID0gdHhQcmVidWlsZC50eEhleC5zdGFydHNXaXRoKCcweCcpID8gdHhQcmVidWlsZC50eEhleCA6ICcweCcgKyB0eFByZWJ1aWxkLnR4SGV4O1xuICAgIGlmICghaXNUaXAyMFRyYW5zYWN0aW9uKHR4SGV4KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFRlbXBvIHRyYW5zYWN0aW9uIGhleDogZXhwZWN0ZWQgYSAweDc2IFRJUC0yMCB0cmFuc2FjdGlvbmApO1xuICAgIH1cblxuICAgIGNvbnN0IHR4QnVpbGRlciA9IHRoaXMuZ2V0VHJhbnNhY3Rpb25CdWlsZGVyKCk7XG4gICAgdHhCdWlsZGVyLmZyb20odHhIZXgpO1xuICAgIGNvbnN0IHR4ID0gKGF3YWl0IHR4QnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSB0eC5nZXRPcGVyYXRpb25zKCk7XG4gICAgY29uc3QgcmF3Q2FsbHMgPSB0eC5nZXRSYXdDYWxscygpO1xuXG4gICAgLy8gSWYgdGhlIGNhbGxlciBzcGVjaWZpZWQgZXhwbGljaXQgcmVjaXBpZW50cywgdmVyaWZ5IHRoZXkgbWF0Y2ggdGhlIHRyYW5zYWN0aW9uLlxuICAgIC8vIEEgdHJhbnNhY3Rpb24gaXMgZWl0aGVyIGFsbCB0b2tlbiB0cmFuc2ZlciBvcGVyYXRpb25zIE9SIGEgc2luZ2xlIHJhdyBjb250cmFjdCBjYWxsIOKAlCBuZXZlciBtaXhlZC5cbiAgICBjb25zdCByZWNpcGllbnRzID0gdHhQYXJhbXM/LnJlY2lwaWVudHM7XG4gICAgaWYgKHJlY2lwaWVudHMgJiYgcmVjaXBpZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAocmF3Q2FsbHMubGVuZ3RoID4gMCkge1xuICAgICAgICAvLyBDb250cmFjdCBjYWxsIHRyYW5zYWN0aW9uIOKAlCBzaW5nbGUgcmF3IGNhbGwsIHNpbmdsZSByZWNpcGllbnQgd2l0aCBkYXRhXG4gICAgICAgIGlmIChyYXdDYWxscy5sZW5ndGggIT09IHJlY2lwaWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFRyYW5zYWN0aW9uIGhhcyAke3Jhd0NhbGxzLmxlbmd0aH0gY2FsbChzKSBidXQgJHtyZWNpcGllbnRzLmxlbmd0aH0gcmVjaXBpZW50KHMpIHdlcmUgcmVxdWVzdGVkYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYXdDYWxscy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IHJhd0NhbGwgPSByYXdDYWxsc1tpXTtcbiAgICAgICAgICBjb25zdCByZWNpcGllbnQgPSByZWNpcGllbnRzW2ldO1xuICAgICAgICAgIGlmIChyYXdDYWxsLnRvLnRvTG93ZXJDYXNlKCkgIT09IHJlY2lwaWVudC5hZGRyZXNzLnNwbGl0KCc/JylbMF0udG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSYXcgY2FsbCAke2l9IGFkZHJlc3MgbWlzbWF0Y2g6IGV4cGVjdGVkICR7cmVjaXBpZW50LmFkZHJlc3N9LCBnb3QgJHtyYXdDYWxsLnRvfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXJlY2lwaWVudC5kYXRhIHx8IHJhd0NhbGwuZGF0YS50b0xvd2VyQ2FzZSgpICE9PSByZWNpcGllbnQuZGF0YS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJhdyBjYWxsICR7aX0gY2FsbGRhdGEgbWlzbWF0Y2hgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRva2VuIHRyYW5zZmVyIHRyYW5zYWN0aW9uIOKAlCBvcGVyYXRpb25zIG1hdGNoZWQgMS10by0xIGFnYWluc3QgcmVjaXBpZW50c1xuICAgICAgICBpZiAob3BlcmF0aW9ucy5sZW5ndGggIT09IHJlY2lwaWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFRyYW5zYWN0aW9uIGhhcyAke29wZXJhdGlvbnMubGVuZ3RofSBvcGVyYXRpb24ocykgYnV0ICR7cmVjaXBpZW50cy5sZW5ndGh9IHJlY2lwaWVudChzKSB3ZXJlIHJlcXVlc3RlZGBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3BlcmF0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGNvbnN0IG9wID0gb3BlcmF0aW9uc1tpXTtcbiAgICAgICAgICBjb25zdCByZWNpcGllbnQgPSByZWNpcGllbnRzW2ldO1xuICAgICAgICAgIGNvbnN0IHJlY2lwaWVudEJhc2VBZGRyZXNzID0gcmVjaXBpZW50LmFkZHJlc3Muc3BsaXQoJz8nKVswXTtcbiAgICAgICAgICBpZiAob3AudG8udG9Mb3dlckNhc2UoKSAhPT0gcmVjaXBpZW50QmFzZUFkZHJlc3MudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBPcGVyYXRpb24gJHtpfSByZWNpcGllbnQgbWlzbWF0Y2g6IGV4cGVjdGVkICR7cmVjaXBpZW50LmFkZHJlc3N9LCBnb3QgJHtvcC50b31gKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3Qgb3BBbW91bnRCYXNlVW5pdHMgPSBhbW91bnRUb1RpcDIwVW5pdHMob3AuYW1vdW50KS50b1N0cmluZygpO1xuICAgICAgICAgIGlmIChvcEFtb3VudEJhc2VVbml0cyAhPT0gcmVjaXBpZW50LmFtb3VudC50b1N0cmluZygpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE9wZXJhdGlvbiAke2l9IGFtb3VudCBtaXNtYXRjaDogZXhwZWN0ZWQgJHtyZWNpcGllbnQuYW1vdW50fSwgZ290ICR7b3BBbW91bnRCYXNlVW5pdHN9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmVyaWZ5IGZlZSB0b2tlbiBpZiBzcGVjaWZpZWRcbiAgICBpZiAodHhQYXJhbXM/LmZlZVRva2VuKSB7XG4gICAgICBjb25zdCB0eEZlZVRva2VuID0gdHguZ2V0RmVlVG9rZW4oKTtcbiAgICAgIGlmICh0eEZlZVRva2VuPy50b0xvd2VyQ2FzZSgpICE9PSB0eFBhcmFtcy5mZWVUb2tlbi50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmVlIHRva2VuIG1pc21hdGNoOiBleHBlY3RlZCAke3R4UGFyYW1zLmZlZVRva2VufSwgZ290ICR7dHhGZWVUb2tlbiB8fCAnbm9uZSd9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGNvaW4tc3BlY2lmaWMgZmllbGRzIGluIHRoZSBpbnRlbnQgZm9yIFRlbXBvIFRTUyB0cmFuc2FjdGlvbnMuXG4gICAqIEVuc3VyZXMgZmVlVG9rZW4gaXMgcHJvcGVybHkgd2lyZWQgdGhyb3VnaCB0aGUgaW50ZW50IGZvciBUZW1wbyB0cmFuc2FjdGlvbnMuXG4gICAqIEBwYXJhbSBpbnRlbnQgLSBUaGUgcG9wdWxhdGVkIGludGVudCB0byBtb2RpZnlcbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBwYXJhbWV0ZXJzIGNvbnRhaW5pbmcgZmVlVG9rZW5cbiAgICovXG4gIHNldENvaW5TcGVjaWZpY0ZpZWxkc0luSW50ZW50KGludGVudDogUG9wdWxhdGVkSW50ZW50LCBwYXJhbXM6IFByZWJ1aWxkVHJhbnNhY3Rpb25XaXRoSW50ZW50T3B0aW9ucyk6IHZvaWQge1xuICAgIGlmIChwYXJhbXMuZmVlVG9rZW4pIHtcbiAgICAgIGludGVudC5mZWVPcHRpb25zID0gaW50ZW50LmZlZU9wdGlvbnNcbiAgICAgICAgPyB7IC4uLmludGVudC5mZWVPcHRpb25zLCBmZWVUb2tlbjogcGFyYW1zLmZlZVRva2VuIH1cbiAgICAgICAgOiB7IGZlZVRva2VuOiBwYXJhbXMuZmVlVG9rZW4gfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUXVlcnkgdGhlIFRlbXBvIEFsY2hlbXkgUlBDIGZvciByZWNvdmVyeSBiYWxhbmNlL25vbmNlIGluZm9ybWF0aW9uLlxuICAgKiBSb3V0ZXMgdGhyb3VnaCBxdWVyeVRlbXBvUnBjIHVzaW5nIHRoZSBVUkwgZnJvbSBlbnZpcm9ubWVudHMudHMuXG4gICAqL1xuICBhc3luYyByZWNvdmVyeUJsb2NrY2hhaW5FeHBsb3JlclF1ZXJ5KFxuICAgIHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LFxuICAgIGFwaUtleT86IHN0cmluZ1xuICApOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PiB7XG4gICAgY29uc3QgZXZtQ29uZmlnID0gY29tbW9uLkVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS5ldm07XG4gICAgY29uc3QgY29pbkZhbWlseSA9IHRoaXMuZ2V0RmFtaWx5KCk7XG4gICAgaWYgKCFldm1Db25maWcgfHwgIShjb2luRmFtaWx5IGluIGV2bUNvbmZpZykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgZW52IGNvbmZpZyBtaXNzaW5nIGZvciAke2NvaW5GYW1pbHl9IGluICR7dGhpcy5iaXRnby5nZXRFbnYoKX1gKTtcbiAgICB9XG4gICAgY29uc3QgdG9rZW4gPSBhcGlLZXkgfHwgZXZtQ29uZmlnW2NvaW5GYW1pbHldLmFwaVRva2VuO1xuICAgIGNvbnN0IHJwY1VybCA9IGV2bUNvbmZpZ1tjb2luRmFtaWx5XS5iYXNlVXJsO1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5VGVtcG9ScGMocXVlcnksIHJwY1VybCwgdG9rZW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zbGF0ZXMgRXRoZXJzY2FuLXN0eWxlIHJlY292ZXJ5IHF1ZXJpZXMgaW50byBUZW1wbyBBbGNoZW15IEpTT04tUlBDIGNhbGxzLlxuICAgKlxuICAgKiBTdXBwb3J0ZWQ6XG4gICAqICAgYWNjb3VudC9iYWxhbmNlICAgICAg4oaSIHJldHVybnMgeyByZXN1bHQ6ICcwJyB9IChubyBuYXRpdmUgY29pbiBvbiBUZW1wbylcbiAgICogICBhY2NvdW50L3Rva2VuYmFsYW5jZSDihpIgZXRoX2NhbGwgKGJhbGFuY2VPZiBzZWxlY3RvciAweDcwYTA4MjMxKSDihpIgeyByZXN1bHQ6IGRlY2ltYWxTdHJpbmcgfVxuICAgKiAgIGFjY291bnQvdHhsaXN0ICAgICAgIOKGkiBldGhfZ2V0VHJhbnNhY3Rpb25Db3VudCDihpIgeyBub25jZTogbnVtYmVyIH1cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcXVlcnlUZW1wb1JwYyhcbiAgICBxdWVyeTogUmVjb3JkPHN0cmluZywgc3RyaW5nPixcbiAgICBycGNVcmw6IHN0cmluZyxcbiAgICBhcGlLZXk/OiBzdHJpbmdcbiAgKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICAgIGNvbnN0IGVuZHBvaW50ID0gYXBpS2V5ID8gYCR7cnBjVXJsfSR7YXBpS2V5fWAgOiBycGNVcmw7XG4gICAgY29uc3QgeyBtb2R1bGUsIGFjdGlvbiwgYWRkcmVzcywgY29udHJhY3RhZGRyZXNzLCB0YWcgfSA9IHF1ZXJ5O1xuXG4gICAgbGV0IG1ldGhvZDogc3RyaW5nO1xuICAgIGxldCBwYXJhbXM6IHVua25vd25bXTtcblxuICAgIGlmIChtb2R1bGUgPT09ICdhY2NvdW50JyAmJiBhY3Rpb24gPT09ICdiYWxhbmNlJykge1xuICAgICAgcmV0dXJuIHsgcmVzdWx0OiAnMCcgfTtcbiAgICB9IGVsc2UgaWYgKG1vZHVsZSA9PT0gJ2FjY291bnQnICYmIGFjdGlvbiA9PT0gJ3Rva2VuYmFsYW5jZScpIHtcbiAgICAgIGNvbnN0IHBhZGRlZEFkZHIgPSAoYWRkcmVzcyA/PyAnJykucmVwbGFjZSgvXjB4LywgJycpLnBhZFN0YXJ0KDY0LCAnMCcpO1xuICAgICAgbWV0aG9kID0gJ2V0aF9jYWxsJztcbiAgICAgIHBhcmFtcyA9IFt7IHRvOiBjb250cmFjdGFkZHJlc3MsIGRhdGE6ICcweDcwYTA4MjMxJyArIHBhZGRlZEFkZHIgfSwgdGFnID8/ICdsYXRlc3QnXTtcbiAgICB9IGVsc2UgaWYgKG1vZHVsZSA9PT0gJ2FjY291bnQnICYmIGFjdGlvbiA9PT0gJ3R4bGlzdCcpIHtcbiAgICAgIG1ldGhvZCA9ICdldGhfZ2V0VHJhbnNhY3Rpb25Db3VudCc7XG4gICAgICBwYXJhbXMgPSBbYWRkcmVzcywgJ2xhdGVzdCddO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHF1ZXJ5VGVtcG9ScGM6IHVuc3VwcG9ydGVkIG1vZHVsZT0ke21vZHVsZX0gYWN0aW9uPSR7YWN0aW9ufWApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKGVuZHBvaW50LCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBqc29ucnBjOiAnMi4wJywgbWV0aG9kLCBwYXJhbXMsIGlkOiAxIH0pLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXMub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHJlYWNoIFRlbXBvIFJQQyBlbmRwb2ludCAoSFRUUCAke3Jlcy5zdGF0dXN9KWApO1xuICAgIH1cblxuICAgIGNvbnN0IGJvZHkgPSAoYXdhaXQgcmVzLmpzb24oKSkgYXMgeyByZXN1bHQ/OiB1bmtub3duOyBlcnJvcj86IHsgbWVzc2FnZTogc3RyaW5nIH0gfTtcbiAgICBpZiAoYm9keS5lcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW1wbyBSUEMgZXJyb3I6ICR7Ym9keS5lcnJvci5tZXNzYWdlfWApO1xuICAgIH1cblxuICAgIGlmIChtb2R1bGUgPT09ICdhY2NvdW50JyAmJiBhY3Rpb24gPT09ICd0eGxpc3QnKSB7XG4gICAgICByZXR1cm4geyBub25jZTogcGFyc2VJbnQoYm9keS5yZXN1bHQgYXMgc3RyaW5nLCAxNikgfTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHsgcmVzdWx0OiBCaWdJbnQoYm9keS5yZXN1bHQgYXMgc3RyaW5nKS50b1N0cmluZygpIH07XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4geyByZXN1bHQ6ICcwJyB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTaGFyZWQgaGVscGVyOiBxdWVyaWVzIHRoZSB0b2tlbiBiYWxhbmNlLCBjb21wdXRlcyBzd2VlcCBhbW91bnQsIGFuZCBidWlsZHNcbiAgICogYW4gdW5zaWduZWQgVElQLTIwIHRyYW5zZmVyIHRyYW5zYWN0aW9uLiBVc2VkIGJ5IGJvdGggcmVjb3ZlcnkgcGF0aHMuXG4gICAqXG4gICAqIC0gdG9rZW5Db250cmFjdEFkZHJlc3M6IHRoZSB0b2tlbiB0byBzd2VlcCAoZGVmYXVsdHMgdG8gcGF0aFVTRClcbiAgICogLSBmZWVUb2tlbjogYWx3YXlzIHBhdGhVU0RcbiAgICogLSBJZiBzd2VlcGluZyBwYXRoVVNEIGl0c2VsZiwgcmVzZXJ2ZXMgZ2FzTGltaXQgw5cgbWF4RmVlUGVyR2FzIC8gMTBeMTIgcGF0aFVTRCB1bml0cyBmb3IgZmVlcy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYnVpbGRUZW1wb1N3ZWVwVHgoXG4gICAgd2FsbGV0QWRkcmVzczogc3RyaW5nLFxuICAgIHBhcmFtczogUmVjb3Zlck9wdGlvbnNcbiAgKTogUHJvbWlzZTx7IHR4OiBUaXAyMFRyYW5zYWN0aW9uOyBub25jZTogbnVtYmVyOyBzd2VlcEFtb3VudDogYmlnaW50OyBnYXNNYXJnaW5Vbml0czogYmlnaW50IH0+IHtcbiAgICBpZiAoIXBhcmFtcy50b2tlbkNvbnRyYWN0QWRkcmVzcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0b2tlbkNvbnRyYWN0QWRkcmVzcyBpcyByZXF1aXJlZCBmb3Igc3dlZXAnKTtcbiAgICB9XG4gICAgY29uc3QgdG9rZW5BZGRyZXNzID0gcGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzO1xuXG4gICAgY29uc3QgcGF0aFVzZFRva2VuTmFtZSA9IHRoaXMuZ2V0Q2hhaW4oKSA9PT0gTUFJTk5FVF9DT0lOID8gUEFUSF9VU0RfVE9LRU5fTUFJTk5FVCA6IFBBVEhfVVNEX1RPS0VOX1RFU1RORVQ7XG4gICAgY29uc3QgcGF0aFVzZEFkZHJlc3MgPSAoY29pbnMuZ2V0KHBhdGhVc2RUb2tlbk5hbWUpIGFzIHVua25vd24gYXMgeyBjb250cmFjdEFkZHJlc3M6IHN0cmluZyB9KS5jb250cmFjdEFkZHJlc3M7XG5cbiAgICBjb25zdCByYXdCYWxhbmNlID0gYXdhaXQgdGhpcy5xdWVyeUFkZHJlc3NUb2tlbkJhbGFuY2UodG9rZW5BZGRyZXNzLCB3YWxsZXRBZGRyZXNzLCBwYXJhbXMuYXBpS2V5KTtcbiAgICBjb25zdCBiYWxhbmNlID0gQmlnSW50KHJhd0JhbGFuY2UudG9TdHJpbmcoKSk7XG5cbiAgICBjb25zdCBpc1BhdGhVc2QgPSB0b2tlbkFkZHJlc3MudG9Mb3dlckNhc2UoKSA9PT0gcGF0aFVzZEFkZHJlc3MudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBnYXNMaW1pdEJpZyA9IEJpZ0ludChwYXJhbXMuZ2FzTGltaXQgPz8gNzAwXzAwMCk7XG4gICAgY29uc3QgbWF4RmVlUGVyR2FzQmlnID0gQmlnSW50KHBhcmFtcy5laXAxNTU5Py5tYXhGZWVQZXJHYXMgPz8gMjBfMDAwXzAwMF8wMDApO1xuICAgIC8vIDc1JSBidWZmZXIgb24gdG9wIG9mIGdhc0xpbWl0IMOXIG1heEZlZVBlckdhcyB0byBjb3ZlciBhY3R1YWwgb24tY2hhaW4gZ2FzIHZhcmlhbmNlXG4gICAgY29uc3QgZ2FzTWFyZ2luVW5pdHMgPSAoZ2FzTGltaXRCaWcgKiBtYXhGZWVQZXJHYXNCaWcgKiAxNzVuKSAvICgxMG4gKiogMTJuICogMTAwbik7XG4gICAgY29uc3Qgc3dlZXBBbW91bnQgPSBpc1BhdGhVc2QgPyBiYWxhbmNlIC0gZ2FzTWFyZ2luVW5pdHMgOiBiYWxhbmNlO1xuXG4gICAgaWYgKHN3ZWVwQW1vdW50IDw9IDBuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBJbnN1ZmZpY2llbnQgYmFsYW5jZSBpbiAke3Rva2VuQWRkcmVzc306ICR7YmFsYW5jZX0gdW5pdHMgKG1pbmltdW0gcmVxdWlyZWQ6ICR7XG4gICAgICAgICAgaXNQYXRoVXNkID8gZ2FzTWFyZ2luVW5pdHMgKyAxbiA6IDFuXG4gICAgICAgIH0pYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBzd2VlcEFtb3VudEh1bWFuID0gdGlwMjBVbml0c1RvQW1vdW50KHN3ZWVwQW1vdW50KTtcbiAgICBjb25zdCBub25jZSA9IGF3YWl0IHRoaXMuZ2V0QWRkcmVzc05vbmNlKHdhbGxldEFkZHJlc3MsIHBhcmFtcy5hcGlLZXkpO1xuXG4gICAgY29uc3QgdHhCdWlsZGVyID0gdGhpcy5nZXRUcmFuc2FjdGlvbkJ1aWxkZXIoKSBhcyB1bmtub3duIGFzIFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgIHR4QnVpbGRlclxuICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiB0b2tlbkFkZHJlc3MsIHRvOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiwgYW1vdW50OiBzd2VlcEFtb3VudEh1bWFuIH0pXG4gICAgICAuZmVlVG9rZW4ocGF0aFVzZEFkZHJlc3MpXG4gICAgICAubm9uY2Uobm9uY2UpXG4gICAgICAuZ2FzKGdhc0xpbWl0QmlnKVxuICAgICAgLm1heEZlZVBlckdhcyhtYXhGZWVQZXJHYXNCaWcpXG4gICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoQmlnSW50KHBhcmFtcy5laXAxNTU5Py5tYXhQcmlvcml0eUZlZVBlckdhcyA/PyAxMF8wMDBfMDAwXzAwMCkpO1xuXG4gICAgY29uc3QgdHggPSAoYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgcmV0dXJuIHsgdHgsIG5vbmNlLCBzd2VlcEFtb3VudCwgZ2FzTWFyZ2luVW5pdHMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZXMgdGhlIGJhc2UtY2xhc3MgcmVjb3ZlclRTUyB0byB1c2UgVElQLTIwIHRyYW5zYWN0aW9ucyBpbnN0ZWFkIG9mIHN0YW5kYXJkIEVUSC5cbiAgICpcbiAgICogVHdvIHBhdGhzOlxuICAgKiAgIC0gVW5zaWduZWQgc3dlZXAgKHBsYWluIHB1YmxpYyBrZXkgc2hhcmVzKTogZGVsZWdhdGVzIHRvIGJ1aWxkVW5zaWduZWRTd2VlcFR4blRTU1xuICAgKiAgIC0gU2lnbmVkIHN3ZWVwIChlbmNyeXB0ZWQga2V5cyArIHBhc3NwaHJhc2UpOiBidWlsZHMgYW5kIHNpZ25zIGEgVElQLTIwIHR4IHZpYSBNUENcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWNvdmVyVFNTKFxuICAgIHBhcmFtczogUmVjb3Zlck9wdGlvbnNcbiAgKTogUHJvbWlzZTxSZWNvdmVyeUluZm8gfCBPZmZsaW5lVmF1bHRUeEluZm8gfCBVbnNpZ25lZFN3ZWVwVHhNUEN2Mj4ge1xuICAgIHRoaXMudmFsaWRhdGVSZWNvdmVyeVBhcmFtcyhwYXJhbXMpO1xuICAgIGNvbnN0IHVzZXJLZXkgPSBwYXJhbXMudXNlcktleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIGNvbnN0IGJhY2t1cEtleSA9IHBhcmFtcy5iYWNrdXBLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcblxuICAgIGlmIChnZXRJc1Vuc2lnbmVkU3dlZXAoeyB1c2VyS2V5LCBiYWNrdXBLZXksIGlzVHNzOiBwYXJhbXMuaXNUc3MgfSkpIHtcbiAgICAgIHJldHVybiB0aGlzLmJ1aWxkVW5zaWduZWRTd2VlcFR4blRTUyhwYXJhbXMpO1xuICAgIH1cblxuICAgIC8vIFNpZ25lZCBzd2VlcDogZGVjcnlwdCBNUEMgdjIga2V5IHNoYXJlc1xuICAgIGNvbnN0IHsgdXNlcktleVNoYXJlLCBiYWNrdXBLZXlTaGFyZSwgY29tbW9uS2V5Q2hhaW4gfSA9IGF3YWl0IEVDRFNBVXRpbHMuZ2V0TXBjVjJSZWNvdmVyeUtleVNoYXJlcyhcbiAgICAgIHVzZXJLZXksXG4gICAgICBiYWNrdXBLZXksXG4gICAgICBwYXJhbXMud2FsbGV0UGFzc3BocmFzZVxuICAgICk7XG5cbiAgICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcbiAgICBjb25zdCBkZXJpdmVkQ29tbW9uS2V5Q2hhaW4gPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChjb21tb25LZXlDaGFpbiwgJ20vMCcpO1xuICAgIGNvbnN0IGJhY2t1cEtleVBhaXIgPSBuZXcgS2V5UGFpcih7IHB1YjogZGVyaXZlZENvbW1vbktleUNoYWluLnNsaWNlKDAsIDY2KSB9KTtcbiAgICBjb25zdCBiYXNlQWRkcmVzcyA9IGJhY2t1cEtleVBhaXIuZ2V0QWRkcmVzcygpO1xuXG4gICAgY29uc3QgeyB0eDogdW5zaWduZWRUeCB9ID0gYXdhaXQgdGhpcy5idWlsZFRlbXBvU3dlZXBUeChiYXNlQWRkcmVzcywgcGFyYW1zKTtcbiAgICBjb25zdCBzZXJpYWxpemVkSGV4ID0gYXdhaXQgdW5zaWduZWRUeC5zZXJpYWxpemUoKTtcblxuICAgIC8vIEhhc2ggdGhlIHVuc2lnbmVkIDB4NzYgdHgg4oCUIG1hdGNoZXMgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIncyBvd24gc2lnbmluZyBsb2dpY1xuICAgIGNvbnN0IG1zZ0hhc2hIZXggPSBldGhlcnMudXRpbHMua2VjY2FrMjU2KGV0aGVycy51dGlscy5hcnJheWlmeShzZXJpYWxpemVkSGV4KSk7XG4gICAgY29uc3QgbWVzc2FnZUhhc2ggPSBCdWZmZXIuZnJvbShtc2dIYXNoSGV4LnJlcGxhY2UoJzB4JywgJycpLCAnaGV4Jyk7XG5cbiAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBFQ0RTQVV0aWxzLnNpZ25SZWNvdmVyeU1wY1YyKG1lc3NhZ2VIYXNoLCB1c2VyS2V5U2hhcmUsIGJhY2t1cEtleVNoYXJlLCBjb21tb25LZXlDaGFpbik7XG5cbiAgICAvLyBFQ0RTQU1ldGhvZFR5cGVzLlNpZ25hdHVyZS5yL3MgYXJlIDY0LWNoYXIgaGV4IFdJVEhPVVQgMHggcHJlZml4XG4gICAgdW5zaWduZWRUeC5zZXRTaWduYXR1cmUoe1xuICAgICAgcjogYDB4JHtzaWduYXR1cmUucn1gLFxuICAgICAgczogYDB4JHtzaWduYXR1cmUuc31gLFxuICAgICAgeVBhcml0eTogc2lnbmF0dXJlLnJlY2lkLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc2lnbmVkSGV4ID0gYXdhaXQgdW5zaWduZWRUeC5zZXJpYWxpemUoKTtcbiAgICBjb25zdCB0eElkID0gZXRoZXJzLnV0aWxzLmtlY2NhazI1NihldGhlcnMudXRpbHMuYXJyYXlpZnkoc2lnbmVkSGV4KSk7XG4gICAgcmV0dXJuIHsgaWQ6IHR4SWQsIHR4OiBzaWduZWRIZXggfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYW4gdW5zaWduZWQgVElQLTIwIHN3ZWVwIHRyYW5zYWN0aW9uIGZvciB0aGUgb2ZmbGluZSB2YXVsdCAodW5zaWduZWQgc3dlZXAgcGF0aCkuXG4gICAqIENhbGxlZCBieSByZWNvdmVyVFNTIHdoZW4gcGxhaW4gcHVibGljIGtleSBzaGFyZXMgYXJlIHByb3ZpZGVkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGJ1aWxkVW5zaWduZWRTd2VlcFR4blRTUyhwYXJhbXM6IFJlY292ZXJPcHRpb25zKTogUHJvbWlzZTxPZmZsaW5lVmF1bHRUeEluZm8gfCBVbnNpZ25lZFN3ZWVwVHhNUEN2Mj4ge1xuICAgIGNvbnN0IGJhY2t1cEtleSA9IHBhcmFtcy5iYWNrdXBLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9IHBhcmFtcy5kZXJpdmF0aW9uU2VlZCA/IGdldERlcml2YXRpb25QYXRoKHBhcmFtcy5kZXJpdmF0aW9uU2VlZCkgOiAnbS8wJztcbiAgICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcbiAgICBjb25zdCBkZXJpdmVkQ29tbW9uS2V5Q2hhaW4gPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChiYWNrdXBLZXksIGRlcml2YXRpb25QYXRoKTtcbiAgICBjb25zdCBiYWNrdXBLZXlQYWlyID0gbmV3IEtleVBhaXIoeyBwdWI6IGRlcml2ZWRDb21tb25LZXlDaGFpbi5zbGljZSgwLCA2NikgfSk7XG4gICAgY29uc3QgYmFzZUFkZHJlc3MgPSBiYWNrdXBLZXlQYWlyLmdldEFkZHJlc3MoKTtcblxuICAgIGNvbnN0IHsgdHgsIG5vbmNlLCBzd2VlcEFtb3VudCwgZ2FzTWFyZ2luVW5pdHMgfSA9IGF3YWl0IHRoaXMuYnVpbGRUZW1wb1N3ZWVwVHgoYmFzZUFkZHJlc3MsIHBhcmFtcyk7XG4gICAgY29uc3Qgc2VyaWFsaXplZEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeEhleCA9IHNlcmlhbGl6ZWRIZXgucmVwbGFjZSgnMHgnLCAnJyk7XG4gICAgY29uc3Qgc2lnbmFibGVIZXggPSBldGhlcnMudXRpbHMua2VjY2FrMjU2KGV0aGVycy51dGlscy5hcnJheWlmeShzZXJpYWxpemVkSGV4KSkucmVwbGFjZSgnMHgnLCAnJyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHhSZXF1ZXN0czogW1xuICAgICAgICB7XG4gICAgICAgICAgd2FsbGV0Q29pbjogdGhpcy5nZXRDaGFpbigpLFxuICAgICAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgICAgICAgc2VyaWFsaXplZFR4SGV4LFxuICAgICAgICAgICAgICAgIHNpZ25hYmxlSGV4LFxuICAgICAgICAgICAgICAgIGRlcml2YXRpb25QYXRoLFxuICAgICAgICAgICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICAgICAgICAgIGZlZTogTnVtYmVyKGdhc01hcmdpblVuaXRzKSxcbiAgICAgICAgICAgICAgICAgIGZlZVN0cmluZzogdGlwMjBVbml0c1RvQW1vdW50KGdhc01hcmdpblVuaXRzKSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBhcnNlZFR4OiB7XG4gICAgICAgICAgICAgICAgICBzcGVuZEFtb3VudDogdGlwMjBVbml0c1RvQW1vdW50KHN3ZWVwQW1vdW50KSxcbiAgICAgICAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgIGNvaW5OYW1lOiB0aGlzLmdldENoYWluKCksXG4gICAgICAgICAgICAgICAgICAgICAgYWRkcmVzczogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgdmFsdWVTdHJpbmc6IHRpcDIwVW5pdHNUb0Ftb3VudChzd2VlcEFtb3VudCksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY29pblNwZWNpZmljOiB7IGNvbW1vbktleUNoYWluOiBiYWNrdXBLZXkgfSxcbiAgICAgICAgICAgICAgICBlaXAxNTU5OiBwYXJhbXMuZWlwMTU1OSxcbiAgICAgICAgICAgICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczogcGFyYW1zLnJlcGxheVByb3RlY3Rpb25PcHRpb25zLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBub25jZSxcbiAgICAgICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdHJhbnNhY3Rpb24gYnVpbGRlciBmb3IgVGVtcG8uXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0VHJhbnNhY3Rpb25CdWlsZGVyKGNvbW1vbj86IEV0aExpa2VDb21tb24uZGVmYXVsdCk6IFRyYW5zYWN0aW9uQnVpbGRlciB7XG4gICAgcmV0dXJuIG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihjb2lucy5nZXQodGhpcy5nZXRCYXNlQ2hhaW4oKSkpIGFzIHVua25vd24gYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICB9XG59XG4iXX0=