@bitgo-beta/sdk-coin-flrp 1.0.1-beta.40 → 1.0.1-beta.401

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 (122) hide show
  1. package/dist/src/flrp.d.ts +10 -17
  2. package/dist/src/flrp.d.ts.map +1 -1
  3. package/dist/src/flrp.js +51 -77
  4. package/dist/src/index.d.ts +0 -1
  5. package/dist/src/index.d.ts.map +1 -1
  6. package/dist/src/index.js +1 -2
  7. package/dist/src/lib/ExportInCTxBuilder.d.ts +43 -0
  8. package/dist/src/lib/ExportInCTxBuilder.d.ts.map +1 -0
  9. package/dist/src/lib/ExportInCTxBuilder.js +150 -0
  10. package/dist/src/lib/ExportInPTxBuilder.d.ts +28 -0
  11. package/dist/src/lib/ExportInPTxBuilder.d.ts.map +1 -0
  12. package/dist/src/lib/ExportInPTxBuilder.js +190 -0
  13. package/dist/src/lib/ImportInCTxBuilder.d.ts +34 -0
  14. package/dist/src/lib/ImportInCTxBuilder.d.ts.map +1 -0
  15. package/dist/src/lib/ImportInCTxBuilder.js +191 -0
  16. package/dist/src/lib/ImportInPTxBuilder.d.ts +38 -0
  17. package/dist/src/lib/ImportInPTxBuilder.d.ts.map +1 -0
  18. package/dist/src/lib/ImportInPTxBuilder.js +224 -0
  19. package/dist/src/lib/atomicInCTransactionBuilder.d.ts +12 -16
  20. package/dist/src/lib/atomicInCTransactionBuilder.d.ts.map +1 -1
  21. package/dist/src/lib/atomicInCTransactionBuilder.js +30 -41
  22. package/dist/src/lib/atomicTransactionBuilder.d.ts +126 -69
  23. package/dist/src/lib/atomicTransactionBuilder.d.ts.map +1 -1
  24. package/dist/src/lib/atomicTransactionBuilder.js +320 -211
  25. package/dist/src/lib/iface.d.ts +65 -57
  26. package/dist/src/lib/iface.d.ts.map +1 -1
  27. package/dist/src/lib/iface.js +20 -14
  28. package/dist/src/lib/index.d.ts +5 -0
  29. package/dist/src/lib/index.d.ts.map +1 -1
  30. package/dist/src/lib/index.js +12 -2
  31. package/dist/src/lib/keyPair.d.ts +5 -5
  32. package/dist/src/lib/keyPair.d.ts.map +1 -1
  33. package/dist/src/lib/keyPair.js +17 -9
  34. package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts +41 -0
  35. package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts.map +1 -0
  36. package/dist/src/lib/permissionlessValidatorTxBuilder.js +126 -0
  37. package/dist/src/lib/transaction.d.ts +30 -66
  38. package/dist/src/lib/transaction.d.ts.map +1 -1
  39. package/dist/src/lib/transaction.js +347 -199
  40. package/dist/src/lib/transactionBuilder.d.ts +115 -0
  41. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  42. package/dist/src/lib/transactionBuilder.js +228 -0
  43. package/dist/src/lib/transactionBuilderFactory.d.ts +50 -30
  44. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
  45. package/dist/src/lib/transactionBuilderFactory.js +129 -72
  46. package/dist/src/lib/utils.d.ts +131 -146
  47. package/dist/src/lib/utils.d.ts.map +1 -1
  48. package/dist/src/lib/utils.js +344 -321
  49. package/dist/test/resources/account.d.ts +81 -0
  50. package/dist/test/resources/account.d.ts.map +1 -0
  51. package/dist/test/resources/account.js +79 -0
  52. package/dist/test/resources/transactionData/exportInC.d.ts +50 -0
  53. package/dist/test/resources/transactionData/exportInC.d.ts.map +1 -0
  54. package/dist/test/resources/transactionData/exportInC.js +58 -0
  55. package/dist/test/resources/transactionData/exportInP.d.ts +60 -0
  56. package/dist/test/resources/transactionData/exportInP.d.ts.map +1 -0
  57. package/dist/test/resources/transactionData/exportInP.js +101 -0
  58. package/dist/test/resources/transactionData/importInC.d.ts +56 -0
  59. package/dist/test/resources/transactionData/importInC.d.ts.map +1 -0
  60. package/dist/test/resources/transactionData/importInC.js +120 -0
  61. package/dist/test/resources/transactionData/importInP.d.ts +66 -0
  62. package/dist/test/resources/transactionData/importInP.d.ts.map +1 -0
  63. package/dist/test/resources/transactionData/importInP.js +84 -0
  64. package/dist/test/unit/flrp.js +449 -68
  65. package/dist/test/unit/lib/exportInCTxBuilder.d.ts +2 -0
  66. package/dist/test/unit/lib/exportInCTxBuilder.d.ts.map +1 -0
  67. package/dist/test/unit/lib/exportInCTxBuilder.js +193 -0
  68. package/dist/test/unit/lib/exportInPTxBuilder.d.ts +2 -0
  69. package/dist/test/unit/lib/exportInPTxBuilder.d.ts.map +1 -0
  70. package/dist/test/unit/lib/exportInPTxBuilder.js +296 -0
  71. package/dist/test/unit/lib/importInCTxBuilder.d.ts +2 -0
  72. package/dist/test/unit/lib/importInCTxBuilder.d.ts.map +1 -0
  73. package/dist/test/unit/lib/importInCTxBuilder.js +309 -0
  74. package/dist/test/unit/lib/importInPTxBuilder.d.ts +2 -0
  75. package/dist/test/unit/lib/importInPTxBuilder.d.ts.map +1 -0
  76. package/dist/test/unit/lib/importInPTxBuilder.js +490 -0
  77. package/dist/test/unit/lib/keyPair.d.ts +2 -0
  78. package/dist/test/unit/lib/keyPair.d.ts.map +1 -0
  79. package/dist/test/unit/lib/keyPair.js +158 -0
  80. package/dist/test/unit/lib/signFlowTestSuit.d.ts +20 -0
  81. package/dist/test/unit/lib/signFlowTestSuit.d.ts.map +1 -0
  82. package/dist/test/unit/lib/signFlowTestSuit.js +83 -0
  83. package/dist/test/unit/lib/signatureIndex.d.ts +13 -0
  84. package/dist/test/unit/lib/signatureIndex.d.ts.map +1 -0
  85. package/dist/test/unit/lib/signatureIndex.js +1173 -0
  86. package/dist/test/unit/lib/transactionBuilderFactory.d.ts +2 -0
  87. package/dist/test/unit/lib/transactionBuilderFactory.d.ts.map +1 -0
  88. package/dist/test/unit/lib/transactionBuilderFactory.js +60 -0
  89. package/dist/test/unit/lib/utils.js +681 -206
  90. package/dist/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +20 -11
  92. package/.eslintignore +0 -5
  93. package/.eslintrc.json +0 -7
  94. package/.mocharc.yml +0 -8
  95. package/CHANGELOG.md +0 -0
  96. package/dist/src/iface.d.ts +0 -25
  97. package/dist/src/iface.d.ts.map +0 -1
  98. package/dist/src/iface.js +0 -3
  99. package/dist/src/lib/constants.d.ts +0 -11
  100. package/dist/src/lib/constants.d.ts.map +0 -1
  101. package/dist/src/lib/constants.js +0 -17
  102. package/dist/src/lib/errors.d.ts +0 -8
  103. package/dist/src/lib/errors.d.ts.map +0 -1
  104. package/dist/src/lib/errors.js +0 -19
  105. package/dist/src/lib/exportInCTxBuilder.d.ts +0 -77
  106. package/dist/src/lib/exportInCTxBuilder.d.ts.map +0 -1
  107. package/dist/src/lib/exportInCTxBuilder.js +0 -170
  108. package/dist/src/lib/exportInPTxBuilder.d.ts +0 -30
  109. package/dist/src/lib/exportInPTxBuilder.d.ts.map +0 -1
  110. package/dist/src/lib/exportInPTxBuilder.js +0 -56
  111. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts +0 -2
  112. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts.map +0 -1
  113. package/dist/test/unit/lib/atomicTransactionBuilder.js +0 -222
  114. package/dist/test/unit/lib/exportTxBuilder.d.ts +0 -2
  115. package/dist/test/unit/lib/exportTxBuilder.d.ts.map +0 -1
  116. package/dist/test/unit/lib/exportTxBuilder.js +0 -45
  117. package/dist/test/unit/lib/transaction.d.ts +0 -2
  118. package/dist/test/unit/lib/transaction.d.ts.map +0 -1
  119. package/dist/test/unit/lib/transaction.js +0 -460
  120. package/dist/test/unit/smoke.d.ts +0 -2
  121. package/dist/test/unit/smoke.d.ts.map +0 -1
  122. package/dist/test/unit/smoke.js +0 -23
@@ -1,27 +1,79 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Utils = void 0;
7
+ const flarejs_1 = require("@flarenetwork/flarejs");
4
8
  const sdk_core_1 = require("@bitgo-beta/sdk-core");
5
- const secp256k1_1 = require("@bitgo-beta/secp256k1");
9
+ const buffer_1 = require("buffer");
6
10
  const crypto_1 = require("crypto");
7
- const constants_1 = require("./constants");
11
+ const secp256k1_1 = require("@bitgo-beta/secp256k1");
12
+ const iface_1 = require("./iface");
13
+ const bs58_1 = __importDefault(require("bs58"));
14
+ const bech32_1 = require("bech32");
8
15
  class Utils {
9
16
  constructor() {
10
- this.parseAddress = (pub) => {
11
- // FlareJS equivalent for address parsing
12
- return Buffer.from(pub, 'hex'); // Simplified implementation
17
+ /**
18
+ * Helper method to convert address components to string
19
+ */
20
+ this.addressToString = (hrp, prefix, address) => {
21
+ // Convert the address bytes to 5-bit words for bech32 encoding
22
+ const words = bech32_1.bech32.toWords(address);
23
+ // Create the full bech32 address with format: P-{hrp}1{bech32_encoded_address}
24
+ return `${prefix}-${bech32_1.bech32.encode(hrp, words)}`;
25
+ };
26
+ // In utils.ts, add this method to the Utils class:
27
+ /**
28
+ * Parse an address string into a Buffer
29
+ * @param address - The address to parse
30
+ * @returns Buffer containing the parsed address
31
+ */
32
+ this.parseAddress = (address) => {
33
+ return this.stringToAddress(address);
34
+ };
35
+ this.stringToAddress = (address, hrp) => {
36
+ // Handle hex addresses
37
+ if (address.startsWith('0x')) {
38
+ return buffer_1.Buffer.from(address.slice(2), 'hex');
39
+ }
40
+ // Handle raw hex without 0x prefix
41
+ if (/^[0-9a-fA-F]{40}$/.test(address)) {
42
+ return buffer_1.Buffer.from(address, 'hex');
43
+ }
44
+ // Handle Bech32 addresses
45
+ const parts = address.trim().split('-');
46
+ if (parts.length < 2) {
47
+ throw new Error('Error - Valid address should include -');
48
+ }
49
+ const split = parts[1].lastIndexOf('1');
50
+ if (split < 0) {
51
+ throw new Error('Error - Valid bech32 address must include separator (1)');
52
+ }
53
+ const humanReadablePart = parts[1].slice(0, split);
54
+ if (humanReadablePart !== 'flare' && humanReadablePart !== 'costwo') {
55
+ throw new Error('Error - Invalid HRP');
56
+ }
57
+ return buffer_1.Buffer.from(bech32_1.bech32.fromWords(bech32_1.bech32.decode(parts[1]).words));
13
58
  };
14
59
  }
60
+ isValidTransactionId(txId) {
61
+ throw new Error('Method not implemented.');
62
+ }
63
+ isValidSignature(signature) {
64
+ throw new Error('Method not implemented.');
65
+ }
66
+ /**
67
+ * Check if addresses in wallet match UTXO output addresses
68
+ */
15
69
  includeIn(walletAddresses, otxoOutputAddresses) {
16
70
  return walletAddresses.map((a) => otxoOutputAddresses.includes(a)).reduce((a, b) => a && b, true);
17
71
  }
18
72
  /**
19
- * Checks if it is a valid address no illegal characters
20
- *
21
- * @param {string} address - address to be validated
22
- * @returns {boolean} - the validation result
73
+ * Validates a Flare address or array of addresses
74
+ * @param {string | string[]} address - address(es) to validate
75
+ * @returns {boolean} - validation result
23
76
  */
24
- /** @inheritdoc */
25
77
  isValidAddress(address) {
26
78
  const addressArr = Array.isArray(address) ? address : address.split('~');
27
79
  for (const address of addressArr) {
@@ -32,65 +84,53 @@ class Utils {
32
84
  return true;
33
85
  }
34
86
  isValidAddressRegex(address) {
35
- return constants_1.ADDRESS_REGEX.test(address);
87
+ return /^(^P||NodeID)-[a-zA-Z0-9]+$/.test(address);
36
88
  }
37
89
  /**
38
- * Checks if it is a valid blockId with length 66 including 0x
39
- *
40
- * @param {string} hash - blockId to be validated
41
- * @returns {boolean} - the validation result
90
+ * Validates a block ID
91
+ * @param {string} hash - block ID to validate
92
+ * @returns {boolean} - validation result
42
93
  */
43
- /** @inheritdoc */
44
94
  isValidBlockId(hash) {
45
- // FlareJS equivalent - check if it's a valid CB58 hash with correct length
46
95
  try {
47
- const decoded = Buffer.from(hash); // FlareJS should provide CB58 utilities
48
- return decoded.length === constants_1.DECODED_BLOCK_ID_LENGTH;
96
+ const decoded = buffer_1.Buffer.from(hash, 'hex');
97
+ return decoded.length === 32;
49
98
  }
50
99
  catch {
51
100
  return false;
52
101
  }
53
102
  }
54
103
  /**
55
- * Checks if the string is a valid protocol public key or
56
- * extended public key.
57
- *
58
- * @param {string} pub - the public key to be validated
59
- * @returns {boolean} - the validation result
104
+ * Validates a public key
105
+ * @param {string} pub - public key to validate
106
+ * @returns {boolean} - validation result
60
107
  */
61
108
  isValidPublicKey(pub) {
62
109
  if ((0, sdk_core_1.isValidXpub)(pub))
63
110
  return true;
64
111
  let pubBuf;
65
- if (pub.length === constants_1.SHORT_PUB_KEY_LENGTH) {
112
+ if (pub.length === 50) {
66
113
  try {
67
- // For FlareJS, we'll need to implement CB58 decode functionality
68
- pubBuf = Buffer.from(pub, 'hex'); // Temporary placeholder
114
+ pubBuf = buffer_1.Buffer.from(pub, 'hex');
69
115
  }
70
116
  catch {
71
117
  return false;
72
118
  }
73
119
  }
74
120
  else {
75
- if (pub.length !== constants_1.COMPRESSED_PUBLIC_KEY_LENGTH && pub.length !== constants_1.UNCOMPRESSED_PUBLIC_KEY_LENGTH) {
121
+ if (pub.length !== 66 && pub.length !== 130)
76
122
  return false;
77
- }
78
123
  const firstByte = pub.slice(0, 2);
79
- // uncompressed public key
80
- if (pub.length === constants_1.UNCOMPRESSED_PUBLIC_KEY_LENGTH && firstByte !== '04') {
124
+ if (pub.length === 130 && firstByte !== '04')
81
125
  return false;
82
- }
83
- // compressed public key
84
- if (pub.length === constants_1.COMPRESSED_PUBLIC_KEY_LENGTH && firstByte !== '02' && firstByte !== '03') {
126
+ if (pub.length === 66 && firstByte !== '02' && firstByte !== '03')
85
127
  return false;
86
- }
87
128
  if (!this.allHexChars(pub))
88
129
  return false;
89
- pubBuf = Buffer.from(pub, 'hex');
130
+ pubBuf = buffer_1.Buffer.from(pub, 'hex');
90
131
  }
91
- // validate the public key using BitGo secp256k1
92
132
  try {
93
- secp256k1_1.ecc.isPoint(pubBuf); // Check if it's a valid point
133
+ secp256k1_1.ecc.isPoint(pubBuf);
94
134
  return true;
95
135
  }
96
136
  catch (e) {
@@ -98,269 +138,134 @@ class Utils {
98
138
  }
99
139
  }
100
140
  /**
101
- * Returns whether or not the string is a valid protocol private key, or extended
102
- * private key.
103
- *
104
- * The protocol key format is described in the @stacks/transactions npm package, in the
105
- * createStacksPrivateKey function:
106
- * https://github.com/blockstack/stacks.js/blob/master/packages/transactions/src/keys.ts#L125
107
- *
108
- * @param {string} prv - the private key (or extended private key) to be validated
109
- * @returns {boolean} - the validation result
141
+ * Validates a private key
142
+ * @param {string} prv - private key to validate
143
+ * @returns {boolean} - validation result
110
144
  */
111
145
  isValidPrivateKey(prv) {
112
146
  if ((0, sdk_core_1.isValidXprv)(prv))
113
147
  return true;
114
- if (prv.length !== constants_1.RAW_PRIVATE_KEY_LENGTH && prv.length !== constants_1.SUFFIXED_PRIVATE_KEY_LENGTH) {
148
+ if (prv.length !== 64 && prv.length !== 66)
115
149
  return false;
116
- }
117
- if (prv.length === constants_1.SUFFIXED_PRIVATE_KEY_LENGTH &&
118
- prv.slice(constants_1.RAW_PRIVATE_KEY_LENGTH) !== constants_1.PRIVATE_KEY_COMPRESSED_SUFFIX) {
150
+ if (prv.length === 66 && prv.slice(64) !== '01')
119
151
  return false;
120
- }
121
152
  return this.allHexChars(prv);
122
153
  }
123
154
  /**
124
- * Returns whether or not the string is a composed of hex chars only
125
- *
126
- * @param {string} maybe - the string to be validated
127
- * @returns {boolean} - the validation result
155
+ * Checks if a string contains only hex characters
128
156
  */
129
- allHexChars(maybe) {
130
- return constants_1.HEX_REGEX.test(maybe);
157
+ allHexChars(str) {
158
+ return /^(0x){0,1}([0-9a-f])+$/i.test(str);
131
159
  }
132
160
  /**
133
- * Lightweight Ethereum address validation
134
- * Validates that an address is a 40-character hex string (optionally prefixed with 0x)
135
- *
136
- * @param {string} address - the Ethereum address to validate
137
- * @returns {boolean} - true if valid Ethereum address format
161
+ * Creates a signature using the Flare network parameters
162
+ * Returns a 65-byte signature (64 bytes signature + 1 byte recovery parameter)
138
163
  */
139
- isValidEthereumAddress(address) {
140
- if (!address || typeof address !== 'string') {
141
- return false;
164
+ createSignature(network, message, prv) {
165
+ const messageHash = this.sha256(message);
166
+ const signature = secp256k1_1.ecc.sign(messageHash, prv);
167
+ // Get the public key from the private key for recovery parameter determination
168
+ const publicKey = secp256k1_1.ecc.pointFromScalar(prv, true);
169
+ if (!publicKey) {
170
+ throw new Error('Failed to derive public key from private key');
142
171
  }
143
- // Remove 0x prefix if present
144
- const cleanAddress = address.startsWith('0x') ? address.slice(2) : address;
145
- // Check if it's exactly 40 hex characters
146
- return cleanAddress.length === 40 && /^[0-9a-fA-F]{40}$/.test(cleanAddress);
147
- }
148
- /**
149
- * Pick specific properties from an object (replaces lodash.pick)
150
- *
151
- * @param {T} obj - the source object
152
- * @param {K[]} keys - array of property keys to pick
153
- * @returns {Pick<T, K>} - new object with only the specified properties
154
- */
155
- pick(obj, keys) {
156
- const result = {};
157
- for (const key of keys) {
158
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
159
- result[key] = obj[key];
172
+ // Try recovery with param 0 and 1 to find the correct one
173
+ let recoveryParam = 0;
174
+ for (let i = 0; i <= 1; i++) {
175
+ const recovered = secp256k1_1.ecc.recoverPublicKey(messageHash, signature, i, true);
176
+ if (recovered && buffer_1.Buffer.from(recovered).equals(buffer_1.Buffer.from(publicKey))) {
177
+ recoveryParam = i;
178
+ break;
160
179
  }
161
180
  }
162
- return result;
181
+ // Append recovery parameter to create 65-byte signature
182
+ const sigWithRecovery = buffer_1.Buffer.alloc(65);
183
+ buffer_1.Buffer.from(signature).copy(sigWithRecovery, 0);
184
+ sigWithRecovery[64] = recoveryParam;
185
+ return sigWithRecovery;
163
186
  }
164
187
  /**
165
- * Deep equality comparison (replaces lodash.isEqual)
166
- *
167
- * @param {unknown} a - first value to compare
168
- * @param {unknown} b - second value to compare
169
- * @returns {boolean} - true if values are deeply equal
188
+ * Verifies a signature
189
+ * @param messageHash - The SHA256 hash of the message (e.g., signablePayload)
190
+ * @param signature - The 64-byte signature (without recovery parameter)
191
+ * @param publicKey - The public key to verify against
192
+ * @returns true if signature is valid
170
193
  */
171
- isEqual(a, b) {
172
- if (a === b)
173
- return true;
174
- if (a === null || a === undefined || b === null || b === undefined)
175
- return a === b;
176
- if (typeof a !== typeof b)
194
+ verifySignature(messageHash, signature, publicKey) {
195
+ try {
196
+ return secp256k1_1.ecc.verify(messageHash, publicKey, signature);
197
+ }
198
+ catch (e) {
177
199
  return false;
178
- if (typeof a === 'object') {
179
- if (Array.isArray(a) !== Array.isArray(b))
180
- return false;
181
- if (Array.isArray(a)) {
182
- const arrB = b;
183
- if (a.length !== arrB.length)
184
- return false;
185
- for (let i = 0; i < a.length; i++) {
186
- if (!this.isEqual(a[i], arrB[i]))
187
- return false;
188
- }
189
- return true;
190
- }
191
- const objA = a;
192
- const objB = b;
193
- const keysA = Object.keys(objA);
194
- const keysB = Object.keys(objB);
195
- if (keysA.length !== keysB.length)
196
- return false;
197
- for (const key of keysA) {
198
- if (!keysB.includes(key))
199
- return false;
200
- if (!this.isEqual(objA[key], objB[key]))
201
- return false;
202
- }
203
- return true;
204
200
  }
205
- return false;
206
- }
207
- /** @inheritdoc */
208
- isValidSignature(signature) {
209
- throw new sdk_core_1.NotImplementedError('isValidSignature not implemented');
210
- }
211
- /** @inheritdoc */
212
- isValidTransactionId(txId) {
213
- throw new sdk_core_1.NotImplementedError('isValidTransactionId not implemented');
214
201
  }
215
202
  /**
216
- * FlareJS wrapper to create signature and return it for credentials
217
- * @param network
218
- * @param message
219
- * @param prv
220
- * @return signature
203
+ * Creates a new signature object
221
204
  */
222
- createSignature(network, message, prv) {
223
- // Use BitGo secp256k1 since FlareJS may not expose KeyPair in the same way
224
- try {
225
- const signature = secp256k1_1.ecc.sign(message, prv);
226
- return Buffer.from(signature);
227
- }
228
- catch (error) {
229
- throw new Error(`Failed to create signature: ${error}`);
230
- }
205
+ createNewSig(sigHex) {
206
+ const buffer = buffer_1.Buffer.from(sigHex.padStart(130, '0'), 'hex');
207
+ return new flarejs_1.Signature(buffer);
231
208
  }
232
209
  /**
233
- * FlareJS wrapper to verify signature
234
- * @param network
235
- * @param message
236
- * @param signature
237
- * @param publicKey - public key instead of private key for verification
238
- * @return true if it's verify successful
210
+ * Creates an empty signature with embedded address for signature slot identification.
211
+ * The address is embedded at position 90 (after the first 45 zero bytes).
212
+ * This allows the signing logic to determine which slot belongs to which address.
213
+ * @param addressHex The 20-byte address in hex format (40 chars, without 0x prefix)
239
214
  */
240
- verifySignature(network, message, signature, publicKey) {
241
- try {
242
- return secp256k1_1.ecc.verify(message, publicKey, signature);
243
- }
244
- catch (error) {
245
- return false;
246
- }
215
+ createEmptySigWithAddress(addressHex) {
216
+ // First 45 bytes (90 hex chars) are zeros, followed by 20-byte address (40 hex chars)
217
+ const cleanAddr = this.removeHexPrefix(addressHex).toLowerCase();
218
+ const sigHex = '0'.repeat(90) + cleanAddr.padStart(40, '0');
219
+ const buffer = buffer_1.Buffer.from(sigHex, 'hex');
220
+ return new flarejs_1.Signature(buffer);
247
221
  }
248
222
  /**
249
- * FlareJS wrapper to recover signature
250
- * @param network
251
- * @param message
252
- * @param signature
253
- * @return recovered public key
223
+ * Extracts the embedded address from an empty signature.
224
+ * Returns the address hex string (40 chars) or empty string if not found.
254
225
  */
255
- recoverySignature(network, message, signature) {
256
- try {
257
- // This would need to be implemented with secp256k1 recovery
258
- // For now, throwing error since recovery logic would need to be adapted
259
- throw new sdk_core_1.NotImplementedError('recoverySignature not fully implemented for FlareJS');
260
- }
261
- catch (error) {
262
- throw new Error(`Failed to recover signature: ${error}`);
226
+ getAddressFromEmptySig(sig) {
227
+ const cleanSig = this.removeHexPrefix(sig);
228
+ if (cleanSig.length >= 130) {
229
+ // Address is at position 90-130 (last 40 hex chars = 20 bytes)
230
+ return cleanSig.substring(90, 130).toLowerCase();
263
231
  }
232
+ return '';
264
233
  }
234
+ /**
235
+ * Computes SHA256 hash
236
+ */
265
237
  sha256(buf) {
266
238
  return (0, crypto_1.createHash)('sha256').update(buf).digest();
267
239
  }
268
240
  /**
269
- * Check the raw transaction has a valid format in the blockchain context, throw otherwise.
270
- * It's to reuse in TransactionBuilder and TransactionBuilderFactory
271
- *
272
- * @param rawTransaction Transaction as hex string
241
+ * Validates raw transaction format
273
242
  */
274
243
  validateRawTransaction(rawTransaction) {
275
244
  if (!rawTransaction) {
276
245
  throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
277
246
  }
278
- if (!utils.allHexChars(rawTransaction)) {
247
+ if (!this.allHexChars(rawTransaction)) {
279
248
  throw new sdk_core_1.ParseTransactionError('Raw transaction is not hex string');
280
249
  }
281
250
  }
282
251
  /**
283
- * Check if tx is for the blockchainId
284
- *
285
- * @param {DeprecatedTx} tx
286
- * @param {string} blockchainId
287
- * @returns true if tx is for blockchainId
288
- */
289
- isTransactionOf(tx, blockchainId) {
290
- // FlareJS equivalent - this would need proper CB58 encoding implementation
291
- try {
292
- const txRecord = tx;
293
- const unsignedTx = txRecord.getUnsignedTx();
294
- const transaction = unsignedTx.getTransaction();
295
- const txBlockchainId = transaction.getBlockchainID();
296
- return Buffer.from(txBlockchainId).toString('hex') === blockchainId;
297
- }
298
- catch (error) {
299
- return false;
300
- }
301
- }
302
- /**
303
- * Check if Output is from PVM.
304
- * Output could be EVM or PVM output.
305
- * @param {DeprecatedOutput} output
306
- * @returns {boolean} output has transferable output structure
307
- */
308
- deprecatedIsTransferableOutput(output) {
309
- return 'getOutput' in output;
310
- }
311
- /**
312
- * Check if Output is from PVM.
313
- * Output could be EVM or PVM output.
314
- * @param {Output} output
315
- * @returns {boolean} output is TransferableOutput
252
+ * Checks if output is TransferableOutput type
316
253
  */
317
254
  isTransferableOutput(output) {
318
- return typeof output.getOutput === 'function';
319
- }
320
- /**
321
- * Return a mapper function to that network address representation.
322
- * @param network required to stringify addresses
323
- * @return mapper function
324
- */
325
- deprecatedMapOutputToEntry(network) {
326
- return (output) => {
327
- if (this.deprecatedIsTransferableOutput(output)) {
328
- // Simplified implementation for FlareJS
329
- try {
330
- const transferableOutput = output;
331
- const amount = transferableOutput.amount();
332
- // Simplified address handling - would need proper FlareJS address utilities
333
- const address = 'flare-address-placeholder'; // TODO: implement proper address conversion
334
- return {
335
- value: amount.toString(),
336
- address,
337
- };
338
- }
339
- catch (error) {
340
- throw new Error(`Failed to map output: ${error}`);
341
- }
342
- }
343
- else {
344
- // Handle EVM output case - simplified
345
- return {
346
- value: '0', // TODO: implement proper amount extraction
347
- address: '0x0000000000000000000000000000000000000000', // TODO: implement proper address extraction
348
- };
349
- }
350
- };
255
+ return output?._type === flarejs_1.TypeSymbols.TransferableOutput;
351
256
  }
352
257
  /**
353
- * Return a mapper function to that network address representation.
354
- * @param network required to stringify addresses
355
- * @return mapper function
258
+ * Maps outputs to entry format
356
259
  */
357
260
  mapOutputToEntry(network) {
358
261
  return (output) => {
359
262
  if (this.isTransferableOutput(output)) {
360
- const transferableOutput = output;
361
- const outputAmount = transferableOutput.amount();
362
- // Simplified address handling for FlareJS
363
- const address = 'flare-address-placeholder'; // TODO: implement proper address conversion
263
+ const outputAmount = output.amount();
264
+ const address = output.output
265
+ .getOwners()
266
+ .map((a) => this.addressToString(network.hrp, network.alias, buffer_1.Buffer.from(a)))
267
+ .sort()
268
+ .join(iface_1.ADDRESS_SEPARATOR);
364
269
  return {
365
270
  value: outputAmount.toString(),
366
271
  address,
@@ -372,116 +277,234 @@ class Utils {
372
277
  };
373
278
  }
374
279
  /**
375
- * remove hex prefix (0x)
376
- * @param hex string
377
- * @returns hex without 0x
280
+ * Removes 0x prefix from hex string
378
281
  */
379
282
  removeHexPrefix(hex) {
380
- if (hex.startsWith('0x')) {
381
- return hex.substring(2);
382
- }
383
- return hex;
283
+ return hex.startsWith('0x') ? hex.substring(2) : hex;
384
284
  }
385
285
  /**
386
- * Outputidx convert from number (as string) to buffer.
387
- * @param {string} outputidx number
388
- * @return {Buffer} buffer of size 4 with that number value
286
+ * Converts output index to buffer
389
287
  */
390
288
  outputidxNumberToBuffer(outputidx) {
391
- return Buffer.from(Number(outputidx).toString(16).padStart(constants_1.OUTPUT_INDEX_HEX_LENGTH, '0'), 'hex');
289
+ return buffer_1.Buffer.from(Number(outputidx).toString(16).padStart(8, '0'), 'hex');
392
290
  }
393
291
  /**
394
- * Outputidx buffer to number (as string)
395
- * @param {Buffer} outputidx
396
- * @return {string} outputidx number
292
+ * Converts output index buffer to number string
397
293
  */
398
294
  outputidxBufferToNumber(outputidx) {
399
295
  return parseInt(outputidx.toString('hex'), 16).toString();
400
296
  }
401
297
  /**
402
- * CB58 decode function - simple Base58 decode implementation
403
- * @param {string} data - CB58 encoded string
404
- * @returns {Buffer} decoded buffer
298
+ * Decodes a base58 string with checksum to a Buffer
405
299
  */
406
- cb58Decode(data) {
407
- // For now, use a simple hex decode as placeholder
408
- // In a full implementation, this would be proper CB58 decoding
409
- try {
410
- return Buffer.from(data, 'hex');
411
- }
412
- catch {
413
- // Fallback to buffer from string
414
- return Buffer.from(data);
300
+ cb58Decode(str) {
301
+ const decoded = bs58_1.default.decode(str);
302
+ if (!this.validateChecksum(buffer_1.Buffer.from(decoded))) {
303
+ throw new Error('Invalid checksum');
415
304
  }
305
+ return buffer_1.Buffer.from(decoded.slice(0, decoded.length - 4));
416
306
  }
417
307
  /**
418
- * Convert address buffer to bech32 string
419
- * @param {string} hrp - Human readable part
420
- * @param {string} chainid - Chain identifier
421
- * @param {Buffer} addressBuffer - Address buffer
422
- * @returns {string} Address string
308
+ * Validates a checksum on a Buffer and returns true if valid, false if not
423
309
  */
424
- addressToString(hrp, chainid, addressBuffer) {
425
- // Simple implementation - in practice this would use bech32 encoding
426
- return `${chainid}-${addressBuffer.toString('hex')}`;
310
+ validateChecksum(buff) {
311
+ const hashSlice = buff.slice(buff.length - 4);
312
+ const calculatedHashSlice = (0, crypto_1.createHash)('sha256')
313
+ .update(buff.slice(0, buff.length - 4))
314
+ .digest()
315
+ .slice(28);
316
+ return hashSlice.toString('hex') === calculatedHashSlice.toString('hex');
427
317
  }
428
318
  /**
429
- * Convert string to bytes for FlareJS memo
430
- * Follows FlareJS utils.stringToBytes pattern
431
- * @param {string} text - Text to convert
432
- * @returns {Uint8Array} Byte array
319
+ * Encodes a Buffer as a base58 string with checksum
433
320
  */
434
- stringToBytes(text) {
435
- return new TextEncoder().encode(text);
321
+ cb58Encode(bytes) {
322
+ const withChecksum = this.addChecksum(bytes);
323
+ return bs58_1.default.encode(withChecksum);
436
324
  }
437
325
  /**
438
- * Convert bytes to string from FlareJS memo
439
- * @param {Uint8Array} bytes - Bytes to convert
440
- * @returns {string} Decoded string
326
+ * Adds a checksum to a Buffer and returns the concatenated result
327
+ * Uses last 4 bytes of SHA256 hash as checksum (matching avaxp behavior)
441
328
  */
442
- bytesToString(bytes) {
443
- return new TextDecoder().decode(bytes);
329
+ addChecksum(buff) {
330
+ const buffer = buffer_1.Buffer.from(buff);
331
+ const hashSlice = (0, crypto_1.createHash)('sha256').update(buffer).digest().slice(28);
332
+ return new Uint8Array(buffer_1.Buffer.concat([buffer, hashSlice]));
333
+ }
334
+ flareIdString(value) {
335
+ return new flarejs_1.Id(buffer_1.Buffer.from(value, 'hex'));
444
336
  }
445
337
  /**
446
- * Create memo bytes from various input formats
447
- * Supports string, JSON object, or raw bytes
448
- * @param {string | Record<string, unknown> | Uint8Array} memo - Memo data
449
- * @returns {Uint8Array} Memo bytes for FlareJS
338
+ * Sort addresses lexicographically by their byte representation.
339
+ * This matches how addresses are stored on-chain in Avalanche/Flare P-chain UTXOs.
340
+ *
341
+ * IMPORTANT: This sorting MUST be consistent with FlareJS's internal address sorting.
342
+ * FlareJS uses the same lexicographic comparison: `hexA.localeCompare(hexB)`.
343
+ * The sigIndices in transaction inputs depend on this sorted order, so any deviation
344
+ * would cause signature order mismatches and on-chain verification failures.
345
+ *
346
+ * @param addresses - Array of bech32 address strings (e.g., "P-costwo1...")
347
+ * @returns Array of addresses sorted by hex value (ascending lexicographic order)
450
348
  */
451
- createMemoBytes(memo) {
452
- if (memo instanceof Uint8Array) {
453
- return memo;
454
- }
455
- if (typeof memo === 'string') {
456
- return this.stringToBytes(memo);
349
+ sortAddressesByHex(addresses) {
350
+ return [...addresses].sort((a, b) => {
351
+ const aHex = this.parseAddress(a).toString('hex');
352
+ const bHex = this.parseAddress(b).toString('hex');
353
+ return aHex.localeCompare(bHex);
354
+ });
355
+ }
356
+ /**
357
+ * Sort address buffers lexicographically by their byte representation.
358
+ * This matches how addresses are stored on-chain in Avalanche/Flare P-chain UTXOs.
359
+ * @param addressBuffers - Array of address byte buffers
360
+ * @returns Array of address buffers sorted by hex value
361
+ */
362
+ sortAddressBuffersByHex(addressBuffers) {
363
+ return [...addressBuffers].sort((a, b) => {
364
+ return a.toString('hex').localeCompare(b.toString('hex'));
365
+ });
366
+ }
367
+ /**
368
+ * Recover public key from signature
369
+ * @param messageHash - The SHA256 hash of the message (e.g., signablePayload)
370
+ * @param signature - 65-byte signature (64 bytes signature + 1 byte recovery parameter)
371
+ * @return recovered public key
372
+ */
373
+ recoverySignature(messageHash, signature) {
374
+ try {
375
+ // Extract recovery parameter and signature
376
+ if (signature.length !== 65) {
377
+ throw new Error('Invalid signature length - expected 65 bytes (64 bytes signature + 1 byte recovery)');
378
+ }
379
+ const recoveryParam = signature[64];
380
+ const sigOnly = signature.slice(0, 64);
381
+ // Recover public key using the provided recovery parameter
382
+ // messageHash should already be the SHA256 hash (signablePayload)
383
+ const recovered = secp256k1_1.ecc.recoverPublicKey(messageHash, sigOnly, recoveryParam, true);
384
+ if (!recovered) {
385
+ throw new Error('Failed to recover public key');
386
+ }
387
+ return buffer_1.Buffer.from(recovered);
457
388
  }
458
- if (typeof memo === 'object') {
459
- return this.stringToBytes(JSON.stringify(memo));
389
+ catch (error) {
390
+ throw new Error(`Failed to recover signature: ${error.message}`);
460
391
  }
461
- throw new sdk_core_1.InvalidTransactionError('Invalid memo format');
462
392
  }
463
393
  /**
464
- * Parse memo bytes to string
465
- * @param {Uint8Array} memoBytes - Memo bytes from FlareJS transaction
466
- * @returns {string} Decoded memo string
394
+ * Check if tx is for the blockchainId
395
+ *
396
+ * @param {Tx} tx
397
+ * @param {string} blockchainId - blockchain ID in hex format
398
+ * @returns true if tx is for blockchainId
467
399
  */
468
- parseMemoBytes(memoBytes) {
469
- if (memoBytes.length === 0) {
470
- return '';
471
- }
472
- return this.bytesToString(memoBytes);
400
+ isTransactionOf(tx, blockchainId) {
401
+ // Note: getBlockchainId() and BlockchainId.value() return CB58-encoded strings,
402
+ // but we need hex format, so we use toBytes() and convert to hex
403
+ const extractBlockchainId = (txObj) => {
404
+ if (typeof txObj.getTx === 'function') {
405
+ const innerTx = txObj.getTx();
406
+ if (innerTx.baseTx?.BlockchainId?.toBytes) {
407
+ return buffer_1.Buffer.from(innerTx.baseTx.BlockchainId.toBytes()).toString('hex');
408
+ }
409
+ if (innerTx.blockchainId?.toBytes) {
410
+ return buffer_1.Buffer.from(innerTx.blockchainId.toBytes()).toString('hex');
411
+ }
412
+ }
413
+ if (txObj.tx?.baseTx?.BlockchainId?.toBytes) {
414
+ return buffer_1.Buffer.from(txObj.tx.baseTx.BlockchainId.toBytes()).toString('hex');
415
+ }
416
+ if (txObj.baseTx?.BlockchainId?.toBytes) {
417
+ return buffer_1.Buffer.from(txObj.baseTx.BlockchainId.toBytes()).toString('hex');
418
+ }
419
+ if (txObj.blockchainId?.toBytes) {
420
+ return buffer_1.Buffer.from(txObj.blockchainId.toBytes()).toString('hex');
421
+ }
422
+ return null;
423
+ };
424
+ const txBlockchainId = extractBlockchainId(tx);
425
+ return txBlockchainId === blockchainId;
426
+ }
427
+ /**
428
+ * Convert FlareJS native Utxo to DecodedUtxoObj for internal use
429
+ * @param utxo - FlareJS Utxo object
430
+ * @param network - Flare network configuration
431
+ * @returns DecodedUtxoObj compatible with existing methods
432
+ */
433
+ utxoToDecoded(utxo, network) {
434
+ const outputOwners = utxo.getOutputOwners();
435
+ const output = utxo.output;
436
+ // Get amount from output
437
+ const amount = output.amount().toString();
438
+ // Get txid from utxoId (cb58 encoded)
439
+ const txid = this.cb58Encode(buffer_1.Buffer.from(utxo.utxoId.txID.toBytes()));
440
+ // Get output index
441
+ const outputidx = utxo.utxoId.outputIdx.value().toString();
442
+ // Get threshold
443
+ const threshold = outputOwners.threshold.value();
444
+ // Get locktime
445
+ const locktime = outputOwners.locktime.value().toString();
446
+ // Get addresses as bech32 strings
447
+ const addresses = outputOwners.addrs.map((addr) => this.addressToString(network.hrp, network.alias, buffer_1.Buffer.from(addr.toBytes())));
448
+ return {
449
+ outputID: iface_1.SECP256K1_Transfer_Output,
450
+ locktime,
451
+ amount,
452
+ txid,
453
+ outputidx,
454
+ threshold,
455
+ addresses,
456
+ };
457
+ }
458
+ /**
459
+ * Convert array of FlareJS Utxos to DecodedUtxoObj array
460
+ * @param utxos - Array of FlareJS Utxo objects
461
+ * @param network - Flare network configuration
462
+ * @returns Array of DecodedUtxoObj
463
+ */
464
+ utxosToDecoded(utxos, network) {
465
+ return utxos.map((utxo) => this.utxoToDecoded(utxo, network));
466
+ }
467
+ /**
468
+ * Convert DecodedUtxoObj to native FlareJS Utxo object
469
+ * This is the reverse of utxoToDecoded
470
+ *
471
+ * IMPORTANT: Addresses are sorted lexicographically by byte value to match
472
+ * on-chain storage order. The API may return addresses in arbitrary order, but
473
+ * on-chain UTXOs always store addresses in sorted order.
474
+ *
475
+ * @param decoded - DecodedUtxoObj to convert
476
+ * @param assetId - Asset ID as cb58 encoded string
477
+ * @returns Native FlareJS Utxo object
478
+ */
479
+ decodedToUtxo(decoded, assetId) {
480
+ // Create UTXOID from txid and output index
481
+ const utxoId = flarejs_1.avaxSerial.UTXOID.fromNative(decoded.txid, parseInt(decoded.outputidx, 10));
482
+ // Parse addresses from bech32 strings to byte buffers
483
+ const addressBytes = decoded.addresses.map((addr) => this.parseAddress(addr));
484
+ // Sort addresses lexicographically by byte value to match on-chain order
485
+ // This is critical because the P-chain stores addresses in sorted order,
486
+ // and sigIndices must reference the correct positions.
487
+ const sortedAddressBytes = this.sortAddressBuffersByHex(addressBytes);
488
+ // Create OutputOwners with locktime, threshold, and SORTED addresses
489
+ const locktime = decoded.locktime ? BigInt(decoded.locktime) : BigInt(0);
490
+ const outputOwners = flarejs_1.OutputOwners.fromNative(sortedAddressBytes, locktime, decoded.threshold);
491
+ // Create TransferOutput with amount and owners
492
+ const amount = BigInt(decoded.amount);
493
+ const transferOutput = new flarejs_1.TransferOutput(new flarejs_1.BigIntPr(amount), outputOwners);
494
+ // Create and return the Utxo
495
+ return new flarejs_1.Utxo(utxoId, flarejs_1.Id.fromString(assetId), transferOutput);
473
496
  }
474
497
  /**
475
- * Validate memo size (FlareJS has transaction size limits)
476
- * @param {Uint8Array} memoBytes - Memo bytes
477
- * @param {number} maxSize - Maximum size in bytes (default 4KB)
478
- * @returns {boolean} Whether memo is within size limits
498
+ * Convert array of DecodedUtxoObj to native FlareJS Utxo objects
499
+ * @param decodedUtxos - Array of DecodedUtxoObj
500
+ * @param assetId - Asset ID as cb58 encoded string
501
+ * @returns Array of native FlareJS Utxo objects
479
502
  */
480
- validateMemoSize(memoBytes, maxSize = 4096) {
481
- return memoBytes.length <= maxSize;
503
+ decodedToUtxos(decodedUtxos, assetId) {
504
+ return decodedUtxos.map((decoded) => this.decodedToUtxo(decoded, assetId));
482
505
  }
483
506
  }
484
507
  exports.Utils = Utils;
485
508
  const utils = new Utils();
486
509
  exports.default = utils;
487
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLG1EQVE4QjtBQUU5QixxREFBNEM7QUFDNUMsbUNBQW9DO0FBRXBDLDJDQVdxQjtBQUVyQixNQUFhLEtBQUs7SUFBbEI7UUE0RlMsaUJBQVksR0FBRyxDQUFDLEdBQVcsRUFBVSxFQUFFO1lBQzVDLHlDQUF5QztZQUN6QyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsNEJBQTRCO1FBQzlELENBQUMsQ0FBQztJQThaSixDQUFDO0lBNWZRLFNBQVMsQ0FBQyxlQUF5QixFQUFFLG1CQUE2QjtRQUN2RSxPQUFPLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEcsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsa0JBQWtCO0lBQ2xCLGNBQWMsQ0FBQyxPQUEwQjtRQUN2QyxNQUFNLFVBQVUsR0FBYSxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFbkYsS0FBSyxNQUFNLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZDLE9BQU8sS0FBSyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxt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QUM7UUFDbEMsQ0FBQztRQUVELElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRUQsTUFBTSxJQUFJLGtDQUF1QixDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxjQUFjLENBQUMsU0FBcUI7UUFDbEMsSUFBSSxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxTQUFxQixFQUFFLE9BQU8sR0FBRyxJQUFJO1FBQ3BELE9BQU8sU0FBUyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUM7SUFDckMsQ0FBQztDQUNGO0FBN2ZELHNCQTZmQztBQUVELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7QUFFMUIsa0JBQWUsS0FBSyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVHJhbnNmZXJhYmxlT3V0cHV0IH0gZnJvbSAnQGZsYXJlbmV0d29yay9mbGFyZWpzJztcbmltcG9ydCB7XG4gIEJhc2VVdGlscyxcbiAgRW50cnksXG4gIEludmFsaWRUcmFuc2FjdGlvbkVycm9yLFxuICBpc1ZhbGlkWHBydixcbiAgaXNWYWxpZFhwdWIsXG4gIE5vdEltcGxlbWVudGVkRXJyb3IsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbn0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgRmxhcmVOZXR3b3JrIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgeyBlY2MgfSBmcm9tICdAYml0Z28tYmV0YS9zZWNwMjU2azEnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBEZXByZWNhdGVkT3V0cHV0LCBEZXByZWNhdGVkVHgsIE91dHB1dCB9IGZyb20gJy4vaWZhY2UnO1xuaW1wb3J0IHtcbiAgREVDT0RFRF9CTE9DS19JRF9MRU5HVEgsXG4gIFNIT1JUX1BVQl9LRVlfTEVOR1RILFxuICBDT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RILFxuICBVTkNPTVBSRVNTRURfUFVCTElDX0tFWV9MRU5HVEgsXG4gIFJBV19QUklWQVRFX0tFWV9MRU5HVEgsXG4gIFNVRkZJWEVEX1BSSVZBVEVfS0VZX0xFTkdUSCxcbiAgUFJJVkFURV9LRVlfQ09NUFJFU1NFRF9TVUZGSVgsXG4gIE9VVFBVVF9JTkRFWF9IRVhfTEVOR1RILFxuICBBRERSRVNTX1JFR0VYLFxuICBIRVhfUkVHRVgsXG59IGZyb20gJy4vY29uc3RhbnRzJztcblxuZXhwb3J0IGNsYXNzIFV0aWxzIGltcGxlbWVudHMgQmFzZVV0aWxzIHtcbiAgcHVibGljIGluY2x1ZGVJbih3YWxsZXRBZGRyZXNzZXM6IHN0cmluZ1tdLCBvdHhvT3V0cHV0QWRkcmVzc2VzOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB3YWxsZXRBZGRyZXNzZXMubWFwKChhKSA9PiBvdHhvT3V0cHV0QWRkcmVzc2VzLmluY2x1ZGVzKGEpKS5yZWR1Y2UoKGEsIGIpID0+IGEgJiYgYiwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGl0IGlzIGEgdmFsaWQgYWRkcmVzcyBubyBpbGxlZ2FsIGNoYXJhY3RlcnNcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3MgLSBhZGRyZXNzIHRvIGJlIHZhbGlkYXRlZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGFkZHJlc3NBcnI6IHN0cmluZ1tdID0gQXJyYXkuaXNBcnJheShhZGRyZXNzKSA/IGFkZHJlc3MgOiBhZGRyZXNzLnNwbGl0KCd+Jyk7XG5cbiAgICBmb3IgKGNvbnN0IGFkZHJlc3Mgb2YgYWRkcmVzc0Fycikge1xuICAgICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzUmVnZXgoYWRkcmVzcykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1ZhbGlkQWRkcmVzc1JlZ2V4KGFkZHJlc3M6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBBRERSRVNTX1JFR0VYLnRlc3QoYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGl0IGlzIGEgdmFsaWQgYmxvY2tJZCB3aXRoIGxlbmd0aCA2NiBpbmNsdWRpbmcgMHhcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggLSBibG9ja0lkIHRvIGJlIHZhbGlkYXRlZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQmxvY2tJZChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAvLyBGbGFyZUpTIGVxdWl2YWxlbnQgLSBjaGVjayBpZiBpdCdzIGEgdmFsaWQgQ0I1OCBoYXNoIHdpdGggY29ycmVjdCBsZW5ndGhcbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVjb2RlZCA9IEJ1ZmZlci5mcm9tKGhhc2gpOyAvLyBGbGFyZUpTIHNob3VsZCBwcm92aWRlIENCNTggdXRpbGl0aWVzXG4gICAgICByZXR1cm4gZGVjb2RlZC5sZW5ndGggPT09IERFQ09ERURfQkxPQ0tfSURfTEVOR1RIO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIHN0cmluZyBpcyBhIHZhbGlkIHByb3RvY29sIHB1YmxpYyBrZXkgb3JcbiAgICogZXh0ZW5kZWQgcHVibGljIGtleS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YiAtIHRoZSAgcHVibGljIGtleSB0byBiZSB2YWxpZGF0ZWRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdGhlIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBpc1ZhbGlkUHVibGljS2V5KHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzVmFsaWRYcHViKHB1YikpIHJldHVybiB0cnVlO1xuXG4gICAgbGV0IHB1YkJ1ZjogQnVmZmVyO1xuICAgIGlmIChwdWIubGVuZ3RoID09PSBTSE9SVF9QVUJfS0VZX0xFTkdUSCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gRm9yIEZsYXJlSlMsIHdlJ2xsIG5lZWQgdG8gaW1wbGVtZW50IENCNTggZGVjb2RlIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7IC8vIFRlbXBvcmFyeSBwbGFjZWhvbGRlclxuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHB1Yi5sZW5ndGggIT09IENPTVBSRVNTRURfUFVCTElDX0tFWV9MRU5HVEggJiYgcHViLmxlbmd0aCAhPT0gVU5DT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RIKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmlyc3RCeXRlID0gcHViLnNsaWNlKDAsIDIpO1xuXG4gICAgICAvLyB1bmNvbXByZXNzZWQgcHVibGljIGtleVxuICAgICAgaWYgKHB1Yi5sZW5ndGggPT09IFVOQ09NUFJFU1NFRF9QVUJMSUNfS0VZX0xFTkdUSCAmJiBmaXJzdEJ5dGUgIT09ICcwNCcpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBjb21wcmVzc2VkIHB1YmxpYyBrZXlcbiAgICAgIGlmIChwdWIubGVuZ3RoID09PSBDT01QUkVTU0VEX1BVQkxJQ19LRVlfTEVOR1RIICYmIGZpcnN0Qnl0ZSAhPT0gJzAyJyAmJiBmaXJzdEJ5dGUgIT09ICcwMycpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuYWxsSGV4Q2hhcnMocHViKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7XG4gICAgfVxuICAgIC8vIHZhbGlkYXRlIHRoZSBwdWJsaWMga2V5IHVzaW5nIEJpdEdvIHNlY3AyNTZrMVxuICAgIHRyeSB7XG4gICAgICBlY2MuaXNQb2ludChwdWJCdWYpOyAvLyBDaGVjayBpZiBpdCdzIGEgdmFsaWQgcG9pbnRcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcGFyc2VBZGRyZXNzID0gKHB1Yjogc3RyaW5nKTogQnVmZmVyID0+IHtcbiAgICAvLyBGbGFyZUpTIGVxdWl2YWxlbnQgZm9yIGFkZHJlc3MgcGFyc2luZ1xuICAgIHJldHVybiBCdWZmZXIuZnJvbShwdWIsICdoZXgnKTsgLy8gU2ltcGxpZmllZCBpbXBsZW1lbnRhdGlvblxuICB9O1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBwcm90b2NvbCBwcml2YXRlIGtleSwgb3IgZXh0ZW5kZWRcbiAgICogcHJpdmF0ZSBrZXkuXG4gICAqXG4gICAqIFRoZSBwcm90b2NvbCBrZXkgZm9ybWF0IGlzIGRlc2NyaWJlZCBpbiB0aGUgQHN0YWNrcy90cmFuc2FjdGlvbnMgbnBtIHBhY2thZ2UsIGluIHRoZVxuICAgKiBjcmVhdGVTdGFja3NQcml2YXRlS2V5IGZ1bmN0aW9uOlxuICAgKiBodHRwczovL2dpdGh1Yi5jb20vYmxvY2tzdGFjay9zdGFja3MuanMvYmxvYi9tYXN0ZXIvcGFja2FnZXMvdHJhbnNhY3Rpb25zL3NyYy9rZXlzLnRzI0wxMjVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHBydiAtIHRoZSBwcml2YXRlIGtleSAob3IgZXh0ZW5kZWQgcHJpdmF0ZSBrZXkpIHRvIGJlIHZhbGlkYXRlZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB0aGUgdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIGlzVmFsaWRQcml2YXRlS2V5KHBydjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzVmFsaWRYcHJ2KHBydikpIHJldHVybiB0cnVlO1xuXG4gICAgaWYgKHBydi5sZW5ndGggIT09IFJBV19QUklWQVRFX0tFWV9MRU5HVEggJiYgcHJ2Lmxlbmd0aCAhPT0gU1VGRklYRURfUFJJVkFURV9LRVlfTEVOR1RIKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgcHJ2Lmxlbmd0aCA9PT0gU1VGRklYRURfUFJJVkFURV9LRVlfTEVOR1RIICYmXG4gICAgICBwcnYuc2xpY2UoUkFXX1BSSVZBVEVfS0VZX0xFTkdUSCkgIT09IFBSSVZBVEVfS0VZX0NPTVBSRVNTRURfU1VGRklYXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuYWxsSGV4Q2hhcnMocHJ2KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSBjb21wb3NlZCBvZiBoZXggY2hhcnMgb25seVxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWF5YmUgLSB0aGUgIHN0cmluZyB0byBiZSB2YWxpZGF0ZWRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdGhlIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBhbGxIZXhDaGFycyhtYXliZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIEhFWF9SRUdFWC50ZXN0KG1heWJlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaWdodHdlaWdodCBFdGhlcmV1bSBhZGRyZXNzIHZhbGlkYXRpb25cbiAgICogVmFsaWRhdGVzIHRoYXQgYW4gYWRkcmVzcyBpcyBhIDQwLWNoYXJhY3RlciBoZXggc3RyaW5nIChvcHRpb25hbGx5IHByZWZpeGVkIHdpdGggMHgpXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIC0gdGhlIEV0aGVyZXVtIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdHJ1ZSBpZiB2YWxpZCBFdGhlcmV1bSBhZGRyZXNzIGZvcm1hdFxuICAgKi9cbiAgaXNWYWxpZEV0aGVyZXVtQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoIWFkZHJlc3MgfHwgdHlwZW9mIGFkZHJlc3MgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIDB4IHByZWZpeCBpZiBwcmVzZW50XG4gICAgY29uc3QgY2xlYW5BZGRyZXNzID0gYWRkcmVzcy5zdGFydHNXaXRoKCcweCcpID8gYWRkcmVzcy5zbGljZSgyKSA6IGFkZHJlc3M7XG5cbiAgICAvLyBDaGVjayBpZiBpdCdzIGV4YWN0bHkgNDAgaGV4IGNoYXJhY3RlcnNcbiAgICByZXR1cm4gY2xlYW5BZGRyZXNzLmxlbmd0aCA9PT0gNDAgJiYgL15bMC05YS1mQS1GXXs0MH0kLy50ZXN0KGNsZWFuQWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogUGljayBzcGVjaWZpYyBwcm9wZXJ0aWVzIGZyb20gYW4gb2JqZWN0IChyZXBsYWNlcyBsb2Rhc2gucGljaylcbiAgICpcbiAgICogQHBhcmFtIHtUfSBvYmogLSB0aGUgc291cmNlIG9iamVjdFxuICAgKiBAcGFyYW0ge0tbXX0ga2V5cyAtIGFycmF5IG9mIHByb3BlcnR5IGtleXMgdG8gcGlja1xuICAgKiBAcmV0dXJucyB7UGljazxULCBLPn0gLSBuZXcgb2JqZWN0IHdpdGggb25seSB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXNcbiAgICovXG4gIHBpY2s8VCwgSyBleHRlbmRzIGtleW9mIFQ+KG9iajogVCwga2V5czogS1tdKTogUGljazxULCBLPiB7XG4gICAgY29uc3QgcmVzdWx0ID0ge30gYXMgUGljazxULCBLPjtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IG9ialtrZXldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIERlZXAgZXF1YWxpdHkgY29tcGFyaXNvbiAocmVwbGFjZXMgbG9kYXNoLmlzRXF1YWwpXG4gICAqXG4gICAqIEBwYXJhbSB7dW5rbm93bn0gYSAtIGZpcnN0IHZhbHVlIHRvIGNvbXBhcmVcbiAgICogQHBhcmFtIHt1bmtub3dufSBiIC0gc2Vjb25kIHZhbHVlIHRvIGNvbXBhcmVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdHJ1ZSBpZiB2YWx1ZXMgYXJlIGRlZXBseSBlcXVhbFxuICAgKi9cbiAgaXNFcXVhbChhOiB1bmtub3duLCBiOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgaWYgKGEgPT09IGIpIHJldHVybiB0cnVlO1xuXG4gICAgaWYgKGEgPT09IG51bGwgfHwgYSA9PT0gdW5kZWZpbmVkIHx8IGIgPT09IG51bGwgfHwgYiA9PT0gdW5kZWZpbmVkKSByZXR1cm4gYSA9PT0gYjtcblxuICAgIGlmICh0eXBlb2YgYSAhPT0gdHlwZW9mIGIpIHJldHVybiBmYWxzZTtcblxuICAgIGlmICh0eXBlb2YgYSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGEpICE9PSBBcnJheS5pc0FycmF5KGIpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGEpKSB7XG4gICAgICAgIGNvbnN0IGFyckIgPSBiIGFzIHVua25vd25bXTtcbiAgICAgICAgaWYgKGEubGVuZ3RoICE9PSBhcnJCLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAoIXRoaXMuaXNFcXVhbChhW2ldLCBhcnJCW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvYmpBID0gYSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNvbnN0IG9iakIgPSBiIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgY29uc3Qga2V5c0EgPSBPYmplY3Qua2V5cyhvYmpBKTtcbiAgICAgIGNvbnN0IGtleXNCID0gT2JqZWN0LmtleXMob2JqQik7XG4gICAgICBpZiAoa2V5c0EubGVuZ3RoICE9PSBrZXlzQi5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICAgICAgZm9yIChjb25zdCBrZXkgb2Yga2V5c0EpIHtcbiAgICAgICAgaWYgKCFrZXlzQi5pbmNsdWRlcyhrZXkpKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGlmICghdGhpcy5pc0VxdWFsKG9iakFba2V5XSwgb2JqQltrZXldKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRTaWduYXR1cmUoc2lnbmF0dXJlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcignaXNWYWxpZFNpZ25hdHVyZSBub3QgaW1wbGVtZW50ZWQnKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkVHJhbnNhY3Rpb25JZCh0eElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcignaXNWYWxpZFRyYW5zYWN0aW9uSWQgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogRmxhcmVKUyB3cmFwcGVyIHRvIGNyZWF0ZSBzaWduYXR1cmUgYW5kIHJldHVybiBpdCBmb3IgY3JlZGVudGlhbHNcbiAgICogQHBhcmFtIG5ldHdvcmtcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHBhcmFtIHBydlxuICAgKiBAcmV0dXJuIHNpZ25hdHVyZVxuICAgKi9cbiAgY3JlYXRlU2lnbmF0dXJlKG5ldHdvcms6IEZsYXJlTmV0d29yaywgbWVzc2FnZTogQnVmZmVyLCBwcnY6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgLy8gVXNlIEJpdEdvIHNlY3AyNTZrMSBzaW5jZSBGbGFyZUpTIG1heSBub3QgZXhwb3NlIEtleVBhaXIgaW4gdGhlIHNhbWUgd2F5XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGVjYy5zaWduKG1lc3NhZ2UsIHBydik7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oc2lnbmF0dXJlKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gY3JlYXRlIHNpZ25hdHVyZTogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmxhcmVKUyB3cmFwcGVyIHRvIHZlcmlmeSBzaWduYXR1cmVcbiAgICogQHBhcmFtIG5ldHdvcmtcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHBhcmFtIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0gcHVibGljS2V5IC0gcHVibGljIGtleSBpbnN0ZWFkIG9mIHByaXZhdGUga2V5IGZvciB2ZXJpZmljYXRpb25cbiAgICogQHJldHVybiB0cnVlIGlmIGl0J3MgdmVyaWZ5IHN1Y2Nlc3NmdWxcbiAgICovXG4gIHZlcmlmeVNpZ25hdHVyZShuZXR3b3JrOiBGbGFyZU5ldHdvcmssIG1lc3NhZ2U6IEJ1ZmZlciwgc2lnbmF0dXJlOiBCdWZmZXIsIHB1YmxpY0tleTogQnVmZmVyKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBlY2MudmVyaWZ5KG1lc3NhZ2UsIHB1YmxpY0tleSwgc2lnbmF0dXJlKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGbGFyZUpTIHdyYXBwZXIgdG8gcmVjb3ZlciBzaWduYXR1cmVcbiAgICogQHBhcmFtIG5ldHdvcmtcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHBhcmFtIHNpZ25hdHVyZVxuICAgKiBAcmV0dXJuIHJlY292ZXJlZCBwdWJsaWMga2V5XG4gICAqL1xuICByZWNvdmVyeVNpZ25hdHVyZShuZXR3b3JrOiBGbGFyZU5ldHdvcmssIG1lc3NhZ2U6IEJ1ZmZlciwgc2lnbmF0dXJlOiBCdWZmZXIpOiBCdWZmZXIge1xuICAgIHRyeSB7XG4gICAgICAvLyBUaGlzIHdvdWxkIG5lZWQgdG8gYmUgaW1wbGVtZW50ZWQgd2l0aCBzZWNwMjU2azEgcmVjb3ZlcnlcbiAgICAgIC8vIEZvciBub3csIHRocm93aW5nIGVycm9yIHNpbmNlIHJlY292ZXJ5IGxvZ2ljIHdvdWxkIG5lZWQgdG8gYmUgYWRhcHRlZFxuICAgICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ3JlY292ZXJ5U2lnbmF0dXJlIG5vdCBmdWxseSBpbXBsZW1lbnRlZCBmb3IgRmxhcmVKUycpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZWNvdmVyIHNpZ25hdHVyZTogJHtlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICBzaGEyNTYoYnVmOiBVaW50OEFycmF5KTogQnVmZmVyIHtcbiAgICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGJ1ZikuZGlnZXN0KCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgdGhlIHJhdyB0cmFuc2FjdGlvbiBoYXMgYSB2YWxpZCBmb3JtYXQgaW4gdGhlIGJsb2NrY2hhaW4gY29udGV4dCwgdGhyb3cgb3RoZXJ3aXNlLlxuICAgKiBJdCdzIHRvIHJldXNlIGluIFRyYW5zYWN0aW9uQnVpbGRlciBhbmQgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeVxuICAgKlxuICAgKiBAcGFyYW0gcmF3VHJhbnNhY3Rpb24gVHJhbnNhY3Rpb24gYXMgaGV4IHN0cmluZ1xuICAgKi9cbiAgdmFsaWRhdGVSYXdUcmFuc2FjdGlvbihyYXdUcmFuc2FjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFyYXdUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdSYXcgdHJhbnNhY3Rpb24gaXMgZW1wdHknKTtcbiAgICB9XG4gICAgaWYgKCF1dGlscy5hbGxIZXhDaGFycyhyYXdUcmFuc2FjdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBub3QgaGV4IHN0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0eCBpcyBmb3IgdGhlIGJsb2NrY2hhaW5JZFxuICAgKlxuICAgKiBAcGFyYW0ge0RlcHJlY2F0ZWRUeH0gdHhcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJsb2NrY2hhaW5JZFxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHR4IGlzIGZvciBibG9ja2NoYWluSWRcbiAgICovXG4gIGlzVHJhbnNhY3Rpb25PZih0eDogRGVwcmVjYXRlZFR4LCBibG9ja2NoYWluSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vIEZsYXJlSlMgZXF1aXZhbGVudCAtIHRoaXMgd291bGQgbmVlZCBwcm9wZXIgQ0I1OCBlbmNvZGluZyBpbXBsZW1lbnRhdGlvblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB0eFJlY29yZCA9IHR4IGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gKHR4UmVjb3JkLmdldFVuc2lnbmVkVHggYXMgKCkgPT4gUmVjb3JkPHN0cmluZywgdW5rbm93bj4pKCk7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9ICh1bnNpZ25lZFR4LmdldFRyYW5zYWN0aW9uIGFzICgpID0+IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSgpO1xuICAgICAgY29uc3QgdHhCbG9ja2NoYWluSWQgPSAodHJhbnNhY3Rpb24uZ2V0QmxvY2tjaGFpbklEIGFzICgpID0+IHVua25vd24pKCk7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20odHhCbG9ja2NoYWluSWQgYXMgc3RyaW5nKS50b1N0cmluZygnaGV4JykgPT09IGJsb2NrY2hhaW5JZDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBPdXRwdXQgaXMgZnJvbSBQVk0uXG4gICAqIE91dHB1dCBjb3VsZCBiZSBFVk0gb3IgUFZNIG91dHB1dC5cbiAgICogQHBhcmFtIHtEZXByZWNhdGVkT3V0cHV0fSBvdXRwdXRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IG91dHB1dCBoYXMgdHJhbnNmZXJhYmxlIG91dHB1dCBzdHJ1Y3R1cmVcbiAgICovXG4gIGRlcHJlY2F0ZWRJc1RyYW5zZmVyYWJsZU91dHB1dChvdXRwdXQ6IERlcHJlY2F0ZWRPdXRwdXQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gJ2dldE91dHB1dCcgaW4gKG91dHB1dCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgT3V0cHV0IGlzIGZyb20gUFZNLlxuICAgKiBPdXRwdXQgY291bGQgYmUgRVZNIG9yIFBWTSBvdXRwdXQuXG4gICAqIEBwYXJhbSB7T3V0cHV0fSBvdXRwdXRcbiAgICogQHJldHVybnMge2Jvb2xlYW59IG91dHB1dCBpcyBUcmFuc2ZlcmFibGVPdXRwdXRcbiAgICovXG4gIGlzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dDogT3V0cHV0KTogb3V0cHV0IGlzIFRyYW5zZmVyYWJsZU91dHB1dCB7XG4gICAgcmV0dXJuIHR5cGVvZiAob3V0cHV0IGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLmdldE91dHB1dCA9PT0gJ2Z1bmN0aW9uJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBtYXBwZXIgZnVuY3Rpb24gdG8gdGhhdCBuZXR3b3JrIGFkZHJlc3MgcmVwcmVzZW50YXRpb24uXG4gICAqIEBwYXJhbSBuZXR3b3JrIHJlcXVpcmVkIHRvIHN0cmluZ2lmeSBhZGRyZXNzZXNcbiAgICogQHJldHVybiBtYXBwZXIgZnVuY3Rpb25cbiAgICovXG4gIGRlcHJlY2F0ZWRNYXBPdXRwdXRUb0VudHJ5KG5ldHdvcms6IEZsYXJlTmV0d29yayk6IChvdXRwdXQ6IERlcHJlY2F0ZWRPdXRwdXQpID0+IEVudHJ5IHtcbiAgICByZXR1cm4gKG91dHB1dDogRGVwcmVjYXRlZE91dHB1dCkgPT4ge1xuICAgICAgaWYgKHRoaXMuZGVwcmVjYXRlZElzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dCkpIHtcbiAgICAgICAgLy8gU2ltcGxpZmllZCBpbXBsZW1lbnRhdGlvbiBmb3IgRmxhcmVKU1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHRyYW5zZmVyYWJsZU91dHB1dCA9IG91dHB1dCBhcyB1bmtub3duIGFzIFRyYW5zZmVyYWJsZU91dHB1dDtcbiAgICAgICAgICBjb25zdCBhbW91bnQgPSB0cmFuc2ZlcmFibGVPdXRwdXQuYW1vdW50KCk7XG5cbiAgICAgICAgICAvLyBTaW1wbGlmaWVkIGFkZHJlc3MgaGFuZGxpbmcgLSB3b3VsZCBuZWVkIHByb3BlciBGbGFyZUpTIGFkZHJlc3MgdXRpbGl0aWVzXG4gICAgICAgICAgY29uc3QgYWRkcmVzcyA9ICdmbGFyZS1hZGRyZXNzLXBsYWNlaG9sZGVyJzsgLy8gVE9ETzogaW1wbGVtZW50IHByb3BlciBhZGRyZXNzIGNvbnZlcnNpb25cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2YWx1ZTogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBhZGRyZXNzLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gbWFwIG91dHB1dDogJHtlcnJvcn1gKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSGFuZGxlIEVWTSBvdXRwdXQgY2FzZSAtIHNpbXBsaWZpZWRcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2YWx1ZTogJzAnLCAvLyBUT0RPOiBpbXBsZW1lbnQgcHJvcGVyIGFtb3VudCBleHRyYWN0aW9uXG4gICAgICAgICAgYWRkcmVzczogJzB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsIC8vIFRPRE86IGltcGxlbWVudCBwcm9wZXIgYWRkcmVzcyBleHRyYWN0aW9uXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBtYXBwZXIgZnVuY3Rpb24gdG8gdGhhdCBuZXR3b3JrIGFkZHJlc3MgcmVwcmVzZW50YXRpb24uXG4gICAqIEBwYXJhbSBuZXR3b3JrIHJlcXVpcmVkIHRvIHN0cmluZ2lmeSBhZGRyZXNzZXNcbiAgICogQHJldHVybiBtYXBwZXIgZnVuY3Rpb25cbiAgICovXG4gIG1hcE91dHB1dFRvRW50cnkobmV0d29yazogRmxhcmVOZXR3b3JrKTogKE91dHB1dCkgPT4gRW50cnkge1xuICAgIHJldHVybiAob3V0cHV0OiBPdXRwdXQpID0+IHtcbiAgICAgIGlmICh0aGlzLmlzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dCkpIHtcbiAgICAgICAgY29uc3QgdHJhbnNmZXJhYmxlT3V0cHV0ID0gb3V0cHV0IGFzIFRyYW5zZmVyYWJsZU91dHB1dDtcbiAgICAgICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gdHJhbnNmZXJhYmxlT3V0cHV0LmFtb3VudCgpO1xuXG4gICAgICAgIC8vIFNpbXBsaWZpZWQgYWRkcmVzcyBoYW5kbGluZyBmb3IgRmxhcmVKU1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gJ2ZsYXJlLWFkZHJlc3MtcGxhY2Vob2xkZXInOyAvLyBUT0RPOiBpbXBsZW1lbnQgcHJvcGVyIGFkZHJlc3MgY29udmVyc2lvblxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmFsdWU6IG91dHB1dEFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgIGFkZHJlc3MsXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgb3V0cHV0IHR5cGUnKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIHJlbW92ZSBoZXggcHJlZml4ICgweClcbiAgICogQHBhcmFtIGhleCBzdHJpbmdcbiAgICogQHJldHVybnMgaGV4IHdpdGhvdXQgMHhcbiAgICovXG4gIHJlbW92ZUhleFByZWZpeChoZXg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKGhleC5zdGFydHNXaXRoKCcweCcpKSB7XG4gICAgICByZXR1cm4gaGV4LnN1YnN0cmluZygyKTtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdXRwdXRpZHggY29udmVydCBmcm9tIG51bWJlciAoYXMgc3RyaW5nKSB0byBidWZmZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvdXRwdXRpZHggbnVtYmVyXG4gICAqIEByZXR1cm4ge0J1ZmZlcn0gYnVmZmVyIG9mIHNpemUgNCB3aXRoIHRoYXQgbnVtYmVyIHZhbHVlXG4gICAqL1xuICBvdXRwdXRpZHhOdW1iZXJUb0J1ZmZlcihvdXRwdXRpZHg6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKE51bWJlcihvdXRwdXRpZHgpLnRvU3RyaW5nKDE2KS5wYWRTdGFydChPVVRQVVRfSU5ERVhfSEVYX0xFTkdUSCwgJzAnKSwgJ2hleCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIE91dHB1dGlkeCBidWZmZXIgdG8gbnVtYmVyIChhcyBzdHJpbmcpXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBvdXRwdXRpZHhcbiAgICogQHJldHVybiB7c3RyaW5nfSBvdXRwdXRpZHggbnVtYmVyXG4gICAqL1xuICBvdXRwdXRpZHhCdWZmZXJUb051bWJlcihvdXRwdXRpZHg6IEJ1ZmZlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBhcnNlSW50KG91dHB1dGlkeC50b1N0cmluZygnaGV4JyksIDE2KS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENCNTggZGVjb2RlIGZ1bmN0aW9uIC0gc2ltcGxlIEJhc2U1OCBkZWNvZGUgaW1wbGVtZW50YXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBDQjU4IGVuY29kZWQgc3RyaW5nXG4gICAqIEByZXR1cm5zIHtCdWZmZXJ9IGRlY29kZWQgYnVmZmVyXG4gICAqL1xuICBjYjU4RGVjb2RlKGRhdGE6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgLy8gRm9yIG5vdywgdXNlIGEgc2ltcGxlIGhleCBkZWNvZGUgYXMgcGxhY2Vob2xkZXJcbiAgICAvLyBJbiBhIGZ1bGwgaW1wbGVtZW50YXRpb24sIHRoaXMgd291bGQgYmUgcHJvcGVyIENCNTggZGVjb2RpbmdcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEsICdoZXgnKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIEZhbGxiYWNrIHRvIGJ1ZmZlciBmcm9tIHN0cmluZ1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGFkZHJlc3MgYnVmZmVyIHRvIGJlY2gzMiBzdHJpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhycCAtIEh1bWFuIHJlYWRhYmxlIHBhcnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYWluaWQgLSBDaGFpbiBpZGVudGlmaWVyXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBhZGRyZXNzQnVmZmVyIC0gQWRkcmVzcyBidWZmZXJcbiAgICogQHJldHVybnMge3N0cmluZ30gQWRkcmVzcyBzdHJpbmdcbiAgICovXG4gIGFkZHJlc3NUb1N0cmluZyhocnA6IHN0cmluZywgY2hhaW5pZDogc3RyaW5nLCBhZGRyZXNzQnVmZmVyOiBCdWZmZXIpOiBzdHJpbmcge1xuICAgIC8vIFNpbXBsZSBpbXBsZW1lbnRhdGlvbiAtIGluIHByYWN0aWNlIHRoaXMgd291bGQgdXNlIGJlY2gzMiBlbmNvZGluZ1xuICAgIHJldHVybiBgJHtjaGFpbmlkfS0ke2FkZHJlc3NCdWZmZXIudG9TdHJpbmcoJ2hleCcpfWA7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBzdHJpbmcgdG8gYnl0ZXMgZm9yIEZsYXJlSlMgbWVtb1xuICAgKiBGb2xsb3dzIEZsYXJlSlMgdXRpbHMuc3RyaW5nVG9CeXRlcyBwYXR0ZXJuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGV4dCB0byBjb252ZXJ0XG4gICAqIEByZXR1cm5zIHtVaW50OEFycmF5fSBCeXRlIGFycmF5XG4gICAqL1xuICBzdHJpbmdUb0J5dGVzKHRleHQ6IHN0cmluZyk6IFVpbnQ4QXJyYXkge1xuICAgIHJldHVybiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUodGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBieXRlcyB0byBzdHJpbmcgZnJvbSBGbGFyZUpTIG1lbW9cbiAgICogQHBhcmFtIHtVaW50OEFycmF5fSBieXRlcyAtIEJ5dGVzIHRvIGNvbnZlcnRcbiAgICogQHJldHVybnMge3N0cmluZ30gRGVjb2RlZCBzdHJpbmdcbiAgICovXG4gIGJ5dGVzVG9TdHJpbmcoYnl0ZXM6IFVpbnQ4QXJyYXkpOiBzdHJpbmcge1xuICAgIHJldHVybiBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoYnl0ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBtZW1vIGJ5dGVzIGZyb20gdmFyaW91cyBpbnB1dCBmb3JtYXRzXG4gICAqIFN1cHBvcnRzIHN0cmluZywgSlNPTiBvYmplY3QsIG9yIHJhdyBieXRlc1xuICAgKiBAcGFyYW0ge3N0cmluZyB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgVWludDhBcnJheX0gbWVtbyAtIE1lbW8gZGF0YVxuICAgKiBAcmV0dXJucyB7VWludDhBcnJheX0gTWVtbyBieXRlcyBmb3IgRmxhcmVKU1xuICAgKi9cbiAgY3JlYXRlTWVtb0J5dGVzKG1lbW86IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgVWludDhBcnJheSk6IFVpbnQ4QXJyYXkge1xuICAgIGlmIChtZW1vIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBtZW1vID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRoaXMuc3RyaW5nVG9CeXRlcyhtZW1vKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG1lbW8gPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gdGhpcy5zdHJpbmdUb0J5dGVzKEpTT04uc3RyaW5naWZ5KG1lbW8pKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgbWVtbyBmb3JtYXQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBtZW1vIGJ5dGVzIHRvIHN0cmluZ1xuICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IG1lbW9CeXRlcyAtIE1lbW8gYnl0ZXMgZnJvbSBGbGFyZUpTIHRyYW5zYWN0aW9uXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IERlY29kZWQgbWVtbyBzdHJpbmdcbiAgICovXG4gIHBhcnNlTWVtb0J5dGVzKG1lbW9CeXRlczogVWludDhBcnJheSk6IHN0cmluZyB7XG4gICAgaWYgKG1lbW9CeXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYnl0ZXNUb1N0cmluZyhtZW1vQnl0ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIG1lbW8gc2l6ZSAoRmxhcmVKUyBoYXMgdHJhbnNhY3Rpb24gc2l6ZSBsaW1pdHMpXG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0gbWVtb0J5dGVzIC0gTWVtbyBieXRlc1xuICAgKiBAcGFyYW0ge251bWJlcn0gbWF4U2l6ZSAtIE1heGltdW0gc2l6ZSBpbiBieXRlcyAoZGVmYXVsdCA0S0IpXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBXaGV0aGVyIG1lbW8gaXMgd2l0aGluIHNpemUgbGltaXRzXG4gICAqL1xuICB2YWxpZGF0ZU1lbW9TaXplKG1lbW9CeXRlczogVWludDhBcnJheSwgbWF4U2l6ZSA9IDQwOTYpOiBib29sZWFuIHtcbiAgICByZXR1cm4gbWVtb0J5dGVzLmxlbmd0aCA8PSBtYXhTaXplO1xuICB9XG59XG5cbmNvbnN0IHV0aWxzID0gbmV3IFV0aWxzKCk7XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWxzO1xuIl19
510
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQVUrQjtBQUMvQixtREFPOEI7QUFFOUIsbUNBQWdDO0FBQ2hDLG1DQUFvQztBQUNwQyxxREFBNEM7QUFDNUMsbUNBQW1HO0FBQ25HLGdEQUF3QjtBQUN4QixtQ0FBZ0M7QUFFaEMsTUFBYSxLQUFLO0lBQWxCO1FBNlBFOztXQUVHO1FBQ0ksb0JBQWUsR0FBRyxDQUFDLEdBQVcsRUFBRSxNQUFjLEVBQUUsT0FBZSxFQUFVLEVBQUU7WUFDaEYsK0RBQStEO1lBQy9ELE1BQU0sS0FBSyxHQUFHLGVBQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEMsK0VBQStFO1lBQy9FLE9BQU8sR0FBRyxNQUFNLElBQUksZUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNsRCxDQUFDLENBQUM7UUEyQ0YsbURBQW1EO1FBRW5EOzs7O1dBSUc7UUFDSSxpQkFBWSxHQUFHLENBQUMsT0FBZSxFQUFVLEVBQUU7WUFDaEQsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLENBQUMsQ0FBQztRQUVLLG9CQUFlLEdBQUcsQ0FBQyxPQUFlLEVBQUUsR0FBWSxFQUFVLEVBQUU7WUFDakUsdUJBQXVCO1lBQ3ZCLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUM3QixPQUFPLGVBQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM5QyxDQUFDO1lBRUQsbUNBQW1DO1lBQ25DLElBQUksbUJBQW1CLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3RDLE9BQU8sZUFBTSxDQUFDLElB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LElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUV0RSxxRUFBcUU7UUFDckUsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sWUFBWSxHQUFHLHNCQUFZLENBQUMsVUFBVSxDQUFDLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFOUYsK0NBQStDO1FBQy9DLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEMsTUFBTSxjQUFjLEdBQUcsSUFBSSx3QkFBYyxDQUFDLElBQUksa0JBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUU5RSw2QkFBNkI7UUFDN0IsT0FBTyxJQUFJLGNBQUksQ0FBQyxNQUFNLEVBQUUsWUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxjQUFjLENBQUMsWUFBOEIsRUFBRSxPQUFlO1FBQ25FLE9BQU8sWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUM3RSxDQUFDO0NBQ0Y7QUFqaUJELHNCQWlpQkM7QUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDO0FBQzFCLGtCQUFlLEtBQUssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIFNpZ25hdHVyZSxcbiAgVHJhbnNmZXJhYmxlT3V0cHV0LFxuICBUcmFuc2Zlck91dHB1dCxcbiAgVHlwZVN5bWJvbHMsXG4gIElkLFxuICBVdHhvLFxuICBCaWdJbnRQcixcbiAgT3V0cHV0T3duZXJzLFxuICBhdmF4U2VyaWFsLFxufSBmcm9tICdAZmxhcmVuZXR3b3JrL2ZsYXJlanMnO1xuaW1wb3J0IHtcbiAgQmFzZVV0aWxzLFxuICBFbnRyeSxcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIGlzVmFsaWRYcHJ2LFxuICBpc1ZhbGlkWHB1YixcbiAgUGFyc2VUcmFuc2FjdGlvbkVycm9yLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBGbGFyZU5ldHdvcmsgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGVjYyB9IGZyb20gJ0BiaXRnby1iZXRhL3NlY3AyNTZrMSc7XG5pbXBvcnQgeyBBRERSRVNTX1NFUEFSQVRPUiwgRGVjb2RlZFV0eG9PYmosIE91dHB1dCwgU0VDUDI1NksxX1RyYW5zZmVyX091dHB1dCwgVHggfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCBiczU4IGZyb20gJ2JzNTgnO1xuaW1wb3J0IHsgYmVjaDMyIH0gZnJvbSAnYmVjaDMyJztcblxuZXhwb3J0IGNsYXNzIFV0aWxzIGltcGxlbWVudHMgQmFzZVV0aWxzIHtcbiAgaXNWYWxpZFRyYW5zYWN0aW9uSWQodHhJZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xuICB9XG4gIGlzVmFsaWRTaWduYXR1cmUoc2lnbmF0dXJlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIGlmIGFkZHJlc3NlcyBpbiB3YWxsZXQgbWF0Y2ggVVRYTyBvdXRwdXQgYWRkcmVzc2VzXG4gICAqL1xuICBwdWJsaWMgaW5jbHVkZUluKHdhbGxldEFkZHJlc3Nlczogc3RyaW5nW10sIG90eG9PdXRwdXRBZGRyZXNzZXM6IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHdhbGxldEFkZHJlc3Nlcy5tYXAoKGEpID0+IG90eG9PdXRwdXRBZGRyZXNzZXMuaW5jbHVkZXMoYSkpLnJlZHVjZSgoYSwgYikgPT4gYSAmJiBiLCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBGbGFyZSBhZGRyZXNzIG9yIGFycmF5IG9mIGFkZHJlc3Nlc1xuICAgKiBAcGFyYW0ge3N0cmluZyB8IHN0cmluZ1tdfSBhZGRyZXNzIC0gYWRkcmVzcyhlcykgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyB8IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYWRkcmVzc0Fycjogc3RyaW5nW10gPSBBcnJheS5pc0FycmF5KGFkZHJlc3MpID8gYWRkcmVzcyA6IGFkZHJlc3Muc3BsaXQoJ34nKTtcblxuICAgIGZvciAoY29uc3QgYWRkcmVzcyBvZiBhZGRyZXNzQXJyKSB7XG4gICAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3NSZWdleChhZGRyZXNzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGlzVmFsaWRBZGRyZXNzUmVnZXgoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIC9eKF5QfHxOb2RlSUQpLVthLXpBLVowLTldKyQvLnRlc3QoYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgYmxvY2sgSURcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggLSBibG9jayBJRCB0byB2YWxpZGF0ZVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZEJsb2NrSWQoaGFzaDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGRlY29kZWQgPSBCdWZmZXIuZnJvbShoYXNoLCAnaGV4Jyk7XG4gICAgICByZXR1cm4gZGVjb2RlZC5sZW5ndGggPT09IDMyO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBwdWJsaWMga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwdWIgLSBwdWJsaWMga2V5IHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBpc1ZhbGlkUHVibGljS2V5KHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzVmFsaWRYcHViKHB1YikpIHJldHVybiB0cnVlO1xuXG4gICAgbGV0IHB1YkJ1ZjogQnVmZmVyO1xuICAgIGlmIChwdWIubGVuZ3RoID09PSA1MCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocHViLmxlbmd0aCAhPT0gNjYgJiYgcHViLmxlbmd0aCAhPT0gMTMwKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGZpcnN0Qnl0ZSA9IHB1Yi5zbGljZSgwLCAyKTtcbiAgICAgIGlmIChwdWIubGVuZ3RoID09PSAxMzAgJiYgZmlyc3RCeXRlICE9PSAnMDQnKSByZXR1cm4gZmFsc2U7XG4gICAgICBpZiAocHViLmxlbmd0aCA9PT0gNjYgJiYgZmlyc3RCeXRlICE9PSAnMDInICYmIGZpcnN0Qnl0ZSAhPT0gJzAzJykgcmV0dXJuIGZhbHNlO1xuICAgICAgaWYgKCF0aGlzLmFsbEhleENoYXJzKHB1YikpIHJldHVybiBmYWxzZTtcblxuICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGVjYy5pc1BvaW50KHB1YkJ1Zik7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIHByaXZhdGUga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcnYgLSBwcml2YXRlIGtleSB0byB2YWxpZGF0ZVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZFByaXZhdGVLZXkocHJ2OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoaXNWYWxpZFhwcnYocHJ2KSkgcmV0dXJuIHRydWU7XG4gICAgaWYgKHBydi5sZW5ndGggIT09IDY0ICYmIHBydi5sZW5ndGggIT09IDY2KSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHBydi5sZW5ndGggPT09IDY2ICYmIHBydi5zbGljZSg2NCkgIT09ICcwMScpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5hbGxIZXhDaGFycyhwcnYpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIHN0cmluZyBjb250YWlucyBvbmx5IGhleCBjaGFyYWN0ZXJzXG4gICAqL1xuICBhbGxIZXhDaGFycyhzdHI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAvXigweCl7MCwxfShbMC05YS1mXSkrJC9pLnRlc3Qoc3RyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgc2lnbmF0dXJlIHVzaW5nIHRoZSBGbGFyZSBuZXR3b3JrIHBhcmFtZXRlcnNcbiAgICogUmV0dXJucyBhIDY1LWJ5dGUgc2lnbmF0dXJlICg2NCBieXRlcyBzaWduYXR1cmUgKyAxIGJ5dGUgcmVjb3ZlcnkgcGFyYW1ldGVyKVxuICAgKi9cbiAgY3JlYXRlU2lnbmF0dXJlKG5ldHdvcms6IEZsYXJlTmV0d29yaywgbWVzc2FnZTogQnVmZmVyLCBwcnY6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgY29uc3QgbWVzc2FnZUhhc2ggPSB0aGlzLnNoYTI1NihtZXNzYWdlKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBlY2Muc2lnbihtZXNzYWdlSGFzaCwgcHJ2KTtcblxuICAgIC8vIEdldCB0aGUgcHVibGljIGtleSBmcm9tIHRoZSBwcml2YXRlIGtleSBmb3IgcmVjb3ZlcnkgcGFyYW1ldGVyIGRldGVybWluYXRpb25cbiAgICBjb25zdCBwdWJsaWNLZXkgPSBlY2MucG9pbnRGcm9tU2NhbGFyKHBydiwgdHJ1ZSk7XG4gICAgaWYgKCFwdWJsaWNLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGRlcml2ZSBwdWJsaWMga2V5IGZyb20gcHJpdmF0ZSBrZXknKTtcbiAgICB9XG5cbiAgICAvLyBUcnkgcmVjb3Zlcnkgd2l0aCBwYXJhbSAwIGFuZCAxIHRvIGZpbmQgdGhlIGNvcnJlY3Qgb25lXG4gICAgbGV0IHJlY292ZXJ5UGFyYW0gPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDE7IGkrKykge1xuICAgICAgY29uc3QgcmVjb3ZlcmVkID0gZWNjLnJlY292ZXJQdWJsaWNLZXkobWVzc2FnZUhhc2gsIHNpZ25hdHVyZSwgaSwgdHJ1ZSk7XG4gICAgICBpZiAocmVjb3ZlcmVkICYmIEJ1ZmZlci5mcm9tKHJlY292ZXJlZCkuZXF1YWxzKEJ1ZmZlci5mcm9tKHB1YmxpY0tleSkpKSB7XG4gICAgICAgIHJlY292ZXJ5UGFyYW0gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBcHBlbmQgcmVjb3ZlcnkgcGFyYW1ldGVyIHRvIGNyZWF0ZSA2NS1ieXRlIHNpZ25hdHVyZVxuICAgIGNvbnN0IHNpZ1dpdGhSZWNvdmVyeSA9IEJ1ZmZlci5hbGxvYyg2NSk7XG4gICAgQnVmZmVyLmZyb20oc2lnbmF0dXJlKS5jb3B5KHNpZ1dpdGhSZWNvdmVyeSwgMCk7XG4gICAgc2lnV2l0aFJlY292ZXJ5WzY0XSA9IHJlY292ZXJ5UGFyYW07XG5cbiAgICByZXR1cm4gc2lnV2l0aFJlY292ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIGEgc2lnbmF0dXJlXG4gICAqIEBwYXJhbSBtZXNzYWdlSGFzaCAtIFRoZSBTSEEyNTYgaGFzaCBvZiB0aGUgbWVzc2FnZSAoZS5nLiwgc2lnbmFibGVQYXlsb2FkKVxuICAgKiBAcGFyYW0gc2lnbmF0dXJlIC0gVGhlIDY0LWJ5dGUgc2lnbmF0dXJlICh3aXRob3V0IHJlY292ZXJ5IHBhcmFtZXRlcilcbiAgICogQHBhcmFtIHB1YmxpY0tleSAtIFRoZSBwdWJsaWMga2V5IHRvIHZlcmlmeSBhZ2FpbnN0XG4gICAqIEByZXR1cm5zIHRydWUgaWYgc2lnbmF0dXJlIGlzIHZhbGlkXG4gICAqL1xuICB2ZXJpZnlTaWduYXR1cmUobWVzc2FnZUhhc2g6IEJ1ZmZlciwgc2lnbmF0dXJlOiBCdWZmZXIsIHB1YmxpY0tleTogQnVmZmVyKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBlY2MudmVyaWZ5KG1lc3NhZ2VIYXNoLCBwdWJsaWNLZXksIHNpZ25hdHVyZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHNpZ25hdHVyZSBvYmplY3RcbiAgICovXG4gIGNyZWF0ZU5ld1NpZyhzaWdIZXg6IHN0cmluZyk6IFNpZ25hdHVyZSB7XG4gICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmZyb20oc2lnSGV4LnBhZFN0YXJ0KDEzMCwgJzAnKSwgJ2hleCcpO1xuICAgIHJldHVybiBuZXcgU2lnbmF0dXJlKGJ1ZmZlcik7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBlbXB0eSBzaWduYXR1cmUgd2l0aCBlbWJlZGRlZCBhZGRyZXNzIGZvciBzaWduYXR1cmUgc2xvdCBpZGVudGlmaWNhdGlvbi5cbiAgICogVGhlIGFkZHJlc3MgaXMgZW1iZWRkZWQgYXQgcG9zaXRpb24gOTAgKGFmdGVyIHRoZSBmaXJzdCA0NSB6ZXJvIGJ5dGVzKS5cbiAgICogVGhpcyBhbGxvd3MgdGhlIHNpZ25pbmcgbG9naWMgdG8gZGV0ZXJtaW5lIHdoaWNoIHNsb3QgYmVsb25ncyB0byB3aGljaCBhZGRyZXNzLlxuICAgKiBAcGFyYW0gYWRkcmVzc0hleCBUaGUgMjAtYnl0ZSBhZGRyZXNzIGluIGhleCBmb3JtYXQgKDQwIGNoYXJzLCB3aXRob3V0IDB4IHByZWZpeClcbiAgICovXG4gIGNyZWF0ZUVtcHR5U2lnV2l0aEFkZHJlc3MoYWRkcmVzc0hleDogc3RyaW5nKTogU2lnbmF0dXJlIHtcbiAgICAvLyBGaXJzdCA0NSBieXRlcyAoOTAgaGV4IGNoYXJzKSBhcmUgemVyb3MsIGZvbGxvd2VkIGJ5IDIwLWJ5dGUgYWRkcmVzcyAoNDAgaGV4IGNoYXJzKVxuICAgIGNvbnN0IGNsZWFuQWRkciA9IHRoaXMucmVtb3ZlSGV4UHJlZml4KGFkZHJlc3NIZXgpLnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3Qgc2lnSGV4ID0gJzAnLnJlcGVhdCg5MCkgKyBjbGVhbkFkZHIucGFkU3RhcnQoNDAsICcwJyk7XG4gICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmZyb20oc2lnSGV4LCAnaGV4Jyk7XG4gICAgcmV0dXJuIG5ldyBTaWduYXR1cmUoYnVmZmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0cyB0aGUgZW1iZWRkZWQgYWRkcmVzcyBmcm9tIGFuIGVtcHR5IHNpZ25hdHVyZS5cbiAgICogUmV0dXJucyB0aGUgYWRkcmVzcyBoZXggc3RyaW5nICg0MCBjaGFycykgb3IgZW1wdHkgc3RyaW5nIGlmIG5vdCBmb3VuZC5cbiAgICovXG4gIGdldEFkZHJlc3NGcm9tRW1wdHlTaWcoc2lnOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNsZWFuU2lnID0gdGhpcy5yZW1vdmVIZXhQcmVmaXgoc2lnKTtcbiAgICBpZiAoY2xlYW5TaWcubGVuZ3RoID49IDEzMCkge1xuICAgICAgLy8gQWRkcmVzcyBpcyBhdCBwb3NpdGlvbiA5MC0xMzAgKGxhc3QgNDAgaGV4IGNoYXJzID0gMjAgYnl0ZXMpXG4gICAgICByZXR1cm4gY2xlYW5TaWcuc3Vic3RyaW5nKDkwLCAxMzApLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlcyBTSEEyNTYgaGFzaFxuICAgKi9cbiAgc2hhMjU2KGJ1ZjogVWludDhBcnJheSk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShidWYpLmRpZ2VzdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyByYXcgdHJhbnNhY3Rpb24gZm9ybWF0XG4gICAqL1xuICB2YWxpZGF0ZVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBlbXB0eScpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuYWxsSGV4Q2hhcnMocmF3VHJhbnNhY3Rpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdSYXcgdHJhbnNhY3Rpb24gaXMgbm90IGhleCBzdHJpbmcnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIG91dHB1dCBpcyBUcmFuc2ZlcmFibGVPdXRwdXQgdHlwZVxuICAgKi9cbiAgaXNUcmFuc2ZlcmFibGVPdXRwdXQob3V0cHV0OiBPdXRwdXQpOiBvdXRwdXQgaXMgVHJhbnNmZXJhYmxlT3V0cHV0IHtcbiAgICByZXR1cm4gb3V0cHV0Py5fdHlwZSA9PT0gVHlwZVN5bWJvbHMuVHJhbnNmZXJhYmxlT3V0cHV0O1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcHMgb3V0cHV0cyB0byBlbnRyeSBmb3JtYXRcbiAgICovXG4gIG1hcE91dHB1dFRvRW50cnkobmV0d29yazogRmxhcmVOZXR3b3JrKTogKE91dHB1dCkgPT4gRW50cnkge1xuICAgIHJldHVybiAob3V0cHV0OiBPdXRwdXQpID0+IHtcbiAgICAgIGlmICh0aGlzLmlzVHJhbnNmZXJhYmxlT3V0cHV0KG91dHB1dCkpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gb3V0cHV0LmFtb3VudCgpO1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gKG91dHB1dC5vdXRwdXQgYXMgVHJhbnNmZXJPdXRwdXQpXG4gICAgICAgICAgLmdldE93bmVycygpXG4gICAgICAgICAgLm1hcCgoYSkgPT4gdGhpcy5hZGRyZXNzVG9TdHJpbmcobmV0d29yay5ocnAsIG5ldHdvcmsuYWxpYXMsIEJ1ZmZlci5mcm9tKGEpKSlcbiAgICAgICAgICAuc29ydCgpXG4gICAgICAgICAgLmpvaW4oQUREUkVTU19TRVBBUkFUT1IpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHZhbHVlOiBvdXRwdXRBbW91bnQudG9TdHJpbmcoKSxcbiAgICAgICAgICBhZGRyZXNzLFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG91dHB1dCB0eXBlJyk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIDB4IHByZWZpeCBmcm9tIGhleCBzdHJpbmdcbiAgICovXG4gIHJlbW92ZUhleFByZWZpeChoZXg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGhleC5zdGFydHNXaXRoKCcweCcpID8gaGV4LnN1YnN0cmluZygyKSA6IGhleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBvdXRwdXQgaW5kZXggdG8gYnVmZmVyXG4gICAqL1xuICBvdXRwdXRpZHhOdW1iZXJUb0J1ZmZlcihvdXRwdXRpZHg6IHN0cmluZyk6IEJ1ZmZlciB7XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKE51bWJlcihvdXRwdXRpZHgpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCAnMCcpLCAnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgb3V0cHV0IGluZGV4IGJ1ZmZlciB0byBudW1iZXIgc3RyaW5nXG4gICAqL1xuICBvdXRwdXRpZHhCdWZmZXJUb051bWJlcihvdXRwdXRpZHg6IEJ1ZmZlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBhcnNlSW50KG91dHB1dGlkeC50b1N0cmluZygnaGV4JyksIDE2KS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBtZXRob2QgdG8gY29udmVydCBhZGRyZXNzIGNvbXBvbmVudHMgdG8gc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgYWRkcmVzc1RvU3RyaW5nID0gKGhycDogc3RyaW5nLCBwcmVmaXg6IHN0cmluZywgYWRkcmVzczogQnVmZmVyKTogc3RyaW5nID0+IHtcbiAgICAvLyBDb252ZXJ0IHRoZSBhZGRyZXNzIGJ5dGVzIHRvIDUtYml0IHdvcmRzIGZvciBiZWNoMzIgZW5jb2RpbmdcbiAgICBjb25zdCB3b3JkcyA9IGJlY2gzMi50b1dvcmRzKGFkZHJlc3MpO1xuICAgIC8vIENyZWF0ZSB0aGUgZnVsbCBiZWNoMzIgYWRkcmVzcyB3aXRoIGZvcm1hdDogUC17aHJwfTF7YmVjaDMyX2VuY29kZWRfYWRkcmVzc31cbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke2JlY2gzMi5lbmNvZGUoaHJwLCB3b3Jkcyl9YDtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlcyBhIGJhc2U1OCBzdHJpbmcgd2l0aCBjaGVja3N1bSB0byBhIEJ1ZmZlclxuICAgKi9cbiAgcHVibGljIGNiNThEZWNvZGUoc3RyOiBzdHJpbmcpOiBCdWZmZXIge1xuICAgIGNvbnN0IGRlY29kZWQgPSBiczU4LmRlY29kZShzdHIpO1xuICAgIGlmICghdGhpcy52YWxpZGF0ZUNoZWNrc3VtKEJ1ZmZlci5mcm9tKGRlY29kZWQpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNoZWNrc3VtJyk7XG4gICAgfVxuICAgIHJldHVybiBCdWZmZXIuZnJvbShkZWNvZGVkLnNsaWNlKDAsIGRlY29kZWQubGVuZ3RoIC0gNCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIGNoZWNrc3VtIG9uIGEgQnVmZmVyIGFuZCByZXR1cm5zIHRydWUgaWYgdmFsaWQsIGZhbHNlIGlmIG5vdFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUNoZWNrc3VtKGJ1ZmY6IEJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGhhc2hTbGljZSA9IGJ1ZmYuc2xpY2UoYnVmZi5sZW5ndGggLSA0KTtcbiAgICBjb25zdCBjYWxjdWxhdGVkSGFzaFNsaWNlID0gY3JlYXRlSGFzaCgnc2hhMjU2JylcbiAgICAgIC51cGRhdGUoYnVmZi5zbGljZSgwLCBidWZmLmxlbmd0aCAtIDQpKVxuICAgICAgLmRpZ2VzdCgpXG4gICAgICAuc2xpY2UoMjgpO1xuICAgIHJldHVybiBoYXNoU2xpY2UudG9TdHJpbmcoJ2hleCcpID09PSBjYWxjdWxhdGVkSGFzaFNsaWNlLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmNvZGVzIGEgQnVmZmVyIGFzIGEgYmFzZTU4IHN0cmluZyB3aXRoIGNoZWNrc3VtXG4gICAqL1xuICBwdWJsaWMgY2I1OEVuY29kZShieXRlczogQnVmZmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCB3aXRoQ2hlY2tzdW0gPSB0aGlzLmFkZENoZWNrc3VtKGJ5dGVzKTtcbiAgICByZXR1cm4gYnM1OC5lbmNvZGUod2l0aENoZWNrc3VtKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgY2hlY2tzdW0gdG8gYSBCdWZmZXIgYW5kIHJldHVybnMgdGhlIGNvbmNhdGVuYXRlZCByZXN1bHRcbiAgICogVXNlcyBsYXN0IDQgYnl0ZXMgb2YgU0hBMjU2IGhhc2ggYXMgY2hlY2tzdW0gKG1hdGNoaW5nIGF2YXhwIGJlaGF2aW9yKVxuICAgKi9cbiAgcHVibGljIGFkZENoZWNrc3VtKGJ1ZmY6IEJ1ZmZlciB8IFVpbnQ4QXJyYXkpOiBVaW50OEFycmF5IHtcbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuZnJvbShidWZmKTtcbiAgICBjb25zdCBoYXNoU2xpY2UgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoYnVmZmVyKS5kaWdlc3QoKS5zbGljZSgyOCk7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KEJ1ZmZlci5jb25jYXQoW2J1ZmZlciwgaGFzaFNsaWNlXSkpO1xuICB9XG5cbiAgLy8gSW4gdXRpbHMudHMsIGFkZCB0aGlzIG1ldGhvZCB0byB0aGUgVXRpbHMgY2xhc3M6XG5cbiAgLyoqXG4gICAqIFBhcnNlIGFuIGFkZHJlc3Mgc3RyaW5nIGludG8gYSBCdWZmZXJcbiAgICogQHBhcmFtIGFkZHJlc3MgLSBUaGUgYWRkcmVzcyB0byBwYXJzZVxuICAgKiBAcmV0dXJucyBCdWZmZXIgY29udGFpbmluZyB0aGUgcGFyc2VkIGFkZHJlc3NcbiAgICovXG4gIHB1YmxpYyBwYXJzZUFkZHJlc3MgPSAoYWRkcmVzczogc3RyaW5nKTogQnVmZmVyID0+IHtcbiAgICByZXR1cm4gdGhpcy5zdHJpbmdUb0FkZHJlc3MoYWRkcmVzcyk7XG4gIH07XG5cbiAgcHVibGljIHN0cmluZ1RvQWRkcmVzcyA9IChhZGRyZXNzOiBzdHJpbmcsIGhycD86IHN0cmluZyk6IEJ1ZmZlciA9PiB7XG4gICAgLy8gSGFuZGxlIGhleCBhZGRyZXNzZXNcbiAgICBpZiAoYWRkcmVzcy5zdGFydHNXaXRoKCcweCcpKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oYWRkcmVzcy5zbGljZSgyKSwgJ2hleCcpO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSByYXcgaGV4IHdpdGhvdXQgMHggcHJlZml4XG4gICAgaWYgKC9eWzAtOWEtZkEtRl17NDB9JC8udGVzdChhZGRyZXNzKSkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGFkZHJlc3MsICdoZXgnKTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgQmVjaDMyIGFkZHJlc3Nlc1xuICAgIGNvbnN0IHBhcnRzID0gYWRkcmVzcy50cmltKCkuc3BsaXQoJy0nKTtcbiAgICBpZiAocGFydHMubGVuZ3RoIDwgMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFcnJvciAtIFZhbGlkIGFkZHJlc3Mgc2hvdWxkIGluY2x1ZGUgLScpO1xuICAgIH1cblxuICAgIGNvbnN0IHNwbGl0ID0gcGFydHNbMV0ubGFzdEluZGV4T2YoJzEnKTtcbiAgICBpZiAoc3BsaXQgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIC0gVmFsaWQgYmVjaDMyIGFkZHJlc3MgbXVzdCBpbmNsdWRlIHNlcGFyYXRvciAoMSknKTtcbiAgICB9XG5cbiAgICBjb25zdCBodW1hblJlYWRhYmxlUGFydCA9IHBhcnRzWzFdLnNsaWNlKDAsIHNwbGl0KTtcbiAgICBpZiAoaHVtYW5SZWFkYWJsZVBhcnQgIT09ICdmbGFyZScgJiYgaHVtYW5SZWFkYWJsZVBhcnQgIT09ICdjb3N0d28nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIC0gSW52YWxpZCBIUlAnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gQnVmZmVyLmZyb20oYmVjaDMyLmZyb21Xb3JkcyhiZWNoMzIuZGVjb2RlKHBhcnRzWzFdKS53b3JkcykpO1xuICB9O1xuXG4gIGZsYXJlSWRTdHJpbmcodmFsdWU6IHN0cmluZyk6IElkIHtcbiAgICByZXR1cm4gbmV3IElkKEJ1ZmZlci5mcm9tKHZhbHVlLCAnaGV4JykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNvcnQgYWRkcmVzc2VzIGxleGljb2dyYXBoaWNhbGx5IGJ5IHRoZWlyIGJ5dGUgcmVwcmVzZW50YXRpb24uXG4gICAqIFRoaXMgbWF0Y2hlcyBob3cgYWRkcmVzc2VzIGFyZSBzdG9yZWQgb24tY2hhaW4gaW4gQXZhbGFuY2hlL0ZsYXJlIFAtY2hhaW4gVVRYT3MuXG4gICAqXG4gICAqIElNUE9SVEFOVDogVGhpcyBzb3J0aW5nIE1VU1QgYmUgY29uc2lzdGVudCB3aXRoIEZsYXJlSlMncyBpbnRlcm5hbCBhZGRyZXNzIHNvcnRpbmcuXG4gICAqIEZsYXJlSlMgdXNlcyB0aGUgc2FtZSBsZXhpY29ncmFwaGljIGNvbXBhcmlzb246IGBoZXhBLmxvY2FsZUNvbXBhcmUoaGV4QilgLlxuICAgKiBUaGUgc2lnSW5kaWNlcyBpbiB0cmFuc2FjdGlvbiBpbnB1dHMgZGVwZW5kIG9uIHRoaXMgc29ydGVkIG9yZGVyLCBzbyBhbnkgZGV2aWF0aW9uXG4gICAqIHdvdWxkIGNhdXNlIHNpZ25hdHVyZSBvcmRlciBtaXNtYXRjaGVzIGFuZCBvbi1jaGFpbiB2ZXJpZmljYXRpb24gZmFpbHVyZXMuXG4gICAqXG4gICAqIEBwYXJhbSBhZGRyZXNzZXMgLSBBcnJheSBvZiBiZWNoMzIgYWRkcmVzcyBzdHJpbmdzIChlLmcuLCBcIlAtY29zdHdvMS4uLlwiKVxuICAgKiBAcmV0dXJucyBBcnJheSBvZiBhZGRyZXNzZXMgc29ydGVkIGJ5IGhleCB2YWx1ZSAoYXNjZW5kaW5nIGxleGljb2dyYXBoaWMgb3JkZXIpXG4gICAqL1xuICBwdWJsaWMgc29ydEFkZHJlc3Nlc0J5SGV4KGFkZHJlc3Nlczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFsuLi5hZGRyZXNzZXNdLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGNvbnN0IGFIZXggPSB0aGlzLnBhcnNlQWRkcmVzcyhhKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCBiSGV4ID0gdGhpcy5wYXJzZUFkZHJlc3MoYikudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgcmV0dXJuIGFIZXgubG9jYWxlQ29tcGFyZShiSGV4KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTb3J0IGFkZHJlc3MgYnVmZmVycyBsZXhpY29ncmFwaGljYWxseSBieSB0aGVpciBieXRlIHJlcHJlc2VudGF0aW9uLlxuICAgKiBUaGlzIG1hdGNoZXMgaG93IGFkZHJlc3NlcyBhcmUgc3RvcmVkIG9uLWNoYWluIGluIEF2YWxhbmNoZS9GbGFyZSBQLWNoYWluIFVUWE9zLlxuICAgKiBAcGFyYW0gYWRkcmVzc0J1ZmZlcnMgLSBBcnJheSBvZiBhZGRyZXNzIGJ5dGUgYnVmZmVyc1xuICAgKiBAcmV0dXJucyBBcnJheSBvZiBhZGRyZXNzIGJ1ZmZlcnMgc29ydGVkIGJ5IGhleCB2YWx1ZVxuICAgKi9cbiAgcHVibGljIHNvcnRBZGRyZXNzQnVmZmVyc0J5SGV4KGFkZHJlc3NCdWZmZXJzOiBCdWZmZXJbXSk6IEJ1ZmZlcltdIHtcbiAgICByZXR1cm4gWy4uLmFkZHJlc3NCdWZmZXJzXS5zb3J0KChhLCBiKSA9PiB7XG4gICAgICByZXR1cm4gYS50b1N0cmluZygnaGV4JykubG9jYWxlQ29tcGFyZShiLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVjb3ZlciBwdWJsaWMga2V5IGZyb20gc2lnbmF0dXJlXG4gICAqIEBwYXJhbSBtZXNzYWdlSGFzaCAtIFRoZSBTSEEyNTYgaGFzaCBvZiB0aGUgbWVzc2FnZSAoZS5nLiwgc2lnbmFibGVQYXlsb2FkKVxuICAgKiBAcGFyYW0gc2lnbmF0dXJlIC0gNjUtYnl0ZSBzaWduYXR1cmUgKDY0IGJ5dGVzIHNpZ25hdHVyZSArIDEgYnl0ZSByZWNvdmVyeSBwYXJhbWV0ZXIpXG4gICAqIEByZXR1cm4gcmVjb3ZlcmVkIHB1YmxpYyBrZXlcbiAgICovXG4gIHJlY292ZXJ5U2lnbmF0dXJlKG1lc3NhZ2VIYXNoOiBCdWZmZXIsIHNpZ25hdHVyZTogQnVmZmVyKTogQnVmZmVyIHtcbiAgICB0cnkge1xuICAgICAgLy8gRXh0cmFjdCByZWNvdmVyeSBwYXJhbWV0ZXIgYW5kIHNpZ25hdHVyZVxuICAgICAgaWYgKHNpZ25hdHVyZS5sZW5ndGggIT09IDY1KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzaWduYXR1cmUgbGVuZ3RoIC0gZXhwZWN0ZWQgNjUgYnl0ZXMgKDY0IGJ5dGVzIHNpZ25hdHVyZSArIDEgYnl0ZSByZWNvdmVyeSknKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVjb3ZlcnlQYXJhbSA9IHNpZ25hdHVyZVs2NF07XG4gICAgICBjb25zdCBzaWdPbmx5ID0gc2lnbmF0dXJlLnNsaWNlKDAsIDY0KTtcblxuICAgICAgLy8gUmVjb3ZlciBwdWJsaWMga2V5IHVzaW5nIHRoZSBwcm92aWRlZCByZWNvdmVyeSBwYXJhbWV0ZXJcbiAgICAgIC8vIG1lc3NhZ2VIYXNoIHNob3VsZCBhbHJlYWR5IGJlIHRoZSBTSEEyNTYgaGFzaCAoc2lnbmFibGVQYXlsb2FkKVxuICAgICAgY29uc3QgcmVjb3ZlcmVkID0gZWNjLnJlY292ZXJQdWJsaWNLZXkobWVzc2FnZUhhc2gsIHNpZ09ubHksIHJlY292ZXJ5UGFyYW0sIHRydWUpO1xuICAgICAgaWYgKCFyZWNvdmVyZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcmVjb3ZlciBwdWJsaWMga2V5Jyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBCdWZmZXIuZnJvbShyZWNvdmVyZWQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZWNvdmVyIHNpZ25hdHVyZTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0eCBpcyBmb3IgdGhlIGJsb2NrY2hhaW5JZFxuICAgKlxuICAgKiBAcGFyYW0ge1R4fSB0eFxuICAgKiBAcGFyYW0ge3N0cmluZ30gYmxvY2tjaGFpbklkIC0gYmxvY2tjaGFpbiBJRCBpbiBoZXggZm9ybWF0XG4gICAqIEByZXR1cm5zIHRydWUgaWYgdHggaXMgZm9yIGJsb2NrY2hhaW5JZFxuICAgKi9cbiAgaXNUcmFuc2FjdGlvbk9mKHR4OiBUeCwgYmxvY2tjaGFpbklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAvLyBOb3RlOiBnZXRCbG9ja2NoYWluSWQoKSBhbmQgQmxvY2tjaGFpbklkLnZhbHVlKCkgcmV0dXJuIENCNTgtZW5jb2RlZCBzdHJpbmdzLFxuICAgIC8vIGJ1dCB3ZSBuZWVkIGhleCBmb3JtYXQsIHNvIHdlIHVzZSB0b0J5dGVzKCkgYW5kIGNvbnZlcnQgdG8gaGV4XG4gICAgY29uc3QgZXh0cmFjdEJsb2NrY2hhaW5JZCA9ICh0eE9iajogYW55KTogc3RyaW5nIHwgbnVsbCA9PiB7XG4gICAgICBpZiAodHlwZW9mIHR4T2JqLmdldFR4ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNvbnN0IGlubmVyVHggPSB0eE9iai5nZXRUeCgpO1xuICAgICAgICBpZiAoaW5uZXJUeC5iYXNlVHg/LkJsb2NrY2hhaW5JZD8udG9CeXRlcykge1xuICAgICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShpbm5lclR4LmJhc2VUeC5CbG9ja2NoYWluSWQudG9CeXRlcygpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlubmVyVHguYmxvY2tjaGFpbklkPy50b0J5dGVzKSB7XG4gICAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGlubmVyVHguYmxvY2tjaGFpbklkLnRvQnl0ZXMoKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0eE9iai50eD8uYmFzZVR4Py5CbG9ja2NoYWluSWQ/LnRvQnl0ZXMpIHtcbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHR4T2JqLnR4LmJhc2VUeC5CbG9ja2NoYWluSWQudG9CeXRlcygpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eE9iai5iYXNlVHg/LkJsb2NrY2hhaW5JZD8udG9CeXRlcykge1xuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20odHhPYmouYmFzZVR4LkJsb2NrY2hhaW5JZC50b0J5dGVzKCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIH1cbiAgICAgIGlmICh0eE9iai5ibG9ja2NoYWluSWQ/LnRvQnl0ZXMpIHtcbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHR4T2JqLmJsb2NrY2hhaW5JZC50b0J5dGVzKCkpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcblxuICAgIGNvbnN0IHR4QmxvY2tjaGFpbklkID0gZXh0cmFjdEJsb2NrY2hhaW5JZCh0eCk7XG4gICAgcmV0dXJuIHR4QmxvY2tjaGFpbklkID09PSBibG9ja2NoYWluSWQ7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBGbGFyZUpTIG5hdGl2ZSBVdHhvIHRvIERlY29kZWRVdHhvT2JqIGZvciBpbnRlcm5hbCB1c2VcbiAgICogQHBhcmFtIHV0eG8gLSBGbGFyZUpTIFV0eG8gb2JqZWN0XG4gICAqIEBwYXJhbSBuZXR3b3JrIC0gRmxhcmUgbmV0d29yayBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIERlY29kZWRVdHhvT2JqIGNvbXBhdGlibGUgd2l0aCBleGlzdGluZyBtZXRob2RzXG4gICAqL1xuICBwdWJsaWMgdXR4b1RvRGVjb2RlZCh1dHhvOiBVdHhvLCBuZXR3b3JrOiBGbGFyZU5ldHdvcmspOiBEZWNvZGVkVXR4b09iaiB7XG4gICAgY29uc3Qgb3V0cHV0T3duZXJzID0gdXR4by5nZXRPdXRwdXRPd25lcnMoKTtcbiAgICBjb25zdCBvdXRwdXQgPSB1dHhvLm91dHB1dCBhcyBUcmFuc2Zlck91dHB1dDtcblxuICAgIC8vIEdldCBhbW91bnQgZnJvbSBvdXRwdXRcbiAgICBjb25zdCBhbW91bnQgPSBvdXRwdXQuYW1vdW50KCkudG9TdHJpbmcoKTtcblxuICAgIC8vIEdldCB0eGlkIGZyb20gdXR4b0lkIChjYjU4IGVuY29kZWQpXG4gICAgY29uc3QgdHhpZCA9IHRoaXMuY2I1OEVuY29kZShCdWZmZXIuZnJvbSh1dHhvLnV0eG9JZC50eElELnRvQnl0ZXMoKSkpO1xuXG4gICAgLy8gR2V0IG91dHB1dCBpbmRleFxuICAgIGNvbnN0IG91dHB1dGlkeCA9IHV0eG8udXR4b0lkLm91dHB1dElkeC52YWx1ZSgpLnRvU3RyaW5nKCk7XG5cbiAgICAvLyBHZXQgdGhyZXNob2xkXG4gICAgY29uc3QgdGhyZXNob2xkID0gb3V0cHV0T3duZXJzLnRocmVzaG9sZC52YWx1ZSgpO1xuXG4gICAgLy8gR2V0IGxvY2t0aW1lXG4gICAgY29uc3QgbG9ja3RpbWUgPSBvdXRwdXRPd25lcnMubG9ja3RpbWUudmFsdWUoKS50b1N0cmluZygpO1xuXG4gICAgLy8gR2V0IGFkZHJlc3NlcyBhcyBiZWNoMzIgc3RyaW5nc1xuICAgIGNvbnN0IGFkZHJlc3NlcyA9IG91dHB1dE93bmVycy5hZGRycy5tYXAoKGFkZHIpID0+XG4gICAgICB0aGlzLmFkZHJlc3NUb1N0cmluZyhuZXR3b3JrLmhycCwgbmV0d29yay5hbGlhcywgQnVmZmVyLmZyb20oYWRkci50b0J5dGVzKCkpKVxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgb3V0cHV0SUQ6IFNFQ1AyNTZLMV9UcmFuc2Zlcl9PdXRwdXQsXG4gICAgICBsb2NrdGltZSxcbiAgICAgIGFtb3VudCxcbiAgICAgIHR4aWQsXG4gICAgICBvdXRwdXRpZHgsXG4gICAgICB0aHJlc2hvbGQsXG4gICAgICBhZGRyZXNzZXMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGFycmF5IG9mIEZsYXJlSlMgVXR4b3MgdG8gRGVjb2RlZFV0eG9PYmogYXJyYXlcbiAgICogQHBhcmFtIHV0eG9zIC0gQXJyYXkgb2YgRmxhcmVKUyBVdHhvIG9iamVjdHNcbiAgICogQHBhcmFtIG5ldHdvcmsgLSBGbGFyZSBuZXR3b3JrIGNvbmZpZ3VyYXRpb25cbiAgICogQHJldHVybnMgQXJyYXkgb2YgRGVjb2RlZFV0eG9PYmpcbiAgICovXG4gIHB1YmxpYyB1dHhvc1RvRGVjb2RlZCh1dHhvczogVXR4b1tdLCBuZXR3b3JrOiBGbGFyZU5ldHdvcmspOiBEZWNvZGVkVXR4b09ialtdIHtcbiAgICByZXR1cm4gdXR4b3MubWFwKCh1dHhvKSA9PiB0aGlzLnV0eG9Ub0RlY29kZWQodXR4bywgbmV0d29yaykpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgRGVjb2RlZFV0eG9PYmogdG8gbmF0aXZlIEZsYXJlSlMgVXR4byBvYmplY3RcbiAgICogVGhpcyBpcyB0aGUgcmV2ZXJzZSBvZiB1dHhvVG9EZWNvZGVkXG4gICAqXG4gICAqIElNUE9SVEFOVDogQWRkcmVzc2VzIGFyZSBzb3J0ZWQgbGV4aWNvZ3JhcGhpY2FsbHkgYnkgYnl0ZSB2YWx1ZSB0byBtYXRjaFxuICAgKiBvbi1jaGFpbiBzdG9yYWdlIG9yZGVyLiBUaGUgQVBJIG1heSByZXR1cm4gYWRkcmVzc2VzIGluIGFyYml0cmFyeSBvcmRlciwgYnV0XG4gICAqIG9uLWNoYWluIFVUWE9zIGFsd2F5cyBzdG9yZSBhZGRyZXNzZXMgaW4gc29ydGVkIG9yZGVyLlxuICAgKlxuICAgKiBAcGFyYW0gZGVjb2RlZCAtIERlY29kZWRVdHhvT2JqIHRvIGNvbnZlcnRcbiAgICogQHBhcmFtIGFzc2V0SWQgLSBBc3NldCBJRCBhcyBjYjU4IGVuY29kZWQgc3RyaW5nXG4gICAqIEByZXR1cm5zIE5hdGl2ZSBGbGFyZUpTIFV0eG8gb2JqZWN0XG4gICAqL1xuICBwdWJsaWMgZGVjb2RlZFRvVXR4byhkZWNvZGVkOiBEZWNvZGVkVXR4b09iaiwgYXNzZXRJZDogc3RyaW5nKTogVXR4byB7XG4gICAgLy8gQ3JlYXRlIFVUWE9JRCBmcm9tIHR4aWQgYW5kIG91dHB1dCBpbmRleFxuICAgIGNvbnN0IHV0eG9JZCA9IGF2YXhTZXJpYWwuVVRYT0lELmZyb21OYXRpdmUoZGVjb2RlZC50eGlkLCBwYXJzZUludChkZWNvZGVkLm91dHB1dGlkeCwgMTApKTtcblxuICAgIC8vIFBhcnNlIGFkZHJlc3NlcyBmcm9tIGJlY2gzMiBzdHJpbmdzIHRvIGJ5dGUgYnVmZmVyc1xuICAgIGNvbnN0IGFkZHJlc3NCeXRlcyA9IGRlY29kZWQuYWRkcmVzc2VzLm1hcCgoYWRkcikgPT4gdGhpcy5wYXJzZUFkZHJlc3MoYWRkcikpO1xuXG4gICAgLy8gU29ydCBhZGRyZXNzZXMgbGV4aWNvZ3JhcGhpY2FsbHkgYnkgYnl0ZSB2YWx1ZSB0byBtYXRjaCBvbi1jaGFpbiBvcmRlclxuICAgIC8vIFRoaXMgaXMgY3JpdGljYWwgYmVjYXVzZSB0aGUgUC1jaGFpbiBzdG9yZXMgYWRkcmVzc2VzIGluIHNvcnRlZCBvcmRlcixcbiAgICAvLyBhbmQgc2lnSW5kaWNlcyBtdXN0IHJlZmVyZW5jZSB0aGUgY29ycmVjdCBwb3NpdGlvbnMuXG4gICAgY29uc3Qgc29ydGVkQWRkcmVzc0J5dGVzID0gdGhpcy5zb3J0QWRkcmVzc0J1ZmZlcnNCeUhleChhZGRyZXNzQnl0ZXMpO1xuXG4gICAgLy8gQ3JlYXRlIE91dHB1dE93bmVycyB3aXRoIGxvY2t0aW1lLCB0aHJlc2hvbGQsIGFuZCBTT1JURUQgYWRkcmVzc2VzXG4gICAgY29uc3QgbG9ja3RpbWUgPSBkZWNvZGVkLmxvY2t0aW1lID8gQmlnSW50KGRlY29kZWQubG9ja3RpbWUpIDogQmlnSW50KDApO1xuICAgIGNvbnN0IG91dHB1dE93bmVycyA9IE91dHB1dE93bmVycy5mcm9tTmF0aXZlKHNvcnRlZEFkZHJlc3NCeXRlcywgbG9ja3RpbWUsIGRlY29kZWQudGhyZXNob2xkKTtcblxuICAgIC8vIENyZWF0ZSBUcmFuc2Zlck91dHB1dCB3aXRoIGFtb3VudCBhbmQgb3duZXJzXG4gICAgY29uc3QgYW1vdW50ID0gQmlnSW50KGRlY29kZWQuYW1vdW50KTtcbiAgICBjb25zdCB0cmFuc2Zlck91dHB1dCA9IG5ldyBUcmFuc2Zlck91dHB1dChuZXcgQmlnSW50UHIoYW1vdW50KSwgb3V0cHV0T3duZXJzKTtcblxuICAgIC8vIENyZWF0ZSBhbmQgcmV0dXJuIHRoZSBVdHhvXG4gICAgcmV0dXJuIG5ldyBVdHhvKHV0eG9JZCwgSWQuZnJvbVN0cmluZyhhc3NldElkKSwgdHJhbnNmZXJPdXRwdXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgYXJyYXkgb2YgRGVjb2RlZFV0eG9PYmogdG8gbmF0aXZlIEZsYXJlSlMgVXR4byBvYmplY3RzXG4gICAqIEBwYXJhbSBkZWNvZGVkVXR4b3MgLSBBcnJheSBvZiBEZWNvZGVkVXR4b09ialxuICAgKiBAcGFyYW0gYXNzZXRJZCAtIEFzc2V0IElEIGFzIGNiNTggZW5jb2RlZCBzdHJpbmdcbiAgICogQHJldHVybnMgQXJyYXkgb2YgbmF0aXZlIEZsYXJlSlMgVXR4byBvYmplY3RzXG4gICAqL1xuICBwdWJsaWMgZGVjb2RlZFRvVXR4b3MoZGVjb2RlZFV0eG9zOiBEZWNvZGVkVXR4b09ialtdLCBhc3NldElkOiBzdHJpbmcpOiBVdHhvW10ge1xuICAgIHJldHVybiBkZWNvZGVkVXR4b3MubWFwKChkZWNvZGVkKSA9PiB0aGlzLmRlY29kZWRUb1V0eG8oZGVjb2RlZCwgYXNzZXRJZCkpO1xuICB9XG59XG5cbmNvbnN0IHV0aWxzID0gbmV3IFV0aWxzKCk7XG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==