@bitgo-beta/sdk-coin-icp 1.0.1-beta.82 → 1.0.1-beta.820

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 (67) hide show
  1. package/dist/resources/messageCompiled.d.ts +797 -0
  2. package/dist/resources/messageCompiled.js +1859 -0
  3. package/dist/src/icp.d.ts +55 -2
  4. package/dist/src/icp.d.ts.map +1 -1
  5. package/dist/src/icp.js +300 -9
  6. package/dist/src/lib/icpAgent.d.ts +36 -0
  7. package/dist/src/lib/icpAgent.d.ts.map +1 -0
  8. package/dist/src/lib/icpAgent.js +90 -0
  9. package/dist/src/lib/iface.d.ts +191 -0
  10. package/dist/src/lib/iface.d.ts.map +1 -0
  11. package/dist/src/lib/iface.js +44 -0
  12. package/dist/src/lib/index.d.ts +4 -0
  13. package/dist/src/lib/index.d.ts.map +1 -1
  14. package/dist/src/lib/index.js +12 -2
  15. package/dist/src/lib/signedTransactionBuilder.d.ts +9 -0
  16. package/dist/src/lib/signedTransactionBuilder.d.ts.map +1 -0
  17. package/dist/src/lib/signedTransactionBuilder.js +64 -0
  18. package/dist/src/lib/transaction.d.ts +54 -0
  19. package/dist/src/lib/transaction.d.ts.map +1 -0
  20. package/dist/src/lib/transaction.js +255 -0
  21. package/dist/src/lib/transactionBuilder.d.ts +58 -28
  22. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  23. package/dist/src/lib/transactionBuilder.js +127 -40
  24. package/dist/src/lib/transactionBuilderFactory.d.ts +15 -14
  25. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
  26. package/dist/src/lib/transactionBuilderFactory.js +43 -27
  27. package/dist/src/lib/transferBuilder.d.ts +7 -24
  28. package/dist/src/lib/transferBuilder.d.ts.map +1 -1
  29. package/dist/src/lib/transferBuilder.js +88 -43
  30. package/dist/src/lib/unsignedTransactionBuilder.d.ts +13 -0
  31. package/dist/src/lib/unsignedTransactionBuilder.d.ts.map +1 -0
  32. package/dist/src/lib/unsignedTransactionBuilder.js +90 -0
  33. package/dist/src/lib/utils.d.ts +285 -7
  34. package/dist/src/lib/utils.d.ts.map +1 -1
  35. package/dist/src/lib/utils.js +607 -52
  36. package/dist/src/ticp.d.ts +0 -4
  37. package/dist/src/ticp.d.ts.map +1 -1
  38. package/dist/src/ticp.js +1 -7
  39. package/dist/test/resources/icp.d.ts +268 -0
  40. package/dist/test/resources/icp.d.ts.map +1 -0
  41. package/dist/test/resources/icp.js +377 -0
  42. package/dist/test/unit/getBuilderFactory.d.ts +3 -0
  43. package/dist/test/unit/getBuilderFactory.d.ts.map +1 -0
  44. package/dist/test/unit/getBuilderFactory.js +10 -0
  45. package/dist/test/unit/icp.d.ts +2 -0
  46. package/dist/test/unit/icp.d.ts.map +1 -0
  47. package/dist/test/unit/icp.js +246 -0
  48. package/dist/test/unit/keyPair.d.ts +2 -0
  49. package/dist/test/unit/keyPair.d.ts.map +1 -0
  50. package/dist/test/unit/keyPair.js +107 -0
  51. package/dist/test/unit/transaction.d.ts +2 -0
  52. package/dist/test/unit/transaction.d.ts.map +1 -0
  53. package/dist/test/unit/transaction.js +109 -0
  54. package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts +2 -0
  55. package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts.map +1 -0
  56. package/dist/test/unit/transactionBuilder/transactionBuilder.js +274 -0
  57. package/dist/test/unit/transactionBuilder/transactionRecover.d.ts +2 -0
  58. package/dist/test/unit/transactionBuilder/transactionRecover.d.ts.map +1 -0
  59. package/dist/test/unit/transactionBuilder/transactionRecover.js +188 -0
  60. package/dist/test/unit/utils.d.ts +2 -0
  61. package/dist/test/unit/utils.d.ts.map +1 -0
  62. package/dist/test/unit/utils.js +206 -0
  63. package/dist/tsconfig.tsbuildinfo +1 -0
  64. package/package.json +23 -12
  65. package/.eslintignore +0 -4
  66. package/.mocharc.yml +0 -8
  67. package/CHANGELOG.md +0 -44
@@ -37,44 +37,153 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.Utils = void 0;
40
- const secp256k1_1 = require("@noble/curves/secp256k1");
40
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
41
41
  const principal_1 = require("@dfinity/principal");
42
42
  const agent = __importStar(require("@dfinity/agent"));
43
43
  const crypto_1 = __importDefault(require("crypto"));
44
44
  const crc_32_1 = __importDefault(require("crc-32"));
45
+ const iface_1 = require("./iface");
45
46
  const keyPair_1 = require("./keyPair");
47
+ const messageCompiled = require('../../resources/messageCompiled');
48
+ const { encode, decode, Encoder } = require('cbor-x/index-no-eval'); // The "cbor-x" library is used here because it supports modern features like BigInt. do not replace it with "cbor as "cbor" is not compatible with Rust's serde_cbor when handling big numbers.
49
+ const js_sha256_1 = __importDefault(require("js-sha256"));
50
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
51
+ const secp256k1_1 = require("@noble/curves/secp256k1");
52
+ //custom encoder that avoids tagging
53
+ const encoder = new Encoder({
54
+ structuredClone: false,
55
+ useToJSON: false,
56
+ mapsAsObjects: false,
57
+ largeBigIntToFloat: false,
58
+ });
46
59
  class Utils {
60
+ constructor() {
61
+ this.signPayload = (privateKey, payloadHex) => {
62
+ const privateKeyBytes = Buffer.from(privateKey, 'hex');
63
+ const payloadHash = crypto_1.default.createHash('sha256').update(Buffer.from(payloadHex, 'hex')).digest('hex');
64
+ const signature = secp256k1_1.secp256k1.sign(payloadHash, privateKeyBytes);
65
+ const r = Buffer.from(signature.r.toString(16).padStart(64, '0'), 'hex');
66
+ const s = Buffer.from(signature.s.toString(16).padStart(64, '0'), 'hex');
67
+ return Buffer.concat([r, s]).toString('hex');
68
+ };
69
+ }
70
+ /** @inheritdoc */
71
+ isValidSignature(signature) {
72
+ throw new sdk_core_1.MethodNotImplementedError();
73
+ }
74
+ /**
75
+ * gets the fee data of this transaction.
76
+ */
77
+ feeData() {
78
+ return '-10000'; // fee is static for ICP transactions as per ICP documentation
79
+ }
80
+ /**
81
+ * Checks if the provided address is a valid ICP address.
82
+ *
83
+ * @param {string} address - The address to validate.
84
+ * @returns {boolean} - Returns `true` if the address is valid, otherwise `false`.
85
+ */
47
86
  isValidAddress(address) {
48
- throw new Error('Method not implemented.');
87
+ const rootAddress = this.validateMemoAndReturnRootAddress(address);
88
+ return rootAddress !== undefined && this.isValidHash(rootAddress);
49
89
  }
50
- isValidTransactionId(txId) {
51
- throw new Error('Method not implemented.');
90
+ /**
91
+ * Validates the memo ID in the address and returns the root address.
92
+ *
93
+ * @param {string} address - The address to validate and extract the root address from.
94
+ * @returns {string | undefined} - The root address if valid, otherwise `undefined`.
95
+ */
96
+ validateMemoAndReturnRootAddress(address) {
97
+ if (!address) {
98
+ return undefined;
99
+ }
100
+ const [rootAddress, memoId] = address.split('?memoId=');
101
+ if (memoId && this.validateMemo(BigInt(memoId))) {
102
+ return rootAddress;
103
+ }
104
+ return address;
52
105
  }
106
+ /**
107
+ * Checks if the provided hex string is a valid public key.
108
+ *
109
+ * A valid public key can be either compressed or uncompressed:
110
+ * - Compressed public keys are 33 bytes long and start with either 0x02 or 0x03.
111
+ * - Uncompressed public keys are 65 bytes long and start with 0x04.
112
+ *
113
+ * @param {string} hexStr - The hex string representation of the public key to validate.
114
+ * @returns {boolean} - Returns `true` if the hex string is a valid public key, otherwise `false`.
115
+ */
53
116
  isValidPublicKey(hexStr) {
54
- if (!this.isValidHex(hexStr)) {
55
- return false;
56
- }
57
- if (!this.isValidLength(hexStr)) {
117
+ if (!this.isValidHex(hexStr) || !this.isValidLength(hexStr)) {
58
118
  return false;
59
119
  }
60
120
  const pubKeyBytes = this.hexToBytes(hexStr);
61
121
  const firstByte = pubKeyBytes[0];
62
- return ((pubKeyBytes.length === 33 && (firstByte === 2 || firstByte === 3)) ||
63
- (pubKeyBytes.length === 65 && firstByte === 4));
122
+ const validCompressed = pubKeyBytes.length === 33 && (firstByte === 2 || firstByte === 3);
123
+ const validUncompressed = pubKeyBytes.length === 65 && firstByte === 4;
124
+ return validCompressed || validUncompressed;
125
+ }
126
+ /**
127
+ * Encodes a value into CBOR format and returns it as a hex string.
128
+ *
129
+ * @param {unknown} value - The value to encode.
130
+ * @returns {string} - The CBOR encoded value as a hex string.
131
+ */
132
+ cborEncode(value) {
133
+ if (value === undefined) {
134
+ throw new Error('Value to encode cannot be undefined.');
135
+ }
136
+ const cborData = encode(value);
137
+ return Buffer.from(cborData).toString('hex');
64
138
  }
139
+ /**
140
+ * Checks if the length of the given hexadecimal string is valid.
141
+ * A valid length is either 66 characters (33 bytes) or 130 characters (65 bytes).
142
+ *
143
+ * @param {string} hexStr - The hexadecimal string to check.
144
+ * @returns {boolean} - Returns `true` if the length is valid, otherwise `false`.
145
+ */
65
146
  isValidLength(hexStr) {
66
147
  return hexStr.length / 2 === 33 || hexStr.length / 2 === 65;
67
148
  }
149
+ /**
150
+ * Checks if the provided string is a valid hexadecimal string.
151
+ *
152
+ * A valid hexadecimal string consists of pairs of hexadecimal digits (0-9, a-f, A-F).
153
+ *
154
+ * @param hexStr - The string to be validated as a hexadecimal string.
155
+ * @returns True if the string is a valid hexadecimal string, false otherwise.
156
+ */
68
157
  isValidHex(hexStr) {
69
158
  return /^([0-9a-fA-F]{2})+$/.test(hexStr);
70
159
  }
160
+ /**
161
+ * Converts a hexadecimal string to a Uint8Array.
162
+ *
163
+ * @param {string} hex - The hexadecimal string to convert.
164
+ * @returns {Uint8Array} The resulting byte array.
165
+ */
71
166
  hexToBytes(hex) {
72
- return new Uint8Array(Buffer.from(hex, 'hex'));
167
+ const bytes = new Uint8Array(hex.length / 2);
168
+ for (let i = 0; i < hex.length; i += 2) {
169
+ bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
170
+ }
171
+ return bytes;
73
172
  }
74
173
  /** @inheritdoc */
75
174
  isValidPrivateKey(key) {
76
175
  return this.isValidKey(key);
77
176
  }
177
+ /**
178
+ * Validates whether the provided key is a valid ICP private key.
179
+ *
180
+ * This function attempts to create a new instance of `IcpKeyPair` using the provided key.
181
+ * If the key is valid, the function returns `true`. If the key is invalid, an error is thrown,
182
+ * and the function returns `false`.
183
+ *
184
+ * @param {string} key - The private key to validate.
185
+ * @returns {boolean} - `true` if the key is valid, `false` otherwise.
186
+ */
78
187
  isValidKey(key) {
79
188
  try {
80
189
  new keyPair_1.KeyPair({ prv: key });
@@ -84,23 +193,13 @@ class Utils {
84
193
  return false;
85
194
  }
86
195
  }
87
- isValidSignature(signature) {
88
- throw new Error('Method not implemented.');
89
- }
90
- isValidBlockId(hash) {
91
- throw new Error('Method not implemented.');
92
- }
93
- getHeaders() {
94
- return {
95
- 'Content-Type': 'application/json',
96
- };
97
- }
98
- getNetworkIdentifier() {
99
- return {
100
- blockchain: 'Internet Computer',
101
- network: '00000000000000020101',
102
- };
103
- }
196
+ /**
197
+ * Compresses an uncompressed public key.
198
+ *
199
+ * @param {string} uncompressedKey - The uncompressed public key in hexadecimal format.
200
+ * @returns {string} - The compressed public key in hexadecimal format.
201
+ * @throws {Error} - If the input key is not a valid uncompressed public key.
202
+ */
104
203
  compressPublicKey(uncompressedKey) {
105
204
  if (uncompressedKey.startsWith('02') || uncompressedKey.startsWith('03')) {
106
205
  return uncompressedKey;
@@ -112,59 +211,515 @@ class Utils {
112
211
  const yHex = uncompressedKey.slice(66);
113
212
  const y = BigInt(`0x${yHex}`);
114
213
  const prefix = y % 2n === 0n ? '02' : '03';
115
- return prefix + xHex;
214
+ return `${prefix}${xHex}`;
215
+ }
216
+ /**
217
+ * Converts a public key from its hexadecimal string representation to DER format.
218
+ *
219
+ * @param {string} publicKeyHex - The public key in hexadecimal string format.
220
+ * @returns The public key in DER format as a Uint8Array.
221
+ */
222
+ getPublicKeyInDERFormat(publicKeyHex) {
223
+ const publicKeyBuffer = Buffer.from(publicKeyHex, 'hex');
224
+ const ellipticKey = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBuffer.toString('hex'));
225
+ const uncompressedPublicKeyHex = ellipticKey.toHex(false);
226
+ const derEncodedKey = agent.wrapDER(Buffer.from(uncompressedPublicKeyHex, 'hex'), agent.SECP256K1_OID);
227
+ return derEncodedKey;
116
228
  }
117
- getCurveType() {
118
- return 'secp256k1';
229
+ /**
230
+ * Converts a public key in hexadecimal format to a Dfinity Principal ID.
231
+ *
232
+ * @param {string} publicKeyHex - The public key in hexadecimal format.
233
+ * @returns The corresponding Dfinity Principal ID.
234
+ */
235
+ getPrincipalIdFromPublicKey(publicKeyHex) {
236
+ const derEncodedKey = this.getPublicKeyInDERFormat(publicKeyHex);
237
+ const principalId = principal_1.Principal.selfAuthenticating(Buffer.from(derEncodedKey));
238
+ return principalId;
119
239
  }
240
+ /**
241
+ * Derives a DfinityPrincipal from a given public key in hexadecimal format.
242
+ *
243
+ * @param {string} publicKeyHex - The public key in hexadecimal format.
244
+ * @returns The derived DfinityPrincipal.
245
+ * @throws Will throw an error if the principal cannot be derived from the public key.
246
+ */
120
247
  derivePrincipalFromPublicKey(publicKeyHex) {
121
248
  try {
122
- const point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyHex);
123
- const uncompressedPublicKeyHex = point.toHex(false);
124
- const derEncodedKey = agent.wrapDER(Buffer.from(uncompressedPublicKeyHex, 'hex'), agent.SECP256K1_OID);
249
+ const derEncodedKey = this.getPublicKeyInDERFormat(publicKeyHex);
125
250
  const principalId = principal_1.Principal.selfAuthenticating(Buffer.from(derEncodedKey));
126
251
  const principal = principal_1.Principal.fromUint8Array(principalId.toUint8Array());
127
252
  return principal;
128
253
  }
129
254
  catch (error) {
130
- throw new Error(`Failed to process the public key: ${error.message}`);
255
+ throw new Error(`Failed to derive principal from public key: ${error.message}`);
131
256
  }
132
257
  }
258
+ /**
259
+ * Converts a DfinityPrincipal and an optional subAccount to a string representation of an account ID.
260
+ *
261
+ * @param {DfinityPrincipal} principal - The principal to convert.
262
+ * @param {Uint8Array} [subAccount=new Uint8Array(32)] - An optional sub-account, defaults to a 32-byte array of zeros.
263
+ * @returns {string} The hexadecimal string representation of the account ID.
264
+ */
133
265
  fromPrincipal(principal, subAccount = new Uint8Array(32)) {
134
- const ACCOUNT_ID_PREFIX = new Uint8Array([0x0a, ...Buffer.from('account-id')]);
135
- const principalBytes = principal.toUint8Array();
136
- const combinedBytes = new Uint8Array(ACCOUNT_ID_PREFIX.length + principalBytes.length + subAccount.length);
137
- combinedBytes.set(ACCOUNT_ID_PREFIX, 0);
138
- combinedBytes.set(principalBytes, ACCOUNT_ID_PREFIX.length);
139
- combinedBytes.set(subAccount, ACCOUNT_ID_PREFIX.length + principalBytes.length);
266
+ const principalBytes = Buffer.from(principal.toUint8Array().buffer);
267
+ return this.getAccountIdFromPrincipalBytes(this.getAccountIdPrefix(), principalBytes, subAccount);
268
+ }
269
+ getAccountIdFromPrincipalBytes(ACCOUNT_ID_PREFIX, principalBytes, subAccount) {
270
+ const combinedBytes = Buffer.concat([ACCOUNT_ID_PREFIX, principalBytes, subAccount]);
140
271
  const sha224Hash = crypto_1.default.createHash('sha224').update(combinedBytes).digest();
141
272
  const checksum = Buffer.alloc(4);
142
273
  checksum.writeUInt32BE(crc_32_1.default.buf(sha224Hash) >>> 0, 0);
143
274
  const accountIdBytes = Buffer.concat([checksum, sha224Hash]);
144
275
  return accountIdBytes.toString('hex');
145
276
  }
277
+ /**
278
+ * Retrieves the address associated with a given hex-encoded public key.
279
+ *
280
+ * @param {string} hexEncodedPublicKey - The public key in hex-encoded format.
281
+ * @returns {Promise<string>} A promise that resolves to the address derived from the provided public key.
282
+ * @throws {Error} Throws an error if the provided public key is not in a valid hex-encoded format.
283
+ */
146
284
  async getAddressFromPublicKey(hexEncodedPublicKey) {
147
- const isKeyValid = this.isValidPublicKey(hexEncodedPublicKey);
148
- if (!isKeyValid) {
149
- throw new Error('Public Key is not in a valid Hex Encoded Format');
285
+ if (!this.isValidPublicKey(hexEncodedPublicKey)) {
286
+ throw new Error('Invalid hex-encoded public key format.');
150
287
  }
151
288
  const compressedKey = this.compressPublicKey(hexEncodedPublicKey);
152
- const KeyPair = new keyPair_1.KeyPair({ pub: compressedKey });
153
- return KeyPair.getAddress();
289
+ const keyPair = new keyPair_1.KeyPair({ pub: compressedKey });
290
+ return keyPair.getAddress();
154
291
  }
292
+ /**
293
+ * Generates a new key pair. If a seed is provided, it will be used to generate the key pair.
294
+ *
295
+ * @param {Buffer} [seed] - Optional seed for key generation.
296
+ * @returns {KeyPair} - The generated key pair containing both public and private keys.
297
+ * @throws {Error} - If the private key is missing in the generated key pair.
298
+ */
155
299
  generateKeyPair(seed) {
156
300
  const keyPair = seed ? new keyPair_1.KeyPair({ seed }) : new keyPair_1.KeyPair();
157
- const keys = keyPair.getKeys();
158
- if (!keys.prv) {
159
- throw new Error('Missing prv in key generation.');
301
+ const { pub, prv } = keyPair.getKeys();
302
+ if (!prv) {
303
+ throw new Error('Private key is missing in the generated key pair.');
160
304
  }
305
+ return { pub, prv };
306
+ }
307
+ /**
308
+ * Validates the provided fee.
309
+ *
310
+ * @param {string} fee - The fee to validate.
311
+ * @throws {BuildTransactionError} - If the fee is zero or invalid.
312
+ */
313
+ validateFee(fee) {
314
+ const feeValue = new bignumber_js_1.default(fee);
315
+ if (feeValue.isZero()) {
316
+ throw new sdk_core_1.BuildTransactionError('Fee cannot be zero');
317
+ }
318
+ return true;
319
+ }
320
+ /** @inheritdoc */
321
+ validateValue(value) {
322
+ if (value.isLessThanOrEqualTo(0)) {
323
+ throw new sdk_core_1.BuildTransactionError('amount cannot be less than or equal to zero');
324
+ }
325
+ return true;
326
+ }
327
+ /**
328
+ * Validates the provided memo.
329
+ *
330
+ * @param {number | BigInt} memo - The memo to validate.
331
+ * @returns {boolean} - Returns `true` if the memo is valid.
332
+ * @throws {BuildTransactionError} - If the memo is invalid.
333
+ */
334
+ validateMemo(memo) {
335
+ const memoNumber = Number(memo);
336
+ if (memoNumber < 0 || Number.isNaN(memoNumber)) {
337
+ throw new sdk_core_1.BuildTransactionError('Invalid memo');
338
+ }
339
+ return true;
340
+ }
341
+ validateExpireTime(expireTime) {
342
+ if (Number(expireTime) < Date.now() * 1000000) {
343
+ throw new sdk_core_1.BuildTransactionError('Invalid expiry time');
344
+ }
345
+ return true;
346
+ }
347
+ /**
348
+ * Validates the raw transaction data to ensure it has a valid format in the blockchain context.
349
+ *
350
+ * @param {IcpTransactionData} transactionData - The transaction data to validate.
351
+ * @throws {ParseTransactionError} If the transaction data is invalid.
352
+ */
353
+ validateRawTransaction(transactionData) {
354
+ if (!transactionData) {
355
+ throw new sdk_core_1.ParseTransactionError('Transaction data is missing.');
356
+ }
357
+ const { senderPublicKeyHex, senderAddress, receiverAddress } = transactionData;
358
+ if (senderPublicKeyHex && !this.isValidPublicKey(senderPublicKeyHex)) {
359
+ throw new sdk_core_1.ParseTransactionError('Sender public key is invalid.');
360
+ }
361
+ if (!this.isValidAddress(senderAddress)) {
362
+ throw new sdk_core_1.ParseTransactionError('Sender address is invalid.');
363
+ }
364
+ if (!this.isValidAddress(receiverAddress)) {
365
+ throw new sdk_core_1.ParseTransactionError('Receiver address is invalid.');
366
+ }
367
+ this.validateFee(transactionData.fee);
368
+ this.validateValue(new bignumber_js_1.default(transactionData.amount));
369
+ this.validateMemo(transactionData.memo);
370
+ this.validateExpireTime(transactionData.expiryTime);
371
+ }
372
+ /**
373
+ *
374
+ * @param {object} update
375
+ * @returns {Buffer}
376
+ */
377
+ generateHttpCanisterUpdateId(update) {
378
+ return this.HttpCanisterUpdateRepresentationIndependentHash(update);
379
+ }
380
+ /**
381
+ * Generates a representation-independent hash for an HTTP canister update.
382
+ *
383
+ * @param {HttpCanisterUpdate} update - The HTTP canister update object.
384
+ * @returns {Buffer} - The hash of the update object.
385
+ */
386
+ HttpCanisterUpdateRepresentationIndependentHash(update) {
387
+ const updateMap = {
388
+ request_type: iface_1.RequestType.CALL,
389
+ canister_id: update.canister_id,
390
+ method_name: update.method_name,
391
+ arg: update.arg,
392
+ ingress_expiry: update.ingress_expiry,
393
+ sender: update.sender,
394
+ };
395
+ return this.hashOfMap(updateMap);
396
+ }
397
+ /**
398
+ * Generates a SHA-256 hash for a given map object.
399
+ *
400
+ * @param {Record<string, unknown>} map - The map object to hash.
401
+ * @returns {Buffer} - The resulting hash as a Buffer.
402
+ */
403
+ hashOfMap(map) {
404
+ const hashes = [];
405
+ for (const key in map) {
406
+ hashes.push(this.hashKeyVal(key, map[key]));
407
+ }
408
+ hashes.sort((buf0, buf1) => buf0.compare(buf1));
409
+ return this.sha256(hashes);
410
+ }
411
+ /**
412
+ * Generates a hash for a key-value pair.
413
+ *
414
+ * @param {string} key - The key to hash.
415
+ * @param {string | Buffer | BigInt} val - The value to hash.
416
+ * @returns {Buffer} - The resulting hash as a Buffer.
417
+ */
418
+ hashKeyVal(key, val) {
419
+ const keyHash = this.hashString(key);
420
+ const valHash = this.hashVal(val);
421
+ return Buffer.concat([keyHash, valHash]);
422
+ }
423
+ /**
424
+ * Generates a SHA-256 hash for a given string.
425
+ *
426
+ * @param {string} value - The string to hash.
427
+ * @returns {Buffer} - The resulting hash as a Buffer.
428
+ */
429
+ hashString(value) {
430
+ return this.sha256([Buffer.from(value)]);
431
+ }
432
+ /**
433
+ * Generates a hash for a 64-bit unsigned integer.
434
+ *
435
+ * @param {bigint} n - The 64-bit unsigned integer to hash.
436
+ * @returns {Buffer} - The resulting hash as a Buffer.
437
+ */
438
+ hashU64(n) {
439
+ const buf = Buffer.allocUnsafe(10);
440
+ let i = 0;
441
+ while (true) {
442
+ const byte = Number(n & BigInt(0x7f));
443
+ n >>= BigInt(7);
444
+ if (n === BigInt(0)) {
445
+ buf[i] = byte;
446
+ break;
447
+ }
448
+ else {
449
+ buf[i] = byte | 0x80;
450
+ ++i;
451
+ }
452
+ }
453
+ return this.hashBytes(buf.subarray(0, i + 1));
454
+ }
455
+ /**
456
+ * Generates a SHA-256 hash for an array of elements.
457
+ *
458
+ * @param {Array<any>} elements - The array of elements to hash.
459
+ * @returns {Buffer} - The resulting hash as a Buffer.
460
+ */
461
+ hashArray(elements) {
462
+ return this.sha256(elements.map(this.hashVal));
463
+ }
464
+ /**
465
+ * Generates a hash for a given value.
466
+ *
467
+ * @param {string | Buffer | BigInt | number | Array<unknown>} val - The value to hash.
468
+ * @returns {Buffer} - The resulting hash as a Buffer.
469
+ * @throws {Error} - If the value type is unsupported.
470
+ */
471
+ hashVal(val) {
472
+ if (typeof val === 'string') {
473
+ return utils.hashString(val);
474
+ }
475
+ else if (Buffer.isBuffer(val) || val instanceof Uint8Array) {
476
+ return utils.hashBytes(val);
477
+ }
478
+ else if (typeof val === 'bigint' || typeof val === 'number') {
479
+ return utils.hashU64(BigInt(val));
480
+ }
481
+ else if (Array.isArray(val)) {
482
+ return utils.hashArray(val);
483
+ }
484
+ else {
485
+ throw new Error(`Unsupported value type for hashing: ${typeof val}`);
486
+ }
487
+ }
488
+ /**
489
+ * Computes the SHA-256 hash of the given buffer.
490
+ *
491
+ * @param value - The buffer to hash.
492
+ * @returns The SHA-256 hash of the input buffer.
493
+ */
494
+ hashBytes(value) {
495
+ return this.sha256([value]);
496
+ }
497
+ /**
498
+ * Computes the SHA-256 hash of the provided array of Buffer chunks.
499
+ *
500
+ * @param {Array<Buffer>} chunks - An array of Buffer objects to be hashed.
501
+ * @returns {Buffer} - The resulting SHA-256 hash as a Buffer.
502
+ */
503
+ sha256(chunks) {
504
+ const hasher = js_sha256_1.default.sha256.create();
505
+ chunks.forEach((chunk) => hasher.update(chunk));
506
+ return Buffer.from(hasher.arrayBuffer());
507
+ }
508
+ /**
509
+ * Converts a hexadecimal string to a Buffer.
510
+ *
511
+ * @param hex - The hexadecimal string to convert.
512
+ * @returns A Buffer containing the binary data represented by the hexadecimal string.
513
+ */
514
+ blobFromHex(hex) {
515
+ return Buffer.from(hex, 'hex');
516
+ }
517
+ /**
518
+ * Converts a binary blob (Buffer) to a hexadecimal string.
519
+ *
520
+ * @param {Buffer} blob - The binary data to be converted.
521
+ * @returns {string} The hexadecimal representation of the binary data.
522
+ */
523
+ blobToHex(blob) {
524
+ return blob.toString('hex');
525
+ }
526
+ /**
527
+ * Decodes a given CBOR-encoded buffer.
528
+ *
529
+ * @param buffer - The CBOR-encoded buffer to decode.
530
+ * @returns The decoded data.
531
+ */
532
+ cborDecode(buffer) {
533
+ const res = decode(buffer);
534
+ return res;
535
+ }
536
+ /**
537
+ * Generates a Buffer containing the domain IC request string.
538
+ *
539
+ * @returns {Buffer} A Buffer object initialized with the string '\x0Aic-request'.
540
+ */
541
+ getDomainICRequest() {
542
+ return Buffer.from('\x0Aic-request');
543
+ }
544
+ /**
545
+ * Combines the domain IC request buffer with the provided message ID buffer to create signature data.
546
+ *
547
+ * @param {Buffer} messageId - The buffer containing the message ID.
548
+ * @returns {Buffer} - The concatenated buffer containing the domain IC request and the message ID.
549
+ */
550
+ makeSignatureData(messageId) {
551
+ return Buffer.concat([this.getDomainICRequest(), messageId]);
552
+ }
553
+ /**
554
+ * Extracts the recipient information from the provided ICP transaction data.
555
+ *
556
+ * @param {IcpTransactionData} icpTransactionData - The ICP transaction data containing the receiver's address and amount.
557
+ * @returns {Recipient[]} An array containing a single recipient object with the receiver's address and amount.
558
+ */
559
+ getRecipients(icpTransactionData) {
161
560
  return {
162
- pub: keys.pub,
163
- prv: keys.prv,
561
+ address: icpTransactionData.receiverAddress,
562
+ amount: icpTransactionData.amount,
563
+ };
564
+ }
565
+ getTransactionSignature(signatureMap, update) {
566
+ return signatureMap.get(this.blobToHex(this.makeSignatureData(this.generateHttpCanisterUpdateId(update))));
567
+ }
568
+ getMetaData(memo, timestamp, ingressEnd) {
569
+ let currentTime = Date.now() * 1000000;
570
+ if (timestamp) {
571
+ currentTime = Number(timestamp);
572
+ }
573
+ let ingressStartTime, ingressEndTime;
574
+ if (ingressEnd) {
575
+ ingressEndTime = Number(ingressEnd);
576
+ ingressStartTime = ingressEndTime - iface_1.MAX_INGRESS_TTL; // 5 mins in nanoseconds
577
+ }
578
+ else {
579
+ ingressStartTime = currentTime;
580
+ ingressEndTime = ingressStartTime + iface_1.MAX_INGRESS_TTL; // 5 mins in nanoseconds
581
+ }
582
+ const metaData = {
583
+ created_at_time: currentTime,
584
+ ingress_start: ingressStartTime,
585
+ ingress_end: ingressEndTime,
586
+ memo: memo,
587
+ };
588
+ return { metaData, ingressEndTime };
589
+ }
590
+ convertSenderBlobToPrincipal(senderBlob) {
591
+ const MAX_LENGTH_IN_BYTES = 29;
592
+ if (senderBlob.length > MAX_LENGTH_IN_BYTES) {
593
+ throw new Error('Bytes too long for a valid Principal');
594
+ }
595
+ const principalBytes = new Uint8Array(MAX_LENGTH_IN_BYTES);
596
+ principalBytes.set(senderBlob.slice(0, senderBlob.length));
597
+ return principalBytes;
598
+ }
599
+ fromArgs(arg) {
600
+ const SendRequestMessage = messageCompiled.SendRequest;
601
+ const args = SendRequestMessage.decode(arg);
602
+ const transformedArgs = {
603
+ payment: { receiverGets: { e8s: Number(args.payment.receiverGets.e8s) } },
604
+ maxFee: { e8s: Number(args.maxFee.e8s) },
605
+ to: { hash: Buffer.from(args.to.hash) },
606
+ createdAtTime: { timestampNanos: (0, bignumber_js_1.default)(args.createdAtTime.timestampNanos.toString()).toNumber() },
607
+ memo: { memo: Number(args.memo.memo.toString()) },
164
608
  };
609
+ return transformedArgs;
610
+ }
611
+ async toArg(args) {
612
+ const SendRequestMessage = messageCompiled.SendRequest;
613
+ const errMsg = SendRequestMessage.verify(args);
614
+ if (errMsg)
615
+ throw new Error(errMsg);
616
+ const message = SendRequestMessage.create(args);
617
+ return SendRequestMessage.encode(message).finish();
618
+ }
619
+ getAccountIdPrefix() {
620
+ return Buffer.from([0x0a, ...Buffer.from('account-id')]);
621
+ }
622
+ /** @inheritdoc */
623
+ isValidBlockId(hash) {
624
+ // ICP block hashes are 64-character hexadecimal strings
625
+ return this.isValidHash(hash);
626
+ }
627
+ /**
628
+ * Returns whether or not the string is a valid ICP hash
629
+ *
630
+ * @param {string} hash - string to validate
631
+ * @returns {boolean}
632
+ */
633
+ isValidHash(hash) {
634
+ return typeof hash === 'string' && /^[0-9a-fA-F]{64}$/.test(hash);
635
+ }
636
+ /** @inheritdoc */
637
+ isValidTransactionId(txId) {
638
+ return this.isValidHash(txId);
639
+ }
640
+ getSignatures(payloadsData, senderPublicKey, senderPrivateKey) {
641
+ return payloadsData.payloads.map((payload) => ({
642
+ signing_payload: payload,
643
+ signature_type: payload.signature_type,
644
+ public_key: {
645
+ hex_bytes: senderPublicKey,
646
+ curve_type: iface_1.CurveType.SECP256K1,
647
+ },
648
+ hex_bytes: this.signPayload(senderPrivateKey, payload.hex_bytes),
649
+ }));
650
+ }
651
+ getTransactionId(unsignedTransaction, senderAddress, receiverAddress) {
652
+ try {
653
+ const decodedTxn = utils.cborDecode(utils.blobFromHex(unsignedTransaction));
654
+ const updates = decodedTxn.updates;
655
+ for (const [, update] of updates) {
656
+ const updateArgs = update.arg;
657
+ const sendArgs = utils.fromArgs(updateArgs);
658
+ const transactionHash = this.generateTransactionHash(sendArgs, senderAddress, receiverAddress);
659
+ return transactionHash;
660
+ }
661
+ throw new Error('No updates found in the unsigned transaction.');
662
+ }
663
+ catch (error) {
664
+ throw new Error(`Unable to compute transaction ID: ${error.message}`);
665
+ }
666
+ }
667
+ safeBigInt(value) {
668
+ if (typeof value === 'bigint') {
669
+ return value;
670
+ }
671
+ if (typeof value === 'number') {
672
+ const MAX_32BIT = 4294967295; // 2^32 - 1
673
+ const MIN_32BIT = -4294967296; // -(2^32)
674
+ const isOutside32BitRange = value > MAX_32BIT || value < MIN_32BIT;
675
+ return isOutside32BitRange ? BigInt(value) : value;
676
+ }
677
+ throw new Error(`Invalid type: expected a number or bigint, but received ${typeof value}`);
678
+ }
679
+ generateTransactionHash(sendArgs, senderAddress, receiverAddress) {
680
+ const senderAccount = this.accountIdentifier(senderAddress);
681
+ const receiverAccount = this.accountIdentifier(receiverAddress);
682
+ const transferFields = new Map([
683
+ [0, senderAccount],
684
+ [1, receiverAccount],
685
+ [2, new Map([[0, this.safeBigInt(sendArgs.payment.receiverGets.e8s)]])],
686
+ [3, new Map([[0, sendArgs.maxFee.e8s]])],
687
+ ]);
688
+ const operationMap = new Map([[2, transferFields]]);
689
+ const txnFields = new Map([
690
+ [0, operationMap],
691
+ [1, this.safeBigInt(sendArgs.memo.memo)],
692
+ [2, new Map([[0, BigInt(sendArgs.createdAtTime.timestampNanos)]])],
693
+ ]);
694
+ const processedTxn = this.getProcessedTransactionMap(txnFields);
695
+ const serializedTxn = encoder.encode(processedTxn);
696
+ return crypto_1.default.createHash('sha256').update(serializedTxn).digest('hex');
697
+ }
698
+ accountIdentifier(accountAddress) {
699
+ const bytes = Buffer.from(accountAddress, 'hex');
700
+ if (bytes.length === 32) {
701
+ return { hash: bytes.slice(4) };
702
+ }
703
+ throw new Error(`Invalid AccountIdentifier: 64 hex chars, got ${accountAddress.length}`);
704
+ }
705
+ getProcessedTransactionMap(txnMap) {
706
+ const operationMap = txnMap.get(0);
707
+ const transferMap = operationMap.get(2);
708
+ transferMap.set(0, this.serializeAccountIdentifier(transferMap.get(0)));
709
+ transferMap.set(1, this.serializeAccountIdentifier(transferMap.get(1)));
710
+ return txnMap;
711
+ }
712
+ serializeAccountIdentifier(accountHash) {
713
+ if (accountHash && accountHash.hash) {
714
+ const hashBuffer = accountHash.hash;
715
+ const checksum = Buffer.alloc(4);
716
+ checksum.writeUInt32BE(crc_32_1.default.buf(hashBuffer) >>> 0, 0);
717
+ return Buffer.concat([checksum, hashBuffer]).toString('hex').toLowerCase();
718
+ }
719
+ throw new Error('Invalid accountHash format');
165
720
  }
166
721
  }
167
722
  exports.Utils = Utils;
168
723
  const utils = new Utils();
169
724
  exports.default = utils;
170
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLHVEQUFvRDtBQUNwRCxrREFBbUU7QUFDbkUsc0RBQXdDO0FBQ3hDLG9EQUE0QjtBQUM1QixvREFBMkI7QUFDM0IsdUNBQWtEO0FBRWxELE1BQWEsS0FBSztJQUNoQixjQUFjLENBQUMsT0FBZTtRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVELG9CQUFvQixDQUFDLElBQVk7UUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxNQUFjO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7WUFDN0IsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUNoQyxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVDLE1BQU0sU0FBUyxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqQyxPQUFPLENBQ0wsQ0FBQyxXQUFXLENBQUMsTUFBTSxLQUFLLEVBQUUsSUFBSSxDQUFDLFNBQVMsS0FBSyxDQUFDLElBQUksU0FBUyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ25FLENBQUMsV0FBVyxDQUFDLE1BQU0sS0FBSyxFQUFFLElBQUksU0FBUyxLQUFLLENBQUMsQ0FBQyxDQUMvQyxDQUFDO0lBQ0osQ0FBQztJQUVELGFBQWEsQ0FBQyxNQUFjO1FBQzFCLE9B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QUFDLEdBQUc7WUFDYixHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7U0FDZCxDQUFDO0lBQ0osQ0FBQztDQUNGO0FBaEpELHNCQWdKQztBQUVELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7QUFDMUIsa0JBQWUsS0FBSyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmFzZVV0aWxzLCBLZXlQYWlyIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgc2VjcDI1NmsxIH0gZnJvbSAnQG5vYmxlL2N1cnZlcy9zZWNwMjU2azEnO1xuaW1wb3J0IHsgUHJpbmNpcGFsIGFzIERmaW5pdHlQcmluY2lwYWwgfSBmcm9tICdAZGZpbml0eS9wcmluY2lwYWwnO1xuaW1wb3J0ICogYXMgYWdlbnQgZnJvbSAnQGRmaW5pdHkvYWdlbnQnO1xuaW1wb3J0IGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IGNyYzMyIGZyb20gJ2NyYy0zMic7XG5pbXBvcnQgeyBLZXlQYWlyIGFzIEljcEtleVBhaXIgfSBmcm9tICcuL2tleVBhaXInO1xuXG5leHBvcnQgY2xhc3MgVXRpbHMgaW1wbGVtZW50cyBCYXNlVXRpbHMge1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gIH1cblxuICBpc1ZhbGlkVHJhbnNhY3Rpb25JZCh0eElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gIH1cblxuICBpc1ZhbGlkUHVibGljS2V5KGhleFN0cjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWRIZXgoaGV4U3RyKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc1ZhbGlkTGVuZ3RoKGhleFN0cikpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBwdWJLZXlCeXRlcyA9IHRoaXMuaGV4VG9CeXRlcyhoZXhTdHIpO1xuICAgIGNvbnN0IGZpcnN0Qnl0ZSA9IHB1YktleUJ5dGVzWzBdO1xuICAgIHJldHVybiAoXG4gICAgICAocHViS2V5Qnl0ZXMubGVuZ3RoID09PSAzMyAmJiAoZmlyc3RCeXRlID09PSAyIHx8IGZpcnN0Qnl0ZSA9PT0gMykpIHx8XG4gICAgICAocHViS2V5Qnl0ZXMubGVuZ3RoID09PSA2NSAmJiBmaXJzdEJ5dGUgPT09IDQpXG4gICAgKTtcbiAgfVxuXG4gIGlzVmFsaWRMZW5ndGgoaGV4U3RyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaGV4U3RyLmxlbmd0aCAvIDIgPT09IDMzIHx8IGhleFN0ci5sZW5ndGggLyAyID09PSA2NTtcbiAgfVxuXG4gIGlzVmFsaWRIZXgoaGV4U3RyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gL14oWzAtOWEtZkEtRl17Mn0pKyQvLnRlc3QoaGV4U3RyKTtcbiAgfVxuXG4gIGhleFRvQnl0ZXMoaGV4OiBzdHJpbmcpOiBVaW50OEFycmF5IHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoQnVmZmVyLmZyb20oaGV4LCAnaGV4JykpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRQcml2YXRlS2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZEtleShrZXkpO1xuICB9XG5cbiAgaXNWYWxpZEtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBuZXcgSWNwS2V5UGFpcih7IHBydjoga2V5IH0pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgaXNWYWxpZFNpZ25hdHVyZShzaWduYXR1cmU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuXG4gIGlzVmFsaWRCbG9ja0lkKGhhc2g6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuXG4gIGdldEhlYWRlcnMoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgfTtcbiAgfVxuXG4gIGdldE5ldHdvcmtJZGVudGlmaWVyKCk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiB7XG4gICAgICBibG9ja2NoYWluOiAnSW50ZXJuZXQgQ29tcHV0ZXInLFxuICAgICAgbmV0d29yazogJzAwMDAwMDAwMDAwMDAwMDIwMTAxJyxcbiAgICB9O1xuICB9XG5cbiAgY29tcHJlc3NQdWJsaWNLZXkodW5jb21wcmVzc2VkS2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh1bmNvbXByZXNzZWRLZXkuc3RhcnRzV2l0aCgnMDInKSB8fCB1bmNvbXByZXNzZWRLZXkuc3RhcnRzV2l0aCgnMDMnKSkge1xuICAgICAgcmV0dXJuIHVuY29tcHJlc3NlZEtleTtcbiAgICB9XG4gICAgaWYgKCF1bmNvbXByZXNzZWRLZXkuc3RhcnRzV2l0aCgnMDQnKSB8fCB1bmNvbXByZXNzZWRLZXkubGVuZ3RoICE9PSAxMzApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB1bmNvbXByZXNzZWQgcHVibGljIGtleSBmb3JtYXQuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgeEhleCA9IHVuY29tcHJlc3NlZEtleS5zbGljZSgyLCA2Nik7XG4gICAgY29uc3QgeUhleCA9IHVuY29tcHJlc3NlZEtleS5zbGljZSg2Nik7XG4gICAgY29uc3QgeSA9IEJpZ0ludChgMHgke3lIZXh9YCk7XG4gICAgY29uc3QgcHJlZml4ID0geSAlIDJuID09PSAwbiA/ICcwMicgOiAnMDMnO1xuXG4gICAgcmV0dXJuIHByZWZpeCArIHhIZXg7XG4gIH1cblxuICBnZXRDdXJ2ZVR5cGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ3NlY3AyNTZrMSc7XG4gIH1cblxuICBkZXJpdmVQcmluY2lwYWxGcm9tUHVibGljS2V5KHB1YmxpY0tleUhleDogc3RyaW5nKTogRGZpbml0eVByaW5jaXBhbCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHBvaW50ID0gc2VjcDI1NmsxLlByb2plY3RpdmVQb2ludC5mcm9tSGV4KHB1YmxpY0tleUhleCk7XG4gICAgICBjb25zdCB1bmNvbXByZXNzZWRQdWJsaWNLZXlIZXggPSBwb2ludC50b0hleChmYWxzZSk7XG4gICAgICBjb25zdCBkZXJFbmNvZGVkS2V5ID0gYWdlbnQud3JhcERFUihCdWZmZXIuZnJvbSh1bmNvbXByZXNzZWRQdWJsaWNLZXlIZXgsICdoZXgnKSwgYWdlbnQuU0VDUDI1NksxX09JRCk7XG4gICAgICBjb25zdCBwcmluY2lwYWxJZCA9IERmaW5pdHlQcmluY2lwYWwuc2VsZkF1dGhlbnRpY2F0aW5nKEJ1ZmZlci5mcm9tKGRlckVuY29kZWRLZXkpKTtcbiAgICAgIGNvbnN0IHByaW5jaXBhbCA9IERmaW5pdHlQcmluY2lwYWwuZnJvbVVpbnQ4QXJyYXkocHJpbmNpcGFsSWQudG9VaW50OEFycmF5KCkpO1xuICAgICAgcmV0dXJuIHByaW5jaXBhbDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcHJvY2VzcyB0aGUgcHVibGljIGtleTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIGZyb21QcmluY2lwYWwocHJpbmNpcGFsOiBEZmluaXR5UHJpbmNpcGFsLCBzdWJBY2NvdW50OiBVaW50OEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoMzIpKTogc3RyaW5nIHtcbiAgICBjb25zdCBBQ0NPVU5UX0lEX1BSRUZJWCA9IG5ldyBVaW50OEFycmF5KFsweDBhLCAuLi5CdWZmZXIuZnJvbSgnYWNjb3VudC1pZCcpXSk7XG4gICAgY29uc3QgcHJpbmNpcGFsQnl0ZXMgPSBwcmluY2lwYWwudG9VaW50OEFycmF5KCk7XG4gICAgY29uc3QgY29tYmluZWRCeXRlcyA9IG5ldyBVaW50OEFycmF5KEFDQ09VTlRfSURfUFJFRklYLmxlbmd0aCArIHByaW5jaXBhbEJ5dGVzLmxlbmd0aCArIHN1YkFjY291bnQubGVuZ3RoKTtcblxuICAgIGNvbWJpbmVkQnl0ZXMuc2V0KEFDQ09VTlRfSURfUFJFRklYLCAwKTtcbiAgICBjb21iaW5lZEJ5dGVzLnNldChwcmluY2lwYWxCeXRlcywgQUNDT1VOVF9JRF9QUkVGSVgubGVuZ3RoKTtcbiAgICBjb21iaW5lZEJ5dGVzLnNldChzdWJBY2NvdW50LCBBQ0NPVU5UX0lEX1BSRUZJWC5sZW5ndGggKyBwcmluY2lwYWxCeXRlcy5sZW5ndGgpO1xuXG4gICAgY29uc3Qgc2hhMjI0SGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyMjQnKS51cGRhdGUoY29tYmluZWRCeXRlcykuZGlnZXN0KCk7XG4gICAgY29uc3QgY2hlY2tzdW0gPSBCdWZmZXIuYWxsb2MoNCk7XG4gICAgY2hlY2tzdW0ud3JpdGVVSW50MzJCRShjcmMzMi5idWYoc2hhMjI0SGFzaCkgPj4+IDAsIDApO1xuXG4gICAgY29uc3QgYWNjb3VudElkQnl0ZXMgPSBCdWZmZXIuY29uY2F0KFtjaGVja3N1bSwgc2hhMjI0SGFzaF0pO1xuICAgIHJldHVybiBhY2NvdW50SWRCeXRlcy50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICBhc3luYyBnZXRBZGRyZXNzRnJvbVB1YmxpY0tleShoZXhFbmNvZGVkUHVibGljS2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGlzS2V5VmFsaWQgPSB0aGlzLmlzVmFsaWRQdWJsaWNLZXkoaGV4RW5jb2RlZFB1YmxpY0tleSk7XG4gICAgaWYgKCFpc0tleVZhbGlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1B1YmxpYyBLZXkgaXMgbm90IGluIGEgdmFsaWQgSGV4IEVuY29kZWQgRm9ybWF0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGNvbXByZXNzZWRLZXkgPSB0aGlzLmNvbXByZXNzUHVibGljS2V5KGhleEVuY29kZWRQdWJsaWNLZXkpO1xuICAgIGNvbnN0IEtleVBhaXIgPSBuZXcgSWNwS2V5UGFpcih7IHB1YjogY29tcHJlc3NlZEtleSB9KTtcbiAgICByZXR1cm4gS2V5UGFpci5nZXRBZGRyZXNzKCk7XG4gIH1cblxuICBwdWJsaWMgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIpOiBLZXlQYWlyIHtcbiAgICBjb25zdCBrZXlQYWlyID0gc2VlZCA/IG5ldyBJY3BLZXlQYWlyKHsgc2VlZCB9KSA6IG5ldyBJY3BLZXlQYWlyKCk7XG4gICAgY29uc3Qga2V5cyA9IGtleVBhaXIuZ2V0S2V5cygpO1xuICAgIGlmICgha2V5cy5wcnYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBwcnYgaW4ga2V5IGdlbmVyYXRpb24uJyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBwdWI6IGtleXMucHViLFxuICAgICAgcHJ2OiBrZXlzLnBydixcbiAgICB9O1xuICB9XG59XG5cbmNvbnN0IHV0aWxzID0gbmV3IFV0aWxzKCk7XG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==
725
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1EQU84QjtBQUM5QixrREFBbUU7QUFDbkUsc0RBQXdDO0FBQ3hDLG9EQUE0QjtBQUM1QixvREFBMkI7QUFDM0IsbUNBWWlCO0FBQ2pCLHVDQUFrRDtBQUNsRCxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUMsaUNBQWlDLENBQUMsQ0FBQztBQUNuRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLGdNQUFnTTtBQUNyUSwwREFBa0M7QUFDbEMsZ0VBQXFDO0FBQ3JDLHVEQUFvRDtBQUVwRCxvQ0FBb0M7QUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUM7SUFDMUIsZUFBZSxFQUFFLEtBQUs7SUFDdEIsU0FBUyxFQUFFLEtBQUs7SUFDaEIsYUFBYSxFQUFFLEtBQUs7SUFDcEIsa0JBQWtCLEVBQUUsS0FBSztDQUMxQixDQUFDLENBQUM7QUFFSCxNQUFhLEtBQUs7SUFBbEI7UUE0bkJFLGdCQUFXLEdBQUcsQ0FBQyxVQUFrQixFQUFFLFVBQWtCLEVBQVUsRUFBRTtZQUMvRCxNQUFNLGVBQWUsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN2RCxNQUFNLFdBQVcsR0FBRyxnQkFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDckcsTUFBTSxTQUFTLEdBQUcscUJBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLGVB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Q0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RSxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVELDBCQUEwQixDQUFDLFdBQWtDO1FBQzNELElBQUksV0FBVyxJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNwQyxNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDO1lBQ3BDLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDakMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxnQkFBSyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdkQsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdFLENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDaEQsQ0FBQztDQUNGO0FBcHRCRCxzQkFvdEJDO0FBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztBQUMxQixrQkFBZSxLQUFLLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBCYXNlVXRpbHMsXG4gIEtleVBhaXIsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbiAgUmVjaXBpZW50LFxuICBCdWlsZFRyYW5zYWN0aW9uRXJyb3IsXG4gIE1ldGhvZE5vdEltcGxlbWVudGVkRXJyb3IsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IFByaW5jaXBhbCBhcyBEZmluaXR5UHJpbmNpcGFsIH0gZnJvbSAnQGRmaW5pdHkvcHJpbmNpcGFsJztcbmltcG9ydCAqIGFzIGFnZW50IGZyb20gJ0BkZmluaXR5L2FnZW50JztcbmltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCBjcmMzMiBmcm9tICdjcmMtMzInO1xuaW1wb3J0IHtcbiAgSHR0cENhbmlzdGVyVXBkYXRlLFxuICBJY3BUcmFuc2FjdGlvbkRhdGEsXG4gIFJlcXVlc3RUeXBlLFxuICBTaWduYXR1cmVzLFxuICBNZXRhRGF0YSxcbiAgU2VuZEFyZ3MsXG4gIFBheWxvYWRzRGF0YSxcbiAgQ3VydmVUeXBlLFxuICBBY2NvdW50SWRlbnRpZmllckhhc2gsXG4gIENib3JVbnNpZ25lZFRyYW5zYWN0aW9uLFxuICBNQVhfSU5HUkVTU19UVEwsXG59IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHsgS2V5UGFpciBhcyBJY3BLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmNvbnN0IG1lc3NhZ2VDb21waWxlZCA9IHJlcXVpcmUoJy4uLy4uL3Jlc291cmNlcy9tZXNzYWdlQ29tcGlsZWQnKTtcbmNvbnN0IHsgZW5jb2RlLCBkZWNvZGUsIEVuY29kZXIgfSA9IHJlcXVpcmUoJ2Nib3IteC9pbmRleC1uby1ldmFsJyk7IC8vIFRoZSBcImNib3IteFwiIGxpYnJhcnkgaXMgdXNlZCBoZXJlIGJlY2F1c2UgaXQgc3VwcG9ydHMgbW9kZXJuIGZlYXR1cmVzIGxpa2UgQmlnSW50LiBkbyBub3QgcmVwbGFjZSBpdCB3aXRoIFwiY2JvciBhcyBcImNib3JcIiBpcyBub3QgY29tcGF0aWJsZSB3aXRoIFJ1c3QncyBzZXJkZV9jYm9yIHdoZW4gaGFuZGxpbmcgYmlnIG51bWJlcnMuXG5pbXBvcnQganNfc2hhMjU2IGZyb20gJ2pzLXNoYTI1Nic7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5pbXBvcnQgeyBzZWNwMjU2azEgfSBmcm9tICdAbm9ibGUvY3VydmVzL3NlY3AyNTZrMSc7XG5cbi8vY3VzdG9tIGVuY29kZXIgdGhhdCBhdm9pZHMgdGFnZ2luZ1xuY29uc3QgZW5jb2RlciA9IG5ldyBFbmNvZGVyKHtcbiAgc3RydWN0dXJlZENsb25lOiBmYWxzZSxcbiAgdXNlVG9KU09OOiBmYWxzZSxcbiAgbWFwc0FzT2JqZWN0czogZmFsc2UsXG4gIGxhcmdlQmlnSW50VG9GbG9hdDogZmFsc2UsXG59KTtcblxuZXhwb3J0IGNsYXNzIFV0aWxzIGltcGxlbWVudHMgQmFzZVV0aWxzIHtcbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRTaWduYXR1cmUoc2lnbmF0dXJlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgTWV0aG9kTm90SW1wbGVtZW50ZWRFcnJvcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldHMgdGhlIGZlZSBkYXRhIG9mIHRoaXMgdHJhbnNhY3Rpb24uXG4gICAqL1xuICBmZWVEYXRhKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICctMTAwMDAnOyAvLyBmZWUgaXMgc3RhdGljIGZvciBJQ1AgdHJhbnNhY3Rpb25zIGFzIHBlciBJQ1AgZG9jdW1lbnRhdGlvblxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgcHJvdmlkZWQgYWRkcmVzcyBpcyBhIHZhbGlkIElDUCBhZGRyZXNzLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzcyAtIFRoZSBhZGRyZXNzIHRvIHZhbGlkYXRlLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYWRkcmVzcyBpcyB2YWxpZCwgb3RoZXJ3aXNlIGBmYWxzZWAuXG4gICAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCByb290QWRkcmVzcyA9IHRoaXMudmFsaWRhdGVNZW1vQW5kUmV0dXJuUm9vdEFkZHJlc3MoYWRkcmVzcyk7XG4gICAgcmV0dXJuIHJvb3RBZGRyZXNzICE9PSB1bmRlZmluZWQgJiYgdGhpcy5pc1ZhbGlkSGFzaChyb290QWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBtZW1vIElEIGluIHRoZSBhZGRyZXNzIGFuZCByZXR1cm5zIHRoZSByb290IGFkZHJlc3MuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIC0gVGhlIGFkZHJlc3MgdG8gdmFsaWRhdGUgYW5kIGV4dHJhY3QgdGhlIHJvb3QgYWRkcmVzcyBmcm9tLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nIHwgdW5kZWZpbmVkfSAtIFRoZSByb290IGFkZHJlc3MgaWYgdmFsaWQsIG90aGVyd2lzZSBgdW5kZWZpbmVkYC5cbiAgICovXG4gIHZhbGlkYXRlTWVtb0FuZFJldHVyblJvb3RBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFhZGRyZXNzKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBbcm9vdEFkZHJlc3MsIG1lbW9JZF0gPSBhZGRyZXNzLnNwbGl0KCc/bWVtb0lkPScpO1xuICAgIGlmIChtZW1vSWQgJiYgdGhpcy52YWxpZGF0ZU1lbW8oQmlnSW50KG1lbW9JZCkpKSB7XG4gICAgICByZXR1cm4gcm9vdEFkZHJlc3M7XG4gICAgfVxuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgcHJvdmlkZWQgaGV4IHN0cmluZyBpcyBhIHZhbGlkIHB1YmxpYyBrZXkuXG4gICAqXG4gICAqIEEgdmFsaWQgcHVibGljIGtleSBjYW4gYmUgZWl0aGVyIGNvbXByZXNzZWQgb3IgdW5jb21wcmVzc2VkOlxuICAgKiAtIENvbXByZXNzZWQgcHVibGljIGtleXMgYXJlIDMzIGJ5dGVzIGxvbmcgYW5kIHN0YXJ0IHdpdGggZWl0aGVyIDB4MDIgb3IgMHgwMy5cbiAgICogLSBVbmNvbXByZXNzZWQgcHVibGljIGtleXMgYXJlIDY1IGJ5dGVzIGxvbmcgYW5kIHN0YXJ0IHdpdGggMHgwNC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhleFN0ciAtIFRoZSBoZXggc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwdWJsaWMga2V5IHRvIHZhbGlkYXRlLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgaGV4IHN0cmluZyBpcyBhIHZhbGlkIHB1YmxpYyBrZXksIG90aGVyd2lzZSBgZmFsc2VgLlxuICAgKi9cbiAgaXNWYWxpZFB1YmxpY0tleShoZXhTdHI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkSGV4KGhleFN0cikgfHwgIXRoaXMuaXNWYWxpZExlbmd0aChoZXhTdHIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgcHViS2V5Qnl0ZXMgPSB0aGlzLmhleFRvQnl0ZXMoaGV4U3RyKTtcbiAgICBjb25zdCBmaXJzdEJ5dGUgPSBwdWJLZXlCeXRlc1swXTtcbiAgICBjb25zdCB2YWxpZENvbXByZXNzZWQgPSBwdWJLZXlCeXRlcy5sZW5ndGggPT09IDMzICYmIChmaXJzdEJ5dGUgPT09IDIgfHwgZmlyc3RCeXRlID09PSAzKTtcbiAgICBjb25zdCB2YWxpZFVuY29tcHJlc3NlZCA9IHB1YktleUJ5dGVzLmxlbmd0aCA9PT0gNjUgJiYgZmlyc3RCeXRlID09PSA0O1xuXG4gICAgcmV0dXJuIHZhbGlkQ29tcHJlc3NlZCB8fCB2YWxpZFVuY29tcHJlc3NlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmNvZGVzIGEgdmFsdWUgaW50byBDQk9SIGZvcm1hdCBhbmQgcmV0dXJucyBpdCBhcyBhIGhleCBzdHJpbmcuXG4gICAqXG4gICAqIEBwYXJhbSB7dW5rbm93bn0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gZW5jb2RlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIFRoZSBDQk9SIGVuY29kZWQgdmFsdWUgYXMgYSBoZXggc3RyaW5nLlxuICAgKi9cbiAgY2JvckVuY29kZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVmFsdWUgdG8gZW5jb2RlIGNhbm5vdCBiZSB1bmRlZmluZWQuJyk7XG4gICAgfVxuICAgIGNvbnN0IGNib3JEYXRhID0gZW5jb2RlKHZhbHVlKTtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oY2JvckRhdGEpLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIGxlbmd0aCBvZiB0aGUgZ2l2ZW4gaGV4YWRlY2ltYWwgc3RyaW5nIGlzIHZhbGlkLlxuICAgKiBBIHZhbGlkIGxlbmd0aCBpcyBlaXRoZXIgNjYgY2hhcmFjdGVycyAoMzMgYnl0ZXMpIG9yIDEzMCBjaGFyYWN0ZXJzICg2NSBieXRlcykuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBoZXhTdHIgLSBUaGUgaGV4YWRlY2ltYWwgc3RyaW5nIHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgbGVuZ3RoIGlzIHZhbGlkLCBvdGhlcndpc2UgYGZhbHNlYC5cbiAgICovXG4gIGlzVmFsaWRMZW5ndGgoaGV4U3RyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaGV4U3RyLmxlbmd0aCAvIDIgPT09IDMzIHx8IGhleFN0ci5sZW5ndGggLyAyID09PSA2NTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIHByb3ZpZGVkIHN0cmluZyBpcyBhIHZhbGlkIGhleGFkZWNpbWFsIHN0cmluZy5cbiAgICpcbiAgICogQSB2YWxpZCBoZXhhZGVjaW1hbCBzdHJpbmcgY29uc2lzdHMgb2YgcGFpcnMgb2YgaGV4YWRlY2ltYWwgZGlnaXRzICgwLTksIGEtZiwgQS1GKS5cbiAgICpcbiAgICogQHBhcmFtIGhleFN0ciAtIFRoZSBzdHJpbmcgdG8gYmUgdmFsaWRhdGVkIGFzIGEgaGV4YWRlY2ltYWwgc3RyaW5nLlxuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBoZXhhZGVjaW1hbCBzdHJpbmcsIGZhbHNlIG90aGVyd2lzZS5cbiAgICovXG4gIGlzVmFsaWRIZXgoaGV4U3RyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gL14oWzAtOWEtZkEtRl17Mn0pKyQvLnRlc3QoaGV4U3RyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGhleGFkZWNpbWFsIHN0cmluZyB0byBhIFVpbnQ4QXJyYXkuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBoZXggLSBUaGUgaGV4YWRlY2ltYWwgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtVaW50OEFycmF5fSBUaGUgcmVzdWx0aW5nIGJ5dGUgYXJyYXkuXG4gICAqL1xuICBoZXhUb0J5dGVzKGhleDogc3RyaW5nKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShoZXgubGVuZ3RoIC8gMik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZXgubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgIGJ5dGVzW2kgLyAyXSA9IHBhcnNlSW50KGhleC5zdWJzdHIoaSwgMiksIDE2KTtcbiAgICB9XG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRQcml2YXRlS2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZEtleShrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB3aGV0aGVyIHRoZSBwcm92aWRlZCBrZXkgaXMgYSB2YWxpZCBJQ1AgcHJpdmF0ZSBrZXkuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gYXR0ZW1wdHMgdG8gY3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIGBJY3BLZXlQYWlyYCB1c2luZyB0aGUgcHJvdmlkZWQga2V5LlxuICAgKiBJZiB0aGUga2V5IGlzIHZhbGlkLCB0aGUgZnVuY3Rpb24gcmV0dXJucyBgdHJ1ZWAuIElmIHRoZSBrZXkgaXMgaW52YWxpZCwgYW4gZXJyb3IgaXMgdGhyb3duLFxuICAgKiBhbmQgdGhlIGZ1bmN0aW9uIHJldHVybnMgYGZhbHNlYC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBwcml2YXRlIGtleSB0byB2YWxpZGF0ZS5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gYHRydWVgIGlmIHRoZSBrZXkgaXMgdmFsaWQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKi9cbiAgaXNWYWxpZEtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBuZXcgSWNwS2V5UGFpcih7IHBydjoga2V5IH0pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbXByZXNzZXMgYW4gdW5jb21wcmVzc2VkIHB1YmxpYyBrZXkuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1bmNvbXByZXNzZWRLZXkgLSBUaGUgdW5jb21wcmVzc2VkIHB1YmxpYyBrZXkgaW4gaGV4YWRlY2ltYWwgZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIFRoZSBjb21wcmVzc2VkIHB1YmxpYyBrZXkgaW4gaGV4YWRlY2ltYWwgZm9ybWF0LlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gLSBJZiB0aGUgaW5wdXQga2V5IGlzIG5vdCBhIHZhbGlkIHVuY29tcHJlc3NlZCBwdWJsaWMga2V5LlxuICAgKi9cbiAgY29tcHJlc3NQdWJsaWNLZXkodW5jb21wcmVzc2VkS2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh1bmNvbXByZXNzZWRLZXkuc3RhcnRzV2l0aCgnMDInKSB8fCB1bmNvbXByZXNzZWRLZXkuc3RhcnRzV2l0aCgnMDMnKSkge1xuICAgICAgcmV0dXJuIHVuY29tcHJlc3NlZEtleTtcbiAgICB9XG4gICAgaWYgKCF1bmNvbXByZXNzZWRLZXkuc3RhcnRzV2l0aCgnMDQnKSB8fCB1bmNvbXByZXNzZWRLZXkubGVuZ3RoICE9PSAxMzApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB1bmNvbXByZXNzZWQgcHVibGljIGtleSBmb3JtYXQuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgeEhleCA9IHVuY29tcHJlc3NlZEtleS5zbGljZSgyLCA2Nik7XG4gICAgY29uc3QgeUhleCA9IHVuY29tcHJlc3NlZEtleS5zbGljZSg2Nik7XG4gICAgY29uc3QgeSA9IEJpZ0ludChgMHgke3lIZXh9YCk7XG4gICAgY29uc3QgcHJlZml4ID0geSAlIDJuID09PSAwbiA/ICcwMicgOiAnMDMnO1xuXG4gICAgcmV0dXJuIGAke3ByZWZpeH0ke3hIZXh9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIHB1YmxpYyBrZXkgZnJvbSBpdHMgaGV4YWRlY2ltYWwgc3RyaW5nIHJlcHJlc2VudGF0aW9uIHRvIERFUiBmb3JtYXQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwdWJsaWNLZXlIZXggLSBUaGUgcHVibGljIGtleSBpbiBoZXhhZGVjaW1hbCBzdHJpbmcgZm9ybWF0LlxuICAgKiBAcmV0dXJucyBUaGUgcHVibGljIGtleSBpbiBERVIgZm9ybWF0IGFzIGEgVWludDhBcnJheS5cbiAgICovXG4gIGdldFB1YmxpY0tleUluREVSRm9ybWF0KHB1YmxpY0tleUhleDogc3RyaW5nKTogVWludDhBcnJheSB7XG4gICAgY29uc3QgcHVibGljS2V5QnVmZmVyID0gQnVmZmVyLmZyb20ocHVibGljS2V5SGV4LCAnaGV4Jyk7XG4gICAgY29uc3QgZWxsaXB0aWNLZXkgPSBzZWNwMjU2azEuUHJvamVjdGl2ZVBvaW50LmZyb21IZXgocHVibGljS2V5QnVmZmVyLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgY29uc3QgdW5jb21wcmVzc2VkUHVibGljS2V5SGV4ID0gZWxsaXB0aWNLZXkudG9IZXgoZmFsc2UpO1xuICAgIGNvbnN0IGRlckVuY29kZWRLZXkgPSBhZ2VudC53cmFwREVSKEJ1ZmZlci5mcm9tKHVuY29tcHJlc3NlZFB1YmxpY0tleUhleCwgJ2hleCcpLCBhZ2VudC5TRUNQMjU2SzFfT0lEKTtcbiAgICByZXR1cm4gZGVyRW5jb2RlZEtleTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIHB1YmxpYyBrZXkgaW4gaGV4YWRlY2ltYWwgZm9ybWF0IHRvIGEgRGZpbml0eSBQcmluY2lwYWwgSUQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwdWJsaWNLZXlIZXggLSBUaGUgcHVibGljIGtleSBpbiBoZXhhZGVjaW1hbCBmb3JtYXQuXG4gICAqIEByZXR1cm5zIFRoZSBjb3JyZXNwb25kaW5nIERmaW5pdHkgUHJpbmNpcGFsIElELlxuICAgKi9cbiAgZ2V0UHJpbmNpcGFsSWRGcm9tUHVibGljS2V5KHB1YmxpY0tleUhleDogc3RyaW5nKTogRGZpbml0eVByaW5jaXBhbCB7XG4gICAgY29uc3QgZGVyRW5jb2RlZEtleSA9IHRoaXMuZ2V0UHVibGljS2V5SW5ERVJGb3JtYXQocHVibGljS2V5SGV4KTtcbiAgICBjb25zdCBwcmluY2lwYWxJZCA9IERmaW5pdHlQcmluY2lwYWwuc2VsZkF1dGhlbnRpY2F0aW5nKEJ1ZmZlci5mcm9tKGRlckVuY29kZWRLZXkpKTtcbiAgICByZXR1cm4gcHJpbmNpcGFsSWQ7XG4gIH1cblxuICAvKipcbiAgICogRGVyaXZlcyBhIERmaW5pdHlQcmluY2lwYWwgZnJvbSBhIGdpdmVuIHB1YmxpYyBrZXkgaW4gaGV4YWRlY2ltYWwgZm9ybWF0LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcHVibGljS2V5SGV4IC0gVGhlIHB1YmxpYyBrZXkgaW4gaGV4YWRlY2ltYWwgZm9ybWF0LlxuICAgKiBAcmV0dXJucyBUaGUgZGVyaXZlZCBEZmluaXR5UHJpbmNpcGFsLlxuICAgKiBAdGhyb3dzIFdpbGwgdGhyb3cgYW4gZXJyb3IgaWYgdGhlIHByaW5jaXBhbCBjYW5ub3QgYmUgZGVyaXZlZCBmcm9tIHRoZSBwdWJsaWMga2V5LlxuICAgKi9cbiAgZGVyaXZlUHJpbmNpcGFsRnJvbVB1YmxpY0tleShwdWJsaWNLZXlIZXg6IHN0cmluZyk6IERmaW5pdHlQcmluY2lwYWwge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZXJFbmNvZGVkS2V5ID0gdGhpcy5nZXRQdWJsaWNLZXlJbkRFUkZvcm1hdChwdWJsaWNLZXlIZXgpO1xuICAgICAgY29uc3QgcHJpbmNpcGFsSWQgPSBEZmluaXR5UHJpbmNpcGFsLnNlbGZBdXRoZW50aWNhdGluZyhCdWZmZXIuZnJvbShkZXJFbmNvZGVkS2V5KSk7XG4gICAgICBjb25zdCBwcmluY2lwYWwgPSBEZmluaXR5UHJpbmNpcGFsLmZyb21VaW50OEFycmF5KHByaW5jaXBhbElkLnRvVWludDhBcnJheSgpKTtcbiAgICAgIHJldHVybiBwcmluY2lwYWw7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGRlcml2ZSBwcmluY2lwYWwgZnJvbSBwdWJsaWMga2V5OiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgRGZpbml0eVByaW5jaXBhbCBhbmQgYW4gb3B0aW9uYWwgc3ViQWNjb3VudCB0byBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhbiBhY2NvdW50IElELlxuICAgKlxuICAgKiBAcGFyYW0ge0RmaW5pdHlQcmluY2lwYWx9IHByaW5jaXBhbCAtIFRoZSBwcmluY2lwYWwgdG8gY29udmVydC5cbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBbc3ViQWNjb3VudD1uZXcgVWludDhBcnJheSgzMildIC0gQW4gb3B0aW9uYWwgc3ViLWFjY291bnQsIGRlZmF1bHRzIHRvIGEgMzItYnl0ZSBhcnJheSBvZiB6ZXJvcy5cbiAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGhleGFkZWNpbWFsIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgYWNjb3VudCBJRC5cbiAgICovXG4gIGZyb21QcmluY2lwYWwocHJpbmNpcGFsOiBEZmluaXR5UHJpbmNpcGFsLCBzdWJBY2NvdW50OiBVaW50OEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoMzIpKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcmluY2lwYWxCeXRlcyA9IEJ1ZmZlci5mcm9tKHByaW5jaXBhbC50b1VpbnQ4QXJyYXkoKS5idWZmZXIpO1xuICAgIHJldHVybiB0aGlzLmdldEFjY291bnRJZEZyb21QcmluY2lwYWxCeXRlcyh0aGlzLmdldEFjY291bnRJZFByZWZpeCgpLCBwcmluY2lwYWxCeXRlcywgc3ViQWNjb3VudCk7XG4gIH1cblxuICBnZXRBY2NvdW50SWRGcm9tUHJpbmNpcGFsQnl0ZXMoXG4gICAgQUNDT1VOVF9JRF9QUkVGSVg6IEJ1ZmZlcjxBcnJheUJ1ZmZlcj4sXG4gICAgcHJpbmNpcGFsQnl0ZXM6IEJ1ZmZlcjxBcnJheUJ1ZmZlckxpa2U+LFxuICAgIHN1YkFjY291bnQ6IFVpbnQ4QXJyYXk8QXJyYXlCdWZmZXJMaWtlPlxuICApOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbWJpbmVkQnl0ZXMgPSBCdWZmZXIuY29uY2F0KFtBQ0NPVU5UX0lEX1BSRUZJWCwgcHJpbmNpcGFsQnl0ZXMsIHN1YkFjY291bnRdKTtcbiAgICBjb25zdCBzaGEyMjRIYXNoID0gY3J5cHRvLmNyZWF0ZUhhc2goJ3NoYTIyNCcpLnVwZGF0ZShjb21iaW5lZEJ5dGVzKS5kaWdlc3QoKTtcbiAgICBjb25zdCBjaGVja3N1bSA9IEJ1ZmZlci5hbGxvYyg0KTtcbiAgICBjaGVja3N1bS53cml0ZVVJbnQzMkJFKGNyYzMyLmJ1ZihzaGEyMjRIYXNoKSA+Pj4gMCwgMCk7XG4gICAgY29uc3QgYWNjb3VudElkQnl0ZXMgPSBCdWZmZXIuY29uY2F0KFtjaGVja3N1bSwgc2hhMjI0SGFzaF0pO1xuICAgIHJldHVybiBhY2NvdW50SWRCeXRlcy50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBhZGRyZXNzIGFzc29jaWF0ZWQgd2l0aCBhIGdpdmVuIGhleC1lbmNvZGVkIHB1YmxpYyBrZXkuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBoZXhFbmNvZGVkUHVibGljS2V5IC0gVGhlIHB1YmxpYyBrZXkgaW4gaGV4LWVuY29kZWQgZm9ybWF0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgYWRkcmVzcyBkZXJpdmVkIGZyb20gdGhlIHByb3ZpZGVkIHB1YmxpYyBrZXkuXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIHByb3ZpZGVkIHB1YmxpYyBrZXkgaXMgbm90IGluIGEgdmFsaWQgaGV4LWVuY29kZWQgZm9ybWF0LlxuICAgKi9cbiAgYXN5bmMgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkoaGV4RW5jb2RlZFB1YmxpY0tleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZFB1YmxpY0tleShoZXhFbmNvZGVkUHVibGljS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleC1lbmNvZGVkIHB1YmxpYyBrZXkgZm9ybWF0LicpO1xuICAgIH1cbiAgICBjb25zdCBjb21wcmVzc2VkS2V5ID0gdGhpcy5jb21wcmVzc1B1YmxpY0tleShoZXhFbmNvZGVkUHVibGljS2V5KTtcbiAgICBjb25zdCBrZXlQYWlyID0gbmV3IEljcEtleVBhaXIoeyBwdWI6IGNvbXByZXNzZWRLZXkgfSk7XG4gICAgcmV0dXJuIGtleVBhaXIuZ2V0QWRkcmVzcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhIG5ldyBrZXkgcGFpci4gSWYgYSBzZWVkIGlzIHByb3ZpZGVkLCBpdCB3aWxsIGJlIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGtleSBwYWlyLlxuICAgKlxuICAgKiBAcGFyYW0ge0J1ZmZlcn0gW3NlZWRdIC0gT3B0aW9uYWwgc2VlZCBmb3Iga2V5IGdlbmVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtLZXlQYWlyfSAtIFRoZSBnZW5lcmF0ZWQga2V5IHBhaXIgY29udGFpbmluZyBib3RoIHB1YmxpYyBhbmQgcHJpdmF0ZSBrZXlzLlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gLSBJZiB0aGUgcHJpdmF0ZSBrZXkgaXMgbWlzc2luZyBpbiB0aGUgZ2VuZXJhdGVkIGtleSBwYWlyLlxuICAgKi9cbiAgcHVibGljIGdlbmVyYXRlS2V5UGFpcihzZWVkPzogQnVmZmVyKTogS2V5UGFpciB7XG4gICAgY29uc3Qga2V5UGFpciA9IHNlZWQgPyBuZXcgSWNwS2V5UGFpcih7IHNlZWQgfSkgOiBuZXcgSWNwS2V5UGFpcigpO1xuICAgIGNvbnN0IHsgcHViLCBwcnYgfSA9IGtleVBhaXIuZ2V0S2V5cygpO1xuICAgIGlmICghcHJ2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ByaXZhdGUga2V5IGlzIG1pc3NpbmcgaW4gdGhlIGdlbmVyYXRlZCBrZXkgcGFpci4nKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcHViLCBwcnYgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhlIHByb3ZpZGVkIGZlZS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGZlZSAtIFRoZSBmZWUgdG8gdmFsaWRhdGUuXG4gICAqIEB0aHJvd3Mge0J1aWxkVHJhbnNhY3Rpb25FcnJvcn0gLSBJZiB0aGUgZmVlIGlzIHplcm8gb3IgaW52YWxpZC5cbiAgICovXG4gIHZhbGlkYXRlRmVlKGZlZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZmVlVmFsdWUgPSBuZXcgQmlnTnVtYmVyKGZlZSk7XG4gICAgaWYgKGZlZVZhbHVlLmlzWmVybygpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdGZWUgY2Fubm90IGJlIHplcm8nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVWYWx1ZSh2YWx1ZTogQmlnTnVtYmVyKTogYm9vbGVhbiB7XG4gICAgaWYgKHZhbHVlLmlzTGVzc1RoYW5PckVxdWFsVG8oMCkpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ2Ftb3VudCBjYW5ub3QgYmUgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHplcm8nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoZSBwcm92aWRlZCBtZW1vLlxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlciB8IEJpZ0ludH0gbWVtbyAtIFRoZSBtZW1vIHRvIHZhbGlkYXRlLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgbWVtbyBpcyB2YWxpZC5cbiAgICogQHRocm93cyB7QnVpbGRUcmFuc2FjdGlvbkVycm9yfSAtIElmIHRoZSBtZW1vIGlzIGludmFsaWQuXG4gICAqL1xuICB2YWxpZGF0ZU1lbW8obWVtbzogbnVtYmVyIHwgQmlnSW50KTogYm9vbGVhbiB7XG4gICAgY29uc3QgbWVtb051bWJlciA9IE51bWJlcihtZW1vKTtcbiAgICBpZiAobWVtb051bWJlciA8IDAgfHwgTnVtYmVyLmlzTmFOKG1lbW9OdW1iZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIG1lbW8nKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICB2YWxpZGF0ZUV4cGlyZVRpbWUoZXhwaXJlVGltZTogbnVtYmVyIHwgQmlnSW50KTogYm9vbGVhbiB7XG4gICAgaWYgKE51bWJlcihleHBpcmVUaW1lKSA8IERhdGUubm93KCkgKiAxMDAwXzAwMCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCBleHBpcnkgdGltZScpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhlIHJhdyB0cmFuc2FjdGlvbiBkYXRhIHRvIGVuc3VyZSBpdCBoYXMgYSB2YWxpZCBmb3JtYXQgaW4gdGhlIGJsb2NrY2hhaW4gY29udGV4dC5cbiAgICpcbiAgICogQHBhcmFtIHtJY3BUcmFuc2FjdGlvbkRhdGF9IHRyYW5zYWN0aW9uRGF0YSAtIFRoZSB0cmFuc2FjdGlvbiBkYXRhIHRvIHZhbGlkYXRlLlxuICAgKiBAdGhyb3dzIHtQYXJzZVRyYW5zYWN0aW9uRXJyb3J9IElmIHRoZSB0cmFuc2FjdGlvbiBkYXRhIGlzIGludmFsaWQuXG4gICAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHRyYW5zYWN0aW9uRGF0YTogSWNwVHJhbnNhY3Rpb25EYXRhKTogdm9pZCB7XG4gICAgaWYgKCF0cmFuc2FjdGlvbkRhdGEpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1RyYW5zYWN0aW9uIGRhdGEgaXMgbWlzc2luZy4nKTtcbiAgICB9XG4gICAgY29uc3QgeyBzZW5kZXJQdWJsaWNLZXlIZXgsIHNlbmRlckFkZHJlc3MsIHJlY2VpdmVyQWRkcmVzcyB9ID0gdHJhbnNhY3Rpb25EYXRhO1xuICAgIGlmIChzZW5kZXJQdWJsaWNLZXlIZXggJiYgIXRoaXMuaXNWYWxpZFB1YmxpY0tleShzZW5kZXJQdWJsaWNLZXlIZXgpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdTZW5kZXIgcHVibGljIGtleSBpcyBpbnZhbGlkLicpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3Moc2VuZGVyQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1NlbmRlciBhZGRyZXNzIGlzIGludmFsaWQuJyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5pc1ZhbGlkQWRkcmVzcyhyZWNlaXZlckFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdSZWNlaXZlciBhZGRyZXNzIGlzIGludmFsaWQuJyk7XG4gICAgfVxuICAgIHRoaXMudmFsaWRhdGVGZWUodHJhbnNhY3Rpb25EYXRhLmZlZSk7XG4gICAgdGhpcy52YWxpZGF0ZVZhbHVlKG5ldyBCaWdOdW1iZXIodHJhbnNhY3Rpb25EYXRhLmFtb3VudCkpO1xuICAgIHRoaXMudmFsaWRhdGVNZW1vKHRyYW5zYWN0aW9uRGF0YS5tZW1vKTtcbiAgICB0aGlzLnZhbGlkYXRlRXhwaXJlVGltZSh0cmFuc2FjdGlvbkRhdGEuZXhwaXJ5VGltZSk7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IHVwZGF0ZVxuICAgKiBAcmV0dXJucyB7QnVmZmVyfVxuICAgKi9cbiAgZ2VuZXJhdGVIdHRwQ2FuaXN0ZXJVcGRhdGVJZCh1cGRhdGU6IEh0dHBDYW5pc3RlclVwZGF0ZSk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIHRoaXMuSHR0cENhbmlzdGVyVXBkYXRlUmVwcmVzZW50YXRpb25JbmRlcGVuZGVudEhhc2godXBkYXRlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSByZXByZXNlbnRhdGlvbi1pbmRlcGVuZGVudCBoYXNoIGZvciBhbiBIVFRQIGNhbmlzdGVyIHVwZGF0ZS5cbiAgICpcbiAgICogQHBhcmFtIHtIdHRwQ2FuaXN0ZXJVcGRhdGV9IHVwZGF0ZSAtIFRoZSBIVFRQIGNhbmlzdGVyIHVwZGF0ZSBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtCdWZmZXJ9IC0gVGhlIGhhc2ggb2YgdGhlIHVwZGF0ZSBvYmplY3QuXG4gICAqL1xuICBIdHRwQ2FuaXN0ZXJVcGRhdGVSZXByZXNlbnRhdGlvbkluZGVwZW5kZW50SGFzaCh1cGRhdGU6IEh0dHBDYW5pc3RlclVwZGF0ZSk6IEJ1ZmZlciB7XG4gICAgY29uc3QgdXBkYXRlTWFwID0ge1xuICAgICAgcmVxdWVzdF90eXBlOiBSZXF1ZXN0VHlwZS5DQUxMLFxuICAgICAgY2FuaXN0ZXJfaWQ6IHVwZGF0ZS5jYW5pc3Rlcl9pZCxcbiAgICAgIG1ldGhvZF9uYW1lOiB1cGRhdGUubWV0aG9kX25hbWUsXG4gICAgICBhcmc6IHVwZGF0ZS5hcmcsXG4gICAgICBpbmdyZXNzX2V4cGlyeTogdXBkYXRlLmluZ3Jlc3NfZXhwaXJ5LFxuICAgICAgc2VuZGVyOiB1cGRhdGUuc2VuZGVyLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuaGFzaE9mTWFwKHVwZGF0ZU1hcCk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgU0hBLTI1NiBoYXNoIGZvciBhIGdpdmVuIG1hcCBvYmplY3QuXG4gICAqXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgdW5rbm93bj59IG1hcCAtIFRoZSBtYXAgb2JqZWN0IHRvIGhhc2guXG4gICAqIEByZXR1cm5zIHtCdWZmZXJ9IC0gVGhlIHJlc3VsdGluZyBoYXNoIGFzIGEgQnVmZmVyLlxuICAgKi9cbiAgaGFzaE9mTWFwKG1hcDogUmVjb3JkPHN0cmluZywgYW55Pik6IEJ1ZmZlciB7XG4gICAgY29uc3QgaGFzaGVzOiBCdWZmZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3Qga2V5IGluIG1hcCkge1xuICAgICAgaGFzaGVzLnB1c2godGhpcy5oYXNoS2V5VmFsKGtleSwgbWFwW2tleV0pKTtcbiAgICB9XG4gICAgaGFzaGVzLnNvcnQoKGJ1ZjAsIGJ1ZjEpID0+IGJ1ZjAuY29tcGFyZShidWYxKSk7XG4gICAgcmV0dXJuIHRoaXMuc2hhMjU2KGhhc2hlcyk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgaGFzaCBmb3IgYSBrZXktdmFsdWUgcGFpci5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBrZXkgdG8gaGFzaC5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBCdWZmZXIgfCBCaWdJbnR9IHZhbCAtIFRoZSB2YWx1ZSB0byBoYXNoLlxuICAgKiBAcmV0dXJucyB7QnVmZmVyfSAtIFRoZSByZXN1bHRpbmcgaGFzaCBhcyBhIEJ1ZmZlci5cbiAgICovXG4gIGhhc2hLZXlWYWwoa2V5OiBzdHJpbmcsIHZhbDogYW55KTogQnVmZmVyIHtcbiAgICBjb25zdCBrZXlIYXNoID0gdGhpcy5oYXNoU3RyaW5nKGtleSk7XG4gICAgY29uc3QgdmFsSGFzaCA9IHRoaXMuaGFzaFZhbCh2YWwpO1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtrZXlIYXNoLCB2YWxIYXNoXSk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgU0hBLTI1NiBoYXNoIGZvciBhIGdpdmVuIHN0cmluZy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIC0gVGhlIHN0cmluZyB0byBoYXNoLlxuICAgKiBAcmV0dXJucyB7QnVmZmVyfSAtIFRoZSByZXN1bHRpbmcgaGFzaCBhcyBhIEJ1ZmZlci5cbiAgICovXG4gIGhhc2hTdHJpbmcodmFsdWU6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2hhMjU2KFtCdWZmZXIuZnJvbSh2YWx1ZSldKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSBoYXNoIGZvciBhIDY0LWJpdCB1bnNpZ25lZCBpbnRlZ2VyLlxuICAgKlxuICAgKiBAcGFyYW0ge2JpZ2ludH0gbiAtIFRoZSA2NC1iaXQgdW5zaWduZWQgaW50ZWdlciB0byBoYXNoLlxuICAgKiBAcmV0dXJucyB7QnVmZmVyfSAtIFRoZSByZXN1bHRpbmcgaGFzaCBhcyBhIEJ1ZmZlci5cbiAgICovXG4gIGhhc2hVNjQobjogYmlnaW50KTogQnVmZmVyIHtcbiAgICBjb25zdCBidWYgPSBCdWZmZXIuYWxsb2NVbnNhZmUoMTApO1xuICAgIGxldCBpID0gMDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgYnl0ZSA9IE51bWJlcihuICYgQmlnSW50KDB4N2YpKTtcbiAgICAgIG4gPj49IEJpZ0ludCg3KTtcbiAgICAgIGlmIChuID09PSBCaWdJbnQoMCkpIHtcbiAgICAgICAgYnVmW2ldID0gYnl0ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBidWZbaV0gPSBieXRlIHwgMHg4MDtcbiAgICAgICAgKytpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5oYXNoQnl0ZXMoYnVmLnN1YmFycmF5KDAsIGkgKyAxKSk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgU0hBLTI1NiBoYXNoIGZvciBhbiBhcnJheSBvZiBlbGVtZW50cy5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheTxhbnk+fSBlbGVtZW50cyAtIFRoZSBhcnJheSBvZiBlbGVtZW50cyB0byBoYXNoLlxuICAgKiBAcmV0dXJucyB7QnVmZmVyfSAtIFRoZSByZXN1bHRpbmcgaGFzaCBhcyBhIEJ1ZmZlci5cbiAgICovXG4gIGhhc2hBcnJheShlbGVtZW50czogQXJyYXk8YW55Pik6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIHRoaXMuc2hhMjU2KGVsZW1lbnRzLm1hcCh0aGlzLmhhc2hWYWwpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSBoYXNoIGZvciBhIGdpdmVuIHZhbHVlLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IEJ1ZmZlciB8IEJpZ0ludCB8IG51bWJlciB8IEFycmF5PHVua25vd24+fSB2YWwgLSBUaGUgdmFsdWUgdG8gaGFzaC5cbiAgICogQHJldHVybnMge0J1ZmZlcn0gLSBUaGUgcmVzdWx0aW5nIGhhc2ggYXMgYSBCdWZmZXIuXG4gICAqIEB0aHJvd3Mge0Vycm9yfSAtIElmIHRoZSB2YWx1ZSB0eXBlIGlzIHVuc3VwcG9ydGVkLlxuICAgKi9cbiAgaGFzaFZhbCh2YWw6IHN0cmluZyB8IEJ1ZmZlciB8IEJpZ0ludCB8IG51bWJlciB8IEFycmF5PHVua25vd24+KTogQnVmZmVyIHtcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB1dGlscy5oYXNoU3RyaW5nKHZhbCk7XG4gICAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSB8fCB2YWwgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICByZXR1cm4gdXRpbHMuaGFzaEJ5dGVzKHZhbCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnYmlnaW50JyB8fCB0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIHV0aWxzLmhhc2hVNjQoQmlnSW50KHZhbCkpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICByZXR1cm4gdXRpbHMuaGFzaEFycmF5KHZhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgdmFsdWUgdHlwZSBmb3IgaGFzaGluZzogJHt0eXBlb2YgdmFsfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlcyB0aGUgU0hBLTI1NiBoYXNoIG9mIHRoZSBnaXZlbiBidWZmZXIuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBidWZmZXIgdG8gaGFzaC5cbiAgICogQHJldHVybnMgVGhlIFNIQS0yNTYgaGFzaCBvZiB0aGUgaW5wdXQgYnVmZmVyLlxuICAgKi9cbiAgaGFzaEJ5dGVzKHZhbHVlOiBCdWZmZXIgfCBVaW50OEFycmF5KTogQnVmZmVyIHtcbiAgICByZXR1cm4gdGhpcy5zaGEyNTYoW3ZhbHVlXSk7XG4gIH1cblxuICAvKipcbiAgICogQ29tcHV0ZXMgdGhlIFNIQS0yNTYgaGFzaCBvZiB0aGUgcHJvdmlkZWQgYXJyYXkgb2YgQnVmZmVyIGNodW5rcy5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheTxCdWZmZXI+fSBjaHVua3MgLSBBbiBhcnJheSBvZiBCdWZmZXIgb2JqZWN0cyB0byBiZSBoYXNoZWQuXG4gICAqIEByZXR1cm5zIHtCdWZmZXJ9IC0gVGhlIHJlc3VsdGluZyBTSEEtMjU2IGhhc2ggYXMgYSBCdWZmZXIuXG4gICAqL1xuICBzaGEyNTYoY2h1bmtzOiBBcnJheTxCdWZmZXI+IHwgQXJyYXk8VWludDhBcnJheT4pOiBCdWZmZXIge1xuICAgIGNvbnN0IGhhc2hlciA9IGpzX3NoYTI1Ni5zaGEyNTYuY3JlYXRlKCk7XG4gICAgY2h1bmtzLmZvckVhY2goKGNodW5rKSA9PiBoYXNoZXIudXBkYXRlKGNodW5rKSk7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGhhc2hlci5hcnJheUJ1ZmZlcigpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIGhleGFkZWNpbWFsIHN0cmluZyB0byBhIEJ1ZmZlci5cbiAgICpcbiAgICogQHBhcmFtIGhleCAtIFRoZSBoZXhhZGVjaW1hbCBzdHJpbmcgdG8gY29udmVydC5cbiAgICogQHJldHVybnMgQSBCdWZmZXIgY29udGFpbmluZyB0aGUgYmluYXJ5IGRhdGEgcmVwcmVzZW50ZWQgYnkgdGhlIGhleGFkZWNpbWFsIHN0cmluZy5cbiAgICovXG4gIGJsb2JGcm9tSGV4KGhleDogc3RyaW5nKTogQnVmZmVyIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oaGV4LCAnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBiaW5hcnkgYmxvYiAoQnVmZmVyKSB0byBhIGhleGFkZWNpbWFsIHN0cmluZy5cbiAgICpcbiAgICogQHBhcmFtIHtCdWZmZXJ9IGJsb2IgLSBUaGUgYmluYXJ5IGRhdGEgdG8gYmUgY29udmVydGVkLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgaGV4YWRlY2ltYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGJpbmFyeSBkYXRhLlxuICAgKi9cbiAgYmxvYlRvSGV4KGJsb2I6IEJ1ZmZlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIGJsb2IudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY29kZXMgYSBnaXZlbiBDQk9SLWVuY29kZWQgYnVmZmVyLlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZmVyIC0gVGhlIENCT1ItZW5jb2RlZCBidWZmZXIgdG8gZGVjb2RlLlxuICAgKiBAcmV0dXJucyBUaGUgZGVjb2RlZCBkYXRhLlxuICAgKi9cbiAgY2JvckRlY29kZShidWZmZXI6IEJ1ZmZlcik6IHVua25vd24ge1xuICAgIGNvbnN0IHJlcyA9IGRlY29kZShidWZmZXIpO1xuICAgIHJldHVybiByZXM7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgQnVmZmVyIGNvbnRhaW5pbmcgdGhlIGRvbWFpbiBJQyByZXF1ZXN0IHN0cmluZy5cbiAgICpcbiAgICogQHJldHVybnMge0J1ZmZlcn0gQSBCdWZmZXIgb2JqZWN0IGluaXRpYWxpemVkIHdpdGggdGhlIHN0cmluZyAnXFx4MEFpYy1yZXF1ZXN0Jy5cbiAgICovXG4gIGdldERvbWFpbklDUmVxdWVzdCgpOiBCdWZmZXIge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbSgnXFx4MEFpYy1yZXF1ZXN0Jyk7XG4gIH1cblxuICAvKipcbiAgICogQ29tYmluZXMgdGhlIGRvbWFpbiBJQyByZXF1ZXN0IGJ1ZmZlciB3aXRoIHRoZSBwcm92aWRlZCBtZXNzYWdlIElEIGJ1ZmZlciB0byBjcmVhdGUgc2lnbmF0dXJlIGRhdGEuXG4gICAqXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBtZXNzYWdlSWQgLSBUaGUgYnVmZmVyIGNvbnRhaW5pbmcgdGhlIG1lc3NhZ2UgSUQuXG4gICAqIEByZXR1cm5zIHtCdWZmZXJ9IC0gVGhlIGNvbmNhdGVuYXRlZCBidWZmZXIgY29udGFpbmluZyB0aGUgZG9tYWluIElDIHJlcXVlc3QgYW5kIHRoZSBtZXNzYWdlIElELlxuICAgKi9cbiAgbWFrZVNpZ25hdHVyZURhdGEobWVzc2FnZUlkOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFt0aGlzLmdldERvbWFpbklDUmVxdWVzdCgpLCBtZXNzYWdlSWRdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0cyB0aGUgcmVjaXBpZW50IGluZm9ybWF0aW9uIGZyb20gdGhlIHByb3ZpZGVkIElDUCB0cmFuc2FjdGlvbiBkYXRhLlxuICAgKlxuICAgKiBAcGFyYW0ge0ljcFRyYW5zYWN0aW9uRGF0YX0gaWNwVHJhbnNhY3Rpb25EYXRhIC0gVGhlIElDUCB0cmFuc2FjdGlvbiBkYXRhIGNvbnRhaW5pbmcgdGhlIHJlY2VpdmVyJ3MgYWRkcmVzcyBhbmQgYW1vdW50LlxuICAgKiBAcmV0dXJucyB7UmVjaXBpZW50W119IEFuIGFycmF5IGNvbnRhaW5pbmcgYSBzaW5nbGUgcmVjaXBpZW50IG9iamVjdCB3aXRoIHRoZSByZWNlaXZlcidzIGFkZHJlc3MgYW5kIGFtb3VudC5cbiAgICovXG4gIGdldFJlY2lwaWVudHMoaWNwVHJhbnNhY3Rpb25EYXRhOiBJY3BUcmFuc2FjdGlvbkRhdGEpOiBSZWNpcGllbnQge1xuICAgIHJldHVybiB7XG4gICAgICBhZGRyZXNzOiBpY3BUcmFuc2FjdGlvbkRhdGEucmVjZWl2ZXJBZGRyZXNzLFxuICAgICAgYW1vdW50OiBpY3BUcmFuc2FjdGlvbkRhdGEuYW1vdW50LFxuICAgIH07XG4gIH1cblxuICBnZXRUcmFuc2FjdGlvblNpZ25hdHVyZShzaWduYXR1cmVNYXA6IE1hcDxzdHJpbmcsIFNpZ25hdHVyZXM+LCB1cGRhdGU6IEh0dHBDYW5pc3RlclVwZGF0ZSk6IFNpZ25hdHVyZXMgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBzaWduYXR1cmVNYXAuZ2V0KHRoaXMuYmxvYlRvSGV4KHRoaXMubWFrZVNpZ25hdHVyZURhdGEodGhpcy5nZW5lcmF0ZUh0dHBDYW5pc3RlclVwZGF0ZUlkKHVwZGF0ZSkpKSk7XG4gIH1cblxuICBnZXRNZXRhRGF0YShcbiAgICBtZW1vOiBudW1iZXIgfCBCaWdJbnQsXG4gICAgdGltZXN0YW1wOiBudW1iZXIgfCBiaWdpbnQgfCB1bmRlZmluZWQsXG4gICAgaW5ncmVzc0VuZDogbnVtYmVyIHwgQmlnSW50IHwgdW5kZWZpbmVkXG4gICk6IHsgbWV0YURhdGE6IE1ldGFEYXRhOyBpbmdyZXNzRW5kVGltZTogbnVtYmVyIHwgQmlnSW50IH0ge1xuICAgIGxldCBjdXJyZW50VGltZSA9IERhdGUubm93KCkgKiAxMDAwMDAwO1xuICAgIGlmICh0aW1lc3RhbXApIHtcbiAgICAgIGN1cnJlbnRUaW1lID0gTnVtYmVyKHRpbWVzdGFtcCk7XG4gICAgfVxuICAgIGxldCBpbmdyZXNzU3RhcnRUaW1lOiBudW1iZXIsIGluZ3Jlc3NFbmRUaW1lOiBudW1iZXI7XG4gICAgaWYgKGluZ3Jlc3NFbmQpIHtcbiAgICAgIGluZ3Jlc3NFbmRUaW1lID0gTnVtYmVyKGluZ3Jlc3NFbmQpO1xuICAgICAgaW5ncmVzc1N0YXJ0VGltZSA9IGluZ3Jlc3NFbmRUaW1lIC0gTUFYX0lOR1JFU1NfVFRMOyAvLyA1IG1pbnMgaW4gbmFub3NlY29uZHNcbiAgICB9IGVsc2Uge1xuICAgICAgaW5ncmVzc1N0YXJ0VGltZSA9IGN1cnJlbnRUaW1lO1xuICAgICAgaW5ncmVzc0VuZFRpbWUgPSBpbmdyZXNzU3RhcnRUaW1lICsgTUFYX0lOR1JFU1NfVFRMOyAvLyA1IG1pbnMgaW4gbmFub3NlY29uZHNcbiAgICB9XG4gICAgY29uc3QgbWV0YURhdGE6IE1ldGFEYXRhID0ge1xuICAgICAgY3JlYXRlZF9hdF90aW1lOiBjdXJyZW50VGltZSxcbiAgICAgIGluZ3Jlc3Nfc3RhcnQ6IGluZ3Jlc3NTdGFydFRpbWUsXG4gICAgICBpbmdyZXNzX2VuZDogaW5ncmVzc0VuZFRpbWUsXG4gICAgICBtZW1vOiBtZW1vLFxuICAgIH07XG5cbiAgICByZXR1cm4geyBtZXRhRGF0YSwgaW5ncmVzc0VuZFRpbWUgfTtcbiAgfVxuXG4gIGNvbnZlcnRTZW5kZXJCbG9iVG9QcmluY2lwYWwoc2VuZGVyQmxvYjogVWludDhBcnJheSk6IFVpbnQ4QXJyYXkge1xuICAgIGNvbnN0IE1BWF9MRU5HVEhfSU5fQllURVMgPSAyOTtcbiAgICBpZiAoc2VuZGVyQmxvYi5sZW5ndGggPiBNQVhfTEVOR1RIX0lOX0JZVEVTKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0J5dGVzIHRvbyBsb25nIGZvciBhIHZhbGlkIFByaW5jaXBhbCcpO1xuICAgIH1cbiAgICBjb25zdCBwcmluY2lwYWxCeXRlcyA9IG5ldyBVaW50OEFycmF5KE1BWF9MRU5HVEhfSU5fQllURVMpO1xuICAgIHByaW5jaXBhbEJ5dGVzLnNldChzZW5kZXJCbG9iLnNsaWNlKDAsIHNlbmRlckJsb2IubGVuZ3RoKSk7XG4gICAgcmV0dXJuIHByaW5jaXBhbEJ5dGVzO1xuICB9XG5cbiAgZnJvbUFyZ3MoYXJnOiBVaW50OEFycmF5KTogU2VuZEFyZ3Mge1xuICAgIGNvbnN0IFNlbmRSZXF1ZXN0TWVzc2FnZSA9IG1lc3NhZ2VDb21waWxlZC5TZW5kUmVxdWVzdDtcbiAgICBjb25zdCBhcmdzID0gU2VuZFJlcXVlc3RNZXNzYWdlLmRlY29kZShhcmcpIGFzIHVua25vd24gYXMgU2VuZEFyZ3M7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRBcmdzOiBTZW5kQXJncyA9IHtcbiAgICAgIHBheW1lbnQ6IHsgcmVjZWl2ZXJHZXRzOiB7IGU4czogTnVtYmVyKGFyZ3MucGF5bWVudC5yZWNlaXZlckdldHMuZThzKSB9IH0sXG4gICAgICBtYXhGZWU6IHsgZThzOiBOdW1iZXIoYXJncy5tYXhGZWUuZThzKSB9LFxuICAgICAgdG86IHsgaGFzaDogQnVmZmVyLmZyb20oYXJncy50by5oYXNoKSB9LFxuICAgICAgY3JlYXRlZEF0VGltZTogeyB0aW1lc3RhbXBOYW5vczogQmlnTnVtYmVyKGFyZ3MuY3JlYXRlZEF0VGltZS50aW1lc3RhbXBOYW5vcy50b1N0cmluZygpKS50b051bWJlcigpIH0sXG4gICAgICBtZW1vOiB7IG1lbW86IE51bWJlcihhcmdzLm1lbW8ubWVtby50b1N0cmluZygpKSB9LFxuICAgIH07XG4gICAgcmV0dXJuIHRyYW5zZm9ybWVkQXJncztcbiAgfVxuXG4gIGFzeW5jIHRvQXJnKGFyZ3M6IFNlbmRBcmdzKTogUHJvbWlzZTxVaW50OEFycmF5PiB7XG4gICAgY29uc3QgU2VuZFJlcXVlc3RNZXNzYWdlID0gbWVzc2FnZUNvbXBpbGVkLlNlbmRSZXF1ZXN0O1xuICAgIGNvbnN0IGVyck1zZyA9IFNlbmRSZXF1ZXN0TWVzc2FnZS52ZXJpZnkoYXJncyk7XG4gICAgaWYgKGVyck1zZykgdGhyb3cgbmV3IEVycm9yKGVyck1zZyk7XG4gICAgY29uc3QgbWVzc2FnZSA9IFNlbmRSZXF1ZXN0TWVzc2FnZS5jcmVhdGUoYXJncyBhcyBhbnkpO1xuICAgIHJldHVybiBTZW5kUmVxdWVzdE1lc3NhZ2UuZW5jb2RlKG1lc3NhZ2UpLmZpbmlzaCgpO1xuICB9XG5cbiAgZ2V0QWNjb3VudElkUHJlZml4KCk6IEJ1ZmZlcjxBcnJheUJ1ZmZlcj4ge1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShbMHgwYSwgLi4uQnVmZmVyLmZyb20oJ2FjY291bnQtaWQnKV0pO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRCbG9ja0lkKGhhc2g6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vIElDUCBibG9jayBoYXNoZXMgYXJlIDY0LWNoYXJhY3RlciBoZXhhZGVjaW1hbCBzdHJpbmdzXG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZEhhc2goaGFzaCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgc3RyaW5nIGlzIGEgdmFsaWQgSUNQIGhhc2hcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggLSBzdHJpbmcgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAqL1xuICBpc1ZhbGlkSGFzaChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHlwZW9mIGhhc2ggPT09ICdzdHJpbmcnICYmIC9eWzAtOWEtZkEtRl17NjR9JC8udGVzdChoYXNoKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkVHJhbnNhY3Rpb25JZCh0eElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkSGFzaCh0eElkKTtcbiAgfVxuXG4gIGdldFNpZ25hdHVyZXMocGF5bG9hZHNEYXRhOiBQYXlsb2Fkc0RhdGEsIHNlbmRlclB1YmxpY0tleTogc3RyaW5nLCBzZW5kZXJQcml2YXRlS2V5OiBzdHJpbmcpOiBTaWduYXR1cmVzW10ge1xuICAgIHJldHVybiBwYXlsb2Fkc0RhdGEucGF5bG9hZHMubWFwKChwYXlsb2FkKSA9PiAoe1xuICAgICAgc2lnbmluZ19wYXlsb2FkOiBwYXlsb2FkLFxuICAgICAgc2lnbmF0dXJlX3R5cGU6IHBheWxvYWQuc2lnbmF0dXJlX3R5cGUsXG4gICAgICBwdWJsaWNfa2V5OiB7XG4gICAgICAgIGhleF9ieXRlczogc2VuZGVyUHVibGljS2V5LFxuICAgICAgICBjdXJ2ZV90eXBlOiBDdXJ2ZVR5cGUuU0VDUDI1NksxLFxuICAgICAgfSxcbiAgICAgIGhleF9ieXRlczogdGhpcy5zaWduUGF5bG9hZChzZW5kZXJQcml2YXRlS2V5LCBwYXlsb2FkLmhleF9ieXRlcyksXG4gICAgfSkpO1xuICB9XG5cbiAgc2lnblBheWxvYWQgPSAocHJpdmF0ZUtleTogc3RyaW5nLCBwYXlsb2FkSGV4OiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgIGNvbnN0IHByaXZhdGVLZXlCeXRlcyA9IEJ1ZmZlci5mcm9tKHByaXZhdGVLZXksICdoZXgnKTtcbiAgICBjb25zdCBwYXlsb2FkSGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoQnVmZmVyLmZyb20ocGF5bG9hZEhleCwgJ2hleCcpKS5kaWdlc3QoJ2hleCcpO1xuICAgIGNvbnN0IHNpZ25hdHVyZSA9IHNlY3AyNTZrMS5zaWduKHBheWxvYWRIYXNoLCBwcml2YXRlS2V5Qnl0ZXMpO1xuICAgIGNvbnN0IHIgPSBCdWZmZXIuZnJvbShzaWduYXR1cmUuci50b1N0cmluZygxNikucGFkU3RhcnQoNjQsICcwJyksICdoZXgnKTtcbiAgICBjb25zdCBzID0gQnVmZmVyLmZyb20oc2lnbmF0dXJlLnMudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDY0LCAnMCcpLCAnaGV4Jyk7XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoW3IsIHNdKS50b1N0cmluZygnaGV4Jyk7XG4gIH07XG5cbiAgZ2V0VHJhbnNhY3Rpb25JZCh1bnNpZ25lZFRyYW5zYWN0aW9uOiBzdHJpbmcsIHNlbmRlckFkZHJlc3M6IHN0cmluZywgcmVjZWl2ZXJBZGRyZXNzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkVHhuID0gdXRpbHMuY2JvckRlY29kZSh1dGlscy5ibG9iRnJvbUhleCh1bnNpZ25lZFRyYW5zYWN0aW9uKSkgYXMgQ2JvclVuc2lnbmVkVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB1cGRhdGVzID0gZGVjb2RlZFR4bi51cGRhdGVzIGFzIHVua25vd24gYXMgW3N0cmluZywgSHR0cENhbmlzdGVyVXBkYXRlXVtdO1xuICAgICAgZm9yIChjb25zdCBbLCB1cGRhdGVdIG9mIHVwZGF0ZXMpIHtcbiAgICAgICAgY29uc3QgdXBkYXRlQXJncyA9IHVwZGF0ZS5hcmc7XG4gICAgICAgIGNvbnN0IHNlbmRBcmdzID0gdXRpbHMuZnJvbUFyZ3ModXBkYXRlQXJncyk7XG4gICAgICAgIGNvbnN0IHRyYW5zYWN0aW9uSGFzaCA9IHRoaXMuZ2VuZXJhdGVUcmFuc2FjdGlvbkhhc2goc2VuZEFyZ3MsIHNlbmRlckFkZHJlc3MsIHJlY2VpdmVyQWRkcmVzcyk7XG4gICAgICAgIHJldHVybiB0cmFuc2FjdGlvbkhhc2g7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHVwZGF0ZXMgZm91bmQgaW4gdGhlIHVuc2lnbmVkIHRyYW5zYWN0aW9uLicpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBjb21wdXRlIHRyYW5zYWN0aW9uIElEOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfVxuICB9XG5cbiAgc2FmZUJpZ0ludCh2YWx1ZTogdW5rbm93bik6IG51bWJlciB8IGJpZ2ludCB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2JpZ2ludCcpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgY29uc3QgTUFYXzMyQklUID0gNDI5NDk2NzI5NTsgLy8gMl4zMiAtIDFcbiAgICAgIGNvbnN0IE1JTl8zMkJJVCA9IC00Mjk0OTY3Mjk2OyAvLyAtKDJeMzIpXG4gICAgICBjb25zdCBpc091dHNpZGUzMkJpdFJhbmdlID0gdmFsdWUgPiBNQVhfMzJCSVQgfHwgdmFsdWUgPCBNSU5fMzJCSVQ7XG4gICAgICByZXR1cm4gaXNPdXRzaWRlMzJCaXRSYW5nZSA/IEJpZ0ludCh2YWx1ZSkgOiB2YWx1ZTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdHlwZTogZXhwZWN0ZWQgYSBudW1iZXIgb3IgYmlnaW50LCBidXQgcmVjZWl2ZWQgJHt0eXBlb2YgdmFsdWV9YCk7XG4gIH1cblxuICBnZW5lcmF0ZVRyYW5zYWN0aW9uSGFzaChzZW5kQXJnczogU2VuZEFyZ3MsIHNlbmRlckFkZHJlc3M6IHN0cmluZywgcmVjZWl2ZXJBZGRyZXNzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHNlbmRlckFjY291bnQgPSB0aGlzLmFjY291bnRJZGVudGlmaWVyKHNlbmRlckFkZHJlc3MpO1xuICAgIGNvbnN0IHJlY2VpdmVyQWNjb3VudCA9IHRoaXMuYWNjb3VudElkZW50aWZpZXIocmVjZWl2ZXJBZGRyZXNzKTtcblxuICAgIGNvbnN0IHRyYW5zZmVyRmllbGRzID0gbmV3IE1hcDxhbnksIGFueT4oW1xuICAgICAgWzAsIHNlbmRlckFjY291bnRdLFxuICAgICAgWzEsIHJlY2VpdmVyQWNjb3VudF0sXG4gICAgICBbMiwgbmV3IE1hcChbWzAsIHRoaXMuc2FmZUJpZ0ludChzZW5kQXJncy5wYXltZW50LnJlY2VpdmVyR2V0cy5lOHMpXV0pXSxcbiAgICAgIFszLCBuZXcgTWFwKFtbMCwgc2VuZEFyZ3MubWF4RmVlLmU4c11dKV0sXG4gICAgXSk7XG5cbiAgICBjb25zdCBvcGVyYXRpb25NYXAgPSBuZXcgTWFwKFtbMiwgdHJhbnNmZXJGaWVsZHNdXSk7XG4gICAgY29uc3QgdHhuRmllbGRzID0gbmV3IE1hcDxhbnksIGFueT4oW1xuICAgICAgWzAsIG9wZXJhdGlvbk1hcF0sXG4gICAgICBbMSwgdGhpcy5zYWZlQmlnSW50KHNlbmRBcmdzLm1lbW8ubWVtbyldLFxuICAgICAgWzIsIG5ldyBNYXAoW1swLCBCaWdJbnQoc2VuZEFyZ3MuY3JlYXRlZEF0VGltZS50aW1lc3RhbXBOYW5vcyldXSldLFxuICAgIF0pO1xuXG4gICAgY29uc3QgcHJvY2Vzc2VkVHhuID0gdGhpcy5nZXRQcm9jZXNzZWRUcmFuc2FjdGlvbk1hcCh0eG5GaWVsZHMpO1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeG4gPSBlbmNvZGVyLmVuY29kZShwcm9jZXNzZWRUeG4pO1xuICAgIHJldHVybiBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHNlcmlhbGl6ZWRUeG4pLmRpZ2VzdCgnaGV4Jyk7XG4gIH1cblxuICBhY2NvdW50SWRlbnRpZmllcihhY2NvdW50QWRkcmVzczogc3RyaW5nKTogQWNjb3VudElkZW50aWZpZXJIYXNoIHtcbiAgICBjb25zdCBieXRlcyA9IEJ1ZmZlci5mcm9tKGFjY291bnRBZGRyZXNzLCAnaGV4Jyk7XG4gICAgaWYgKGJ5dGVzLmxlbmd0aCA9PT0gMzIpIHtcbiAgICAgIHJldHVybiB7IGhhc2g6IGJ5dGVzLnNsaWNlKDQpIH07XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBBY2NvdW50SWRlbnRpZmllcjogNjQgaGV4IGNoYXJzLCBnb3QgJHthY2NvdW50QWRkcmVzcy5sZW5ndGh9YCk7XG4gIH1cblxuICBnZXRQcm9jZXNzZWRUcmFuc2FjdGlvbk1hcCh0eG5NYXA6IE1hcDxhbnksIGFueT4pOiBNYXA8YW55LCBhbnk+IHtcbiAgICBjb25zdCBvcGVyYXRpb25NYXAgPSB0eG5NYXAuZ2V0KDApO1xuICAgIGNvbnN0IHRyYW5zZmVyTWFwID0gb3BlcmF0aW9uTWFwLmdldCgyKTtcbiAgICB0cmFuc2Zlck1hcC5zZXQoMCwgdGhpcy5zZXJpYWxpemVBY2NvdW50SWRlbnRpZmllcih0cmFuc2Zlck1hcC5nZXQoMCkpKTtcbiAgICB0cmFuc2Zlck1hcC5zZXQoMSwgdGhpcy5zZXJpYWxpemVBY2NvdW50SWRlbnRpZmllcih0cmFuc2Zlck1hcC5nZXQoMSkpKTtcbiAgICByZXR1cm4gdHhuTWFwO1xuICB9XG5cbiAgc2VyaWFsaXplQWNjb3VudElkZW50aWZpZXIoYWNjb3VudEhhc2g6IEFjY291bnRJZGVudGlmaWVySGFzaCk6IHN0cmluZyB7XG4gICAgaWYgKGFjY291bnRIYXNoICYmIGFjY291bnRIYXNoLmhhc2gpIHtcbiAgICAgIGNvbnN0IGhhc2hCdWZmZXIgPSBhY2NvdW50SGFzaC5oYXNoO1xuICAgICAgY29uc3QgY2hlY2tzdW0gPSBCdWZmZXIuYWxsb2MoNCk7XG4gICAgICBjaGVja3N1bS53cml0ZVVJbnQzMkJFKGNyYzMyLmJ1ZihoYXNoQnVmZmVyKSA+Pj4gMCwgMCk7XG4gICAgICByZXR1cm4gQnVmZmVyLmNvbmNhdChbY2hlY2tzdW0sIGhhc2hCdWZmZXJdKS50b1N0cmluZygnaGV4JykudG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGFjY291bnRIYXNoIGZvcm1hdCcpO1xuICB9XG59XG5cbmNvbnN0IHV0aWxzID0gbmV3IFV0aWxzKCk7XG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==