@bitgo-beta/sdk-coin-flrp 1.0.1-beta.29 → 1.0.1-beta.290

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 (118) hide show
  1. package/dist/src/flrp.d.ts +6 -75
  2. package/dist/src/flrp.d.ts.map +1 -1
  3. package/dist/src/flrp.js +13 -298
  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 +51 -0
  8. package/dist/src/lib/ExportInCTxBuilder.d.ts.map +1 -0
  9. package/dist/src/lib/ExportInCTxBuilder.js +186 -0
  10. package/dist/src/lib/ExportInPTxBuilder.d.ts +47 -0
  11. package/dist/src/lib/ExportInPTxBuilder.d.ts.map +1 -0
  12. package/dist/src/lib/ExportInPTxBuilder.js +273 -0
  13. package/dist/src/lib/ImportInCTxBuilder.d.ts +48 -0
  14. package/dist/src/lib/ImportInCTxBuilder.d.ts.map +1 -0
  15. package/dist/src/lib/ImportInCTxBuilder.js +215 -0
  16. package/dist/src/lib/ImportInPTxBuilder.d.ts +33 -0
  17. package/dist/src/lib/ImportInPTxBuilder.d.ts.map +1 -0
  18. package/dist/src/lib/ImportInPTxBuilder.js +180 -0
  19. package/dist/src/lib/atomicInCTransactionBuilder.d.ts +18 -16
  20. package/dist/src/lib/atomicInCTransactionBuilder.d.ts.map +1 -1
  21. package/dist/src/lib/atomicInCTransactionBuilder.js +38 -36
  22. package/dist/src/lib/atomicTransactionBuilder.d.ts +42 -76
  23. package/dist/src/lib/atomicTransactionBuilder.d.ts.map +1 -1
  24. package/dist/src/lib/atomicTransactionBuilder.js +141 -218
  25. package/dist/src/lib/iface.d.ts +50 -51
  26. package/dist/src/lib/iface.d.ts.map +1 -1
  27. package/dist/src/lib/iface.js +22 -10
  28. package/dist/src/lib/index.d.ts +4 -0
  29. package/dist/src/lib/index.d.ts.map +1 -1
  30. package/dist/src/lib/index.js +10 -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 +46 -0
  35. package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts.map +1 -0
  36. package/dist/src/lib/permissionlessValidatorTxBuilder.js +134 -0
  37. package/dist/src/lib/transaction.d.ts +8 -73
  38. package/dist/src/lib/transaction.d.ts.map +1 -1
  39. package/dist/src/lib/transaction.js +157 -207
  40. package/dist/src/lib/transactionBuilder.d.ts +107 -0
  41. package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
  42. package/dist/src/lib/transactionBuilder.js +210 -0
  43. package/dist/src/lib/transactionBuilderFactory.d.ts +35 -30
  44. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
  45. package/dist/src/lib/transactionBuilderFactory.js +133 -74
  46. package/dist/src/lib/utils.d.ts +74 -147
  47. package/dist/src/lib/utils.d.ts.map +1 -1
  48. package/dist/src/lib/utils.js +226 -323
  49. package/dist/test/resources/account.d.ts +49 -0
  50. package/dist/test/resources/account.d.ts.map +1 -0
  51. package/dist/test/resources/account.js +52 -0
  52. package/dist/test/resources/transactionData/exportInC.d.ts +20 -0
  53. package/dist/test/resources/transactionData/exportInC.d.ts.map +1 -0
  54. package/dist/test/resources/transactionData/exportInC.js +34 -0
  55. package/dist/test/resources/transactionData/exportInP.d.ts +69 -0
  56. package/dist/test/resources/transactionData/exportInP.d.ts.map +1 -0
  57. package/dist/test/resources/transactionData/exportInP.js +140 -0
  58. package/dist/test/resources/transactionData/importInC.d.ts +27 -0
  59. package/dist/test/resources/transactionData/importInC.d.ts.map +1 -0
  60. package/dist/test/resources/transactionData/importInC.js +44 -0
  61. package/dist/test/resources/transactionData/importInP.d.ts +35 -0
  62. package/dist/test/resources/transactionData/importInP.d.ts.map +1 -0
  63. package/dist/test/resources/transactionData/importInP.js +58 -0
  64. package/dist/test/unit/lib/exportInCTxBuilder.d.ts +2 -0
  65. package/dist/test/unit/lib/exportInCTxBuilder.d.ts.map +1 -0
  66. package/dist/test/unit/lib/exportInCTxBuilder.js +166 -0
  67. package/dist/test/unit/lib/exportInPTxBuilder.d.ts +2 -0
  68. package/dist/test/unit/lib/exportInPTxBuilder.d.ts.map +1 -0
  69. package/dist/test/unit/lib/exportInPTxBuilder.js +121 -0
  70. package/dist/test/unit/lib/importInCTxBuilder.d.ts +2 -0
  71. package/dist/test/unit/lib/importInCTxBuilder.d.ts.map +1 -0
  72. package/dist/test/unit/lib/importInCTxBuilder.js +47 -0
  73. package/dist/test/unit/lib/importInPTxBuilder.d.ts +2 -0
  74. package/dist/test/unit/lib/importInPTxBuilder.d.ts.map +1 -0
  75. package/dist/test/unit/lib/importInPTxBuilder.js +73 -0
  76. package/dist/test/unit/lib/keyPair.d.ts +2 -0
  77. package/dist/test/unit/lib/keyPair.d.ts.map +1 -0
  78. package/dist/test/unit/lib/keyPair.js +158 -0
  79. package/dist/test/unit/lib/signFlowTestSuit.d.ts +20 -0
  80. package/dist/test/unit/lib/signFlowTestSuit.d.ts.map +1 -0
  81. package/dist/test/unit/lib/signFlowTestSuit.js +89 -0
  82. package/dist/test/unit/lib/utils.js +29 -223
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/package.json +16 -13
  85. package/.eslintignore +0 -5
  86. package/.eslintrc.json +0 -7
  87. package/.mocharc.yml +0 -8
  88. package/CHANGELOG.md +0 -0
  89. package/dist/src/iface.d.ts +0 -25
  90. package/dist/src/iface.d.ts.map +0 -1
  91. package/dist/src/iface.js +0 -3
  92. package/dist/src/lib/constants.d.ts +0 -11
  93. package/dist/src/lib/constants.d.ts.map +0 -1
  94. package/dist/src/lib/constants.js +0 -17
  95. package/dist/src/lib/errors.d.ts +0 -8
  96. package/dist/src/lib/errors.d.ts.map +0 -1
  97. package/dist/src/lib/errors.js +0 -19
  98. package/dist/src/lib/exportInCTxBuilder.d.ts +0 -77
  99. package/dist/src/lib/exportInCTxBuilder.d.ts.map +0 -1
  100. package/dist/src/lib/exportInCTxBuilder.js +0 -170
  101. package/dist/src/lib/exportInPTxBuilder.d.ts +0 -30
  102. package/dist/src/lib/exportInPTxBuilder.d.ts.map +0 -1
  103. package/dist/src/lib/exportInPTxBuilder.js +0 -56
  104. package/dist/test/unit/flrp.d.ts +0 -2
  105. package/dist/test/unit/flrp.d.ts.map +0 -1
  106. package/dist/test/unit/flrp.js +0 -118
  107. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts +0 -2
  108. package/dist/test/unit/lib/atomicTransactionBuilder.d.ts.map +0 -1
  109. package/dist/test/unit/lib/atomicTransactionBuilder.js +0 -222
  110. package/dist/test/unit/lib/exportTxBuilder.d.ts +0 -2
  111. package/dist/test/unit/lib/exportTxBuilder.d.ts.map +0 -1
  112. package/dist/test/unit/lib/exportTxBuilder.js +0 -45
  113. package/dist/test/unit/lib/transaction.d.ts +0 -2
  114. package/dist/test/unit/lib/transaction.d.ts.map +0 -1
  115. package/dist/test/unit/lib/transaction.js +0 -460
  116. package/dist/test/unit/smoke.d.ts +0 -2
  117. package/dist/test/unit/smoke.d.ts.map +0 -1
  118. package/dist/test/unit/smoke.js +0 -23
@@ -1,27 +1,74 @@
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
+ //TODO: need check and validate this method
33
+ this.parseAddress = (address) => {
34
+ return this.stringToAddress(address);
35
+ };
36
+ this.stringToAddress = (address, hrp) => {
37
+ // Handle hex addresses
38
+ if (address.startsWith('0x')) {
39
+ return buffer_1.Buffer.from(address.slice(2), 'hex');
40
+ }
41
+ // Handle raw hex without 0x prefix
42
+ if (/^[0-9a-fA-F]{40}$/.test(address)) {
43
+ return buffer_1.Buffer.from(address, 'hex');
44
+ }
45
+ // Handle Bech32 addresses
46
+ const parts = address.trim().split('-');
47
+ if (parts.length < 2) {
48
+ throw new Error('Error - Valid address should include -');
49
+ }
50
+ const split = parts[1].lastIndexOf('1');
51
+ if (split < 0) {
52
+ throw new Error('Error - Valid bech32 address must include separator (1)');
53
+ }
54
+ const humanReadablePart = parts[1].slice(0, split);
55
+ if (humanReadablePart !== 'flare' && humanReadablePart !== 'costwo') {
56
+ throw new Error('Error - Invalid HRP');
57
+ }
58
+ return buffer_1.Buffer.from(bech32_1.bech32.fromWords(bech32_1.bech32.decode(parts[1]).words));
13
59
  };
14
60
  }
61
+ /**
62
+ * Check if addresses in wallet match UTXO output addresses
63
+ */
15
64
  includeIn(walletAddresses, otxoOutputAddresses) {
16
65
  return walletAddresses.map((a) => otxoOutputAddresses.includes(a)).reduce((a, b) => a && b, true);
17
66
  }
18
67
  /**
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
68
+ * Validates a Flare address or array of addresses
69
+ * @param {string | string[]} address - address(es) to validate
70
+ * @returns {boolean} - validation result
23
71
  */
24
- /** @inheritdoc */
25
72
  isValidAddress(address) {
26
73
  const addressArr = Array.isArray(address) ? address : address.split('~');
27
74
  for (const address of addressArr) {
@@ -31,66 +78,57 @@ class Utils {
31
78
  }
32
79
  return true;
33
80
  }
81
+ // Regex patterns
82
+ // export const ADDRESS_REGEX = /^(^P||NodeID)-[a-zA-Z0-9]+$/;
83
+ // export const HEX_REGEX = /^(0x){0,1}([0-9a-f])+$/i;
34
84
  isValidAddressRegex(address) {
35
- return constants_1.ADDRESS_REGEX.test(address);
85
+ return /^(^P||NodeID)-[a-zA-Z0-9]+$/.test(address);
36
86
  }
37
87
  /**
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
88
+ * Validates a block ID
89
+ * @param {string} hash - block ID to validate
90
+ * @returns {boolean} - validation result
42
91
  */
43
- /** @inheritdoc */
44
92
  isValidBlockId(hash) {
45
- // FlareJS equivalent - check if it's a valid CB58 hash with correct length
46
93
  try {
47
- const decoded = Buffer.from(hash); // FlareJS should provide CB58 utilities
48
- return decoded.length === constants_1.DECODED_BLOCK_ID_LENGTH;
94
+ const decoded = buffer_1.Buffer.from(hash, 'hex');
95
+ return decoded.length === 32;
49
96
  }
50
97
  catch {
51
98
  return false;
52
99
  }
53
100
  }
54
101
  /**
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
102
+ * Validates a public key
103
+ * @param {string} pub - public key to validate
104
+ * @returns {boolean} - validation result
60
105
  */
61
106
  isValidPublicKey(pub) {
62
107
  if ((0, sdk_core_1.isValidXpub)(pub))
63
108
  return true;
64
109
  let pubBuf;
65
- if (pub.length === constants_1.SHORT_PUB_KEY_LENGTH) {
110
+ if (pub.length === 50) {
66
111
  try {
67
- // For FlareJS, we'll need to implement CB58 decode functionality
68
- pubBuf = Buffer.from(pub, 'hex'); // Temporary placeholder
112
+ pubBuf = buffer_1.Buffer.from(pub, 'hex');
69
113
  }
70
114
  catch {
71
115
  return false;
72
116
  }
73
117
  }
74
118
  else {
75
- if (pub.length !== constants_1.COMPRESSED_PUBLIC_KEY_LENGTH && pub.length !== constants_1.UNCOMPRESSED_PUBLIC_KEY_LENGTH) {
119
+ if (pub.length !== 66 && pub.length !== 130)
76
120
  return false;
77
- }
78
121
  const firstByte = pub.slice(0, 2);
79
- // uncompressed public key
80
- if (pub.length === constants_1.UNCOMPRESSED_PUBLIC_KEY_LENGTH && firstByte !== '04') {
122
+ if (pub.length === 130 && firstByte !== '04')
81
123
  return false;
82
- }
83
- // compressed public key
84
- if (pub.length === constants_1.COMPRESSED_PUBLIC_KEY_LENGTH && firstByte !== '02' && firstByte !== '03') {
124
+ if (pub.length === 66 && firstByte !== '02' && firstByte !== '03')
85
125
  return false;
86
- }
87
126
  if (!this.allHexChars(pub))
88
127
  return false;
89
- pubBuf = Buffer.from(pub, 'hex');
128
+ pubBuf = buffer_1.Buffer.from(pub, 'hex');
90
129
  }
91
- // validate the public key using BitGo secp256k1
92
130
  try {
93
- secp256k1_1.ecc.isPoint(pubBuf); // Check if it's a valid point
131
+ secp256k1_1.ecc.isPoint(pubBuf);
94
132
  return true;
95
133
  }
96
134
  catch (e) {
@@ -98,269 +136,131 @@ class Utils {
98
136
  }
99
137
  }
100
138
  /**
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
139
+ * Validates a private key
140
+ * @param {string} prv - private key to validate
141
+ * @returns {boolean} - validation result
110
142
  */
111
143
  isValidPrivateKey(prv) {
112
144
  if ((0, sdk_core_1.isValidXprv)(prv))
113
145
  return true;
114
- if (prv.length !== constants_1.RAW_PRIVATE_KEY_LENGTH && prv.length !== constants_1.SUFFIXED_PRIVATE_KEY_LENGTH) {
146
+ if (prv.length !== 64 && prv.length !== 66)
115
147
  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) {
148
+ if (prv.length === 66 && prv.slice(64) !== '01')
119
149
  return false;
120
- }
121
150
  return this.allHexChars(prv);
122
151
  }
123
152
  /**
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
153
+ * Checks if a string contains only hex characters
128
154
  */
129
- allHexChars(maybe) {
130
- return constants_1.HEX_REGEX.test(maybe);
155
+ allHexChars(str) {
156
+ return /^(0x){0,1}([0-9a-f])+$/i.test(str);
131
157
  }
132
158
  /**
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
159
+ * Creates a signature using the Flare network parameters
160
+ * Returns a 65-byte signature (64 bytes signature + 1 byte recovery parameter)
138
161
  */
139
- isValidEthereumAddress(address) {
140
- if (!address || typeof address !== 'string') {
141
- return false;
162
+ createSignature(network, message, prv) {
163
+ const messageHash = this.sha256(message);
164
+ const signature = secp256k1_1.ecc.sign(messageHash, prv);
165
+ // Get the public key from the private key for recovery parameter determination
166
+ const publicKey = secp256k1_1.ecc.pointFromScalar(prv, true);
167
+ if (!publicKey) {
168
+ throw new Error('Failed to derive public key from private key');
142
169
  }
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];
170
+ // Try recovery with param 0 and 1 to find the correct one
171
+ let recoveryParam = 0;
172
+ for (let i = 0; i <= 1; i++) {
173
+ const recovered = secp256k1_1.ecc.recoverPublicKey(messageHash, signature, i, true);
174
+ if (recovered && buffer_1.Buffer.from(recovered).equals(buffer_1.Buffer.from(publicKey))) {
175
+ recoveryParam = i;
176
+ break;
160
177
  }
161
178
  }
162
- return result;
179
+ // Append recovery parameter to create 65-byte signature
180
+ const sigWithRecovery = buffer_1.Buffer.alloc(65);
181
+ buffer_1.Buffer.from(signature).copy(sigWithRecovery, 0);
182
+ sigWithRecovery[64] = recoveryParam;
183
+ return sigWithRecovery;
163
184
  }
164
185
  /**
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
186
+ * Verifies a signature
170
187
  */
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)
188
+ verifySignature(network, message, signature, publicKey) {
189
+ try {
190
+ const messageHash = this.sha256(message);
191
+ return secp256k1_1.ecc.verify(signature, messageHash, publicKey);
192
+ }
193
+ catch (e) {
177
194
  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
195
  }
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
196
  }
215
197
  /**
216
- * FlareJS wrapper to create signature and return it for credentials
217
- * @param network
218
- * @param message
219
- * @param prv
220
- * @return signature
198
+ * Creates a new signature object
221
199
  */
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
- }
200
+ createNewSig(sigHex) {
201
+ const buffer = buffer_1.Buffer.from(sigHex.padStart(130, '0'), 'hex');
202
+ return new flarejs_1.Signature(buffer);
231
203
  }
232
204
  /**
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
205
+ * Creates an empty signature with embedded address for signature slot identification.
206
+ * The address is embedded at position 90 (after the first 45 zero bytes).
207
+ * This allows the signing logic to determine which slot belongs to which address.
208
+ * @param addressHex The 20-byte address in hex format (40 chars, without 0x prefix)
239
209
  */
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
- }
210
+ createEmptySigWithAddress(addressHex) {
211
+ // First 45 bytes (90 hex chars) are zeros, followed by 20-byte address (40 hex chars)
212
+ const cleanAddr = this.removeHexPrefix(addressHex).toLowerCase();
213
+ const sigHex = '0'.repeat(90) + cleanAddr.padStart(40, '0');
214
+ const buffer = buffer_1.Buffer.from(sigHex, 'hex');
215
+ return new flarejs_1.Signature(buffer);
247
216
  }
248
217
  /**
249
- * FlareJS wrapper to recover signature
250
- * @param network
251
- * @param message
252
- * @param signature
253
- * @return recovered public key
218
+ * Extracts the embedded address from an empty signature.
219
+ * Returns the address hex string (40 chars) or empty string if not found.
254
220
  */
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}`);
221
+ getAddressFromEmptySig(sig) {
222
+ const cleanSig = this.removeHexPrefix(sig);
223
+ if (cleanSig.length >= 130) {
224
+ // Address is at position 90-130 (last 40 hex chars = 20 bytes)
225
+ return cleanSig.substring(90, 130).toLowerCase();
263
226
  }
227
+ return '';
264
228
  }
229
+ /**
230
+ * Computes SHA256 hash
231
+ */
265
232
  sha256(buf) {
266
233
  return (0, crypto_1.createHash)('sha256').update(buf).digest();
267
234
  }
268
235
  /**
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
236
+ * Validates raw transaction format
273
237
  */
274
238
  validateRawTransaction(rawTransaction) {
275
239
  if (!rawTransaction) {
276
240
  throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
277
241
  }
278
- if (!utils.allHexChars(rawTransaction)) {
242
+ if (!this.allHexChars(rawTransaction)) {
279
243
  throw new sdk_core_1.ParseTransactionError('Raw transaction is not hex string');
280
244
  }
281
245
  }
282
246
  /**
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
247
+ * Checks if output is TransferableOutput type
316
248
  */
317
249
  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
- };
250
+ return output?._type === flarejs_1.TypeSymbols.TransferableOutput;
351
251
  }
352
252
  /**
353
- * Return a mapper function to that network address representation.
354
- * @param network required to stringify addresses
355
- * @return mapper function
253
+ * Maps outputs to entry format
356
254
  */
357
255
  mapOutputToEntry(network) {
358
256
  return (output) => {
359
257
  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
258
+ const outputAmount = output.amount();
259
+ const address = output.output
260
+ .getOwners()
261
+ .map((a) => this.addressToString(network.hrp, network.alias, buffer_1.Buffer.from(a)))
262
+ .sort()
263
+ .join(iface_1.ADDRESS_SEPARATOR);
364
264
  return {
365
265
  value: outputAmount.toString(),
366
266
  address,
@@ -372,116 +272,119 @@ class Utils {
372
272
  };
373
273
  }
374
274
  /**
375
- * remove hex prefix (0x)
376
- * @param hex string
377
- * @returns hex without 0x
275
+ * Removes 0x prefix from hex string
378
276
  */
379
277
  removeHexPrefix(hex) {
380
- if (hex.startsWith('0x')) {
381
- return hex.substring(2);
382
- }
383
- return hex;
278
+ return hex.startsWith('0x') ? hex.substring(2) : hex;
384
279
  }
385
280
  /**
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
281
+ * Converts output index to buffer
389
282
  */
390
283
  outputidxNumberToBuffer(outputidx) {
391
- return Buffer.from(Number(outputidx).toString(16).padStart(constants_1.OUTPUT_INDEX_HEX_LENGTH, '0'), 'hex');
284
+ return buffer_1.Buffer.from(Number(outputidx).toString(16).padStart(8, '0'), 'hex');
392
285
  }
393
286
  /**
394
- * Outputidx buffer to number (as string)
395
- * @param {Buffer} outputidx
396
- * @return {string} outputidx number
287
+ * Converts output index buffer to number string
397
288
  */
398
289
  outputidxBufferToNumber(outputidx) {
399
290
  return parseInt(outputidx.toString('hex'), 16).toString();
400
291
  }
292
+ // Required by BaseUtils interface but not implemented
293
+ isValidSignature(signature) {
294
+ throw new sdk_core_1.NotImplementedError('isValidSignature not implemented');
295
+ }
296
+ isValidTransactionId(txId) {
297
+ throw new sdk_core_1.NotImplementedError('isValidTransactionId not implemented');
298
+ }
401
299
  /**
402
- * CB58 decode function - simple Base58 decode implementation
403
- * @param {string} data - CB58 encoded string
404
- * @returns {Buffer} decoded buffer
300
+ * Decodes a base58 string with checksum to a Buffer
405
301
  */
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);
302
+ cb58Decode(str) {
303
+ const decoded = bs58_1.default.decode(str);
304
+ if (!this.validateChecksum(buffer_1.Buffer.from(decoded))) {
305
+ throw new Error('Invalid checksum');
415
306
  }
307
+ return buffer_1.Buffer.from(decoded.slice(0, decoded.length - 4));
416
308
  }
417
309
  /**
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
310
+ * Validates a checksum on a Buffer and returns true if valid, false if not
423
311
  */
424
- addressToString(hrp, chainid, addressBuffer) {
425
- // Simple implementation - in practice this would use bech32 encoding
426
- return `${chainid}-${addressBuffer.toString('hex')}`;
312
+ validateChecksum(buff) {
313
+ const hashSlice = buff.slice(buff.length - 4);
314
+ const calculatedHashSlice = (0, crypto_1.createHash)('sha256')
315
+ .update(buff.slice(0, buff.length - 4))
316
+ .digest()
317
+ .slice(28);
318
+ return hashSlice.toString('hex') === calculatedHashSlice.toString('hex');
427
319
  }
428
320
  /**
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
321
+ * Encodes a Buffer as a base58 string with checksum
433
322
  */
434
- stringToBytes(text) {
435
- return new TextEncoder().encode(text);
323
+ cb58Encode(bytes) {
324
+ const withChecksum = this.addChecksum(bytes);
325
+ return bs58_1.default.encode(withChecksum);
436
326
  }
437
327
  /**
438
- * Convert bytes to string from FlareJS memo
439
- * @param {Uint8Array} bytes - Bytes to convert
440
- * @returns {string} Decoded string
328
+ * Adds a checksum to a Buffer and returns the concatenated result
441
329
  */
442
- bytesToString(bytes) {
443
- return new TextDecoder().decode(bytes);
330
+ addChecksum(buff) {
331
+ const hashSlice = (0, crypto_1.createHash)('sha256').update(buff).digest().slice(28);
332
+ return buffer_1.Buffer.concat([buff, hashSlice]);
444
333
  }
445
334
  /**
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
335
+ * Check if tx is for the blockchainId
336
+ *
337
+ * @param {DeprecatedTx} tx
338
+ * @param {string} blockchainId
339
+ * @returns true if tx is for blockchainId
450
340
  */
451
- createMemoBytes(memo) {
452
- if (memo instanceof Uint8Array) {
453
- return memo;
454
- }
455
- if (typeof memo === 'string') {
456
- return this.stringToBytes(memo);
341
+ // TODO: remove DeprecatedTx usage
342
+ isTransactionOf(tx, blockchainId) {
343
+ // FlareJS equivalent - this would need proper CB58 encoding implementation
344
+ try {
345
+ const txRecord = tx;
346
+ const unsignedTx = txRecord.getUnsignedTx();
347
+ const transaction = unsignedTx.getTransaction();
348
+ const txBlockchainId = transaction.getBlockchainID();
349
+ return buffer_1.Buffer.from(txBlockchainId).toString('hex') === blockchainId;
457
350
  }
458
- if (typeof memo === 'object') {
459
- return this.stringToBytes(JSON.stringify(memo));
351
+ catch (error) {
352
+ return false;
460
353
  }
461
- throw new sdk_core_1.InvalidTransactionError('Invalid memo format');
462
354
  }
463
- /**
464
- * Parse memo bytes to string
465
- * @param {Uint8Array} memoBytes - Memo bytes from FlareJS transaction
466
- * @returns {string} Decoded memo string
467
- */
468
- parseMemoBytes(memoBytes) {
469
- if (memoBytes.length === 0) {
470
- return '';
471
- }
472
- return this.bytesToString(memoBytes);
355
+ flareIdString(value) {
356
+ return new flarejs_1.Id(buffer_1.Buffer.from(value, 'hex'));
473
357
  }
474
358
  /**
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
359
+ * FlareJS wrapper to recover signature
360
+ * @param network
361
+ * @param message
362
+ * @param signature
363
+ * @return recovered public key
479
364
  */
480
- validateMemoSize(memoBytes, maxSize = 4096) {
481
- return memoBytes.length <= maxSize;
365
+ recoverySignature(network, message, signature) {
366
+ try {
367
+ // Hash the message first - must match the hash used in signing
368
+ const messageHash = (0, crypto_1.createHash)('sha256').update(message).digest();
369
+ // Extract recovery parameter and signature
370
+ if (signature.length !== 65) {
371
+ throw new Error('Invalid signature length - expected 65 bytes (64 bytes signature + 1 byte recovery)');
372
+ }
373
+ const recoveryParam = signature[64];
374
+ const sigOnly = signature.slice(0, 64);
375
+ // Recover public key using the provided recovery parameter
376
+ const recovered = secp256k1_1.ecc.recoverPublicKey(messageHash, sigOnly, recoveryParam, true);
377
+ if (!recovered) {
378
+ throw new Error('Failed to recover public key');
379
+ }
380
+ return buffer_1.Buffer.from(recovered);
381
+ }
382
+ catch (error) {
383
+ throw new Error(`Failed to recover signature: ${error}`);
384
+ }
482
385
  }
483
386
  }
484
387
  exports.Utils = Utils;
485
388
  const utils = new Utils();
486
389
  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
390
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQUF1RztBQUN2RyxtREFROEI7QUFFOUIsbUNBQWdDO0FBQ2hDLG1DQUFvQztBQUNwQyxxREFBNEM7QUFDNUMsbUNBQWtFO0FBQ2xFLGdEQUF3QjtBQUN4QixtQ0FBZ0M7QUFFaEMsTUFBYSxLQUFLO0lBQWxCO1FBaVFFOztXQUVHO1FBQ0ksb0JBQWUsR0FBRyxDQUFDLEdBQVcsRUFBRSxNQUFjLEVBQUUsT0FBZSxFQUFVLEVBQUU7WUFDaEYsK0RBQStEO1lBQy9ELE1BQU0sS0FBSyxHQUFHLGVBQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEMsK0VBQStFO1lBQy9FLE9BQU8sR0FBRyxNQUFNLElBQUksZUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNsRCxDQUFDLENBQUM7UUF5Q0YsbURBQW1EO1FBRW5EOzs7O1dBSUc7UUFDSCwyQ0FBMkM7UUFDcEMsaUJBQVksR0FBRyxDQUFDLE9BQWUsRUFBVSxFQUFFO1lBQ2hELE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUM7UUFFSyxvQkFBZSxHQUFHLENBQUMsT0FBZSxFQUFFLEdBQVksRUFBVSxFQUFFO1lBQ2pFLHVCQUF1QjtZQUN2QixJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDN0IsT0FBTyxlQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDOUMsQ0FBQztZQUVELG1DQUFtQztZQUNuQyxJQUFJLG1CQUFtQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUN0QyxPQUFP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Q0FBQztRQUMzRCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBcFpELHNCQW9aQztBQUVELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7QUFDMUIsa0JBQWUsS0FBSyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU2lnbmF0dXJlLCBUcmFuc2ZlcmFibGVPdXRwdXQsIFRyYW5zZmVyT3V0cHV0LCBUeXBlU3ltYm9scywgSWQgfSBmcm9tICdAZmxhcmVuZXR3b3JrL2ZsYXJlanMnO1xuaW1wb3J0IHtcbiAgQmFzZVV0aWxzLFxuICBFbnRyeSxcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIGlzVmFsaWRYcHJ2LFxuICBpc1ZhbGlkWHB1YixcbiAgTm90SW1wbGVtZW50ZWRFcnJvcixcbiAgUGFyc2VUcmFuc2FjdGlvbkVycm9yLFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBGbGFyZU5ldHdvcmsgfSBmcm9tICdAYml0Z28tYmV0YS9zdGF0aWNzJztcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGVjYyB9IGZyb20gJ0BiaXRnby1iZXRhL3NlY3AyNTZrMSc7XG5pbXBvcnQgeyBBRERSRVNTX1NFUEFSQVRPUiwgT3V0cHV0LCBEZXByZWNhdGVkVHggfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCBiczU4IGZyb20gJ2JzNTgnO1xuaW1wb3J0IHsgYmVjaDMyIH0gZnJvbSAnYmVjaDMyJztcblxuZXhwb3J0IGNsYXNzIFV0aWxzIGltcGxlbWVudHMgQmFzZVV0aWxzIHtcbiAgLyoqXG4gICAqIENoZWNrIGlmIGFkZHJlc3NlcyBpbiB3YWxsZXQgbWF0Y2ggVVRYTyBvdXRwdXQgYWRkcmVzc2VzXG4gICAqL1xuICBwdWJsaWMgaW5jbHVkZUluKHdhbGxldEFkZHJlc3Nlczogc3RyaW5nW10sIG90eG9PdXRwdXRBZGRyZXNzZXM6IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHdhbGxldEFkZHJlc3Nlcy5tYXAoKGEpID0+IG90eG9PdXRwdXRBZGRyZXNzZXMuaW5jbHVkZXMoYSkpLnJlZHVjZSgoYSwgYikgPT4gYSAmJiBiLCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBGbGFyZSBhZGRyZXNzIG9yIGFycmF5IG9mIGFkZHJlc3Nlc1xuICAgKiBAcGFyYW0ge3N0cmluZyB8IHN0cmluZ1tdfSBhZGRyZXNzIC0gYWRkcmVzcyhlcykgdG8gdmFsaWRhdGVcbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gdmFsaWRhdGlvbiByZXN1bHRcbiAgICovXG4gIGlzVmFsaWRBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyB8IHN0cmluZ1tdKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYWRkcmVzc0Fycjogc3RyaW5nW10gPSBBcnJheS5pc0FycmF5KGFkZHJlc3MpID8gYWRkcmVzcyA6IGFkZHJlc3Muc3BsaXQoJ34nKTtcblxuICAgIGZvciAoY29uc3QgYWRkcmVzcyBvZiBhZGRyZXNzQXJyKSB7XG4gICAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3NSZWdleChhZGRyZXNzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyBSZWdleCBwYXR0ZXJuc1xuICAvLyBleHBvcnQgY29uc3QgQUREUkVTU19SRUdFWCA9IC9eKF5QfHxOb2RlSUQpLVthLXpBLVowLTldKyQvO1xuICAvLyBleHBvcnQgY29uc3QgSEVYX1JFR0VYID0gL14oMHgpezAsMX0oWzAtOWEtZl0pKyQvaTtcblxuICBwcml2YXRlIGlzVmFsaWRBZGRyZXNzUmVnZXgoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIC9eKF5QfHxOb2RlSUQpLVthLXpBLVowLTldKyQvLnRlc3QoYWRkcmVzcyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGEgYmxvY2sgSURcbiAgICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggLSBibG9jayBJRCB0byB2YWxpZGF0ZVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZEJsb2NrSWQoaGFzaDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGRlY29kZWQgPSBCdWZmZXIuZnJvbShoYXNoLCAnaGV4Jyk7XG4gICAgICByZXR1cm4gZGVjb2RlZC5sZW5ndGggPT09IDMyO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYSBwdWJsaWMga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwdWIgLSBwdWJsaWMga2V5IHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIHZhbGlkYXRpb24gcmVzdWx0XG4gICAqL1xuICBpc1ZhbGlkUHVibGljS2V5KHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzVmFsaWRYcHViKHB1YikpIHJldHVybiB0cnVlO1xuXG4gICAgbGV0IHB1YkJ1ZjogQnVmZmVyO1xuICAgIGlmIChwdWIubGVuZ3RoID09PSA1MCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocHViLmxlbmd0aCAhPT0gNjYgJiYgcHViLmxlbmd0aCAhPT0gMTMwKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIGNvbnN0IGZpcnN0Qnl0ZSA9IHB1Yi5zbGljZSgwLCAyKTtcbiAgICAgIGlmIChwdWIubGVuZ3RoID09PSAxMzAgJiYgZmlyc3RCeXRlICE9PSAnMDQnKSByZXR1cm4gZmFsc2U7XG4gICAgICBpZiAocHViLmxlbmd0aCA9PT0gNjYgJiYgZmlyc3RCeXRlICE9PSAnMDInICYmIGZpcnN0Qnl0ZSAhPT0gJzAzJykgcmV0dXJuIGZhbHNlO1xuICAgICAgaWYgKCF0aGlzLmFsbEhleENoYXJzKHB1YikpIHJldHVybiBmYWxzZTtcblxuICAgICAgcHViQnVmID0gQnVmZmVyLmZyb20ocHViLCAnaGV4Jyk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGVjYy5pc1BvaW50KHB1YkJ1Zik7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIHByaXZhdGUga2V5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcnYgLSBwcml2YXRlIGtleSB0byB2YWxpZGF0ZVxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSB2YWxpZGF0aW9uIHJlc3VsdFxuICAgKi9cbiAgaXNWYWxpZFByaXZhdGVLZXkocHJ2OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoaXNWYWxpZFhwcnYocHJ2KSkgcmV0dXJuIHRydWU7XG4gICAgaWYgKHBydi5sZW5ndGggIT09IDY0ICYmIHBydi5sZW5ndGggIT09IDY2KSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKHBydi5sZW5ndGggPT09IDY2ICYmIHBydi5zbGljZSg2NCkgIT09ICcwMScpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5hbGxIZXhDaGFycyhwcnYpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIHN0cmluZyBjb250YWlucyBvbmx5IGhleCBjaGFyYWN0ZXJzXG4gICAqL1xuICBhbGxIZXhDaGFycyhzdHI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAvXigweCl7MCwxfShbMC05YS1mXSkrJC9pLnRlc3Qoc3RyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgc2lnbmF0dXJlIHVzaW5nIHRoZSBGbGFyZSBuZXR3b3JrIHBhcmFtZXRlcnNcbiAgICogUmV0dXJucyBhIDY1LWJ5dGUgc2lnbmF0dXJlICg2NCBieXRlcyBzaWduYXR1cmUgKyAxIGJ5dGUgcmVjb3ZlcnkgcGFyYW1ldGVyKVxuICAgKi9cbiAgY3JlYXRlU2lnbmF0dXJlKG5ldHdvcms6IEZsYXJlTmV0d29yaywgbWVzc2FnZTogQnVmZmVyLCBwcnY6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgY29uc3QgbWVzc2FnZUhhc2ggPSB0aGlzLnNoYTI1NihtZXNzYWdlKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBlY2Muc2lnbihtZXNzYWdlSGFzaCwgcHJ2KTtcblxuICAgIC8vIEdldCB0aGUgcHVibGljIGtleSBmcm9tIHRoZSBwcml2YXRlIGtleSBmb3IgcmVjb3ZlcnkgcGFyYW1ldGVyIGRldGVybWluYXRpb25cbiAgICBjb25zdCBwdWJsaWNLZXkgPSBlY2MucG9pbnRGcm9tU2NhbGFyKHBydiwgdHJ1ZSk7XG4gICAgaWYgKCFwdWJsaWNLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGRlcml2ZSBwdWJsaWMga2V5IGZyb20gcHJpdmF0ZSBrZXknKTtcbiAgICB9XG5cbiAgICAvLyBUcnkgcmVjb3Zlcnkgd2l0aCBwYXJhbSAwIGFuZCAxIHRvIGZpbmQgdGhlIGNvcnJlY3Qgb25lXG4gICAgbGV0IHJlY292ZXJ5UGFyYW0gPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDE7IGkrKykge1xuICAgICAgY29uc3QgcmVjb3ZlcmVkID0gZWNjLnJlY292ZXJQdWJsaWNLZXkobWVzc2FnZUhhc2gsIHNpZ25hdHVyZSwgaSwgdHJ1ZSk7XG4gICAgICBpZiAocmVjb3ZlcmVkICYmIEJ1ZmZlci5mcm9tKHJlY292ZXJlZCkuZXF1YWxzKEJ1ZmZlci5mcm9tKHB1YmxpY0tleSkpKSB7XG4gICAgICAgIHJlY292ZXJ5UGFyYW0gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBcHBlbmQgcmVjb3ZlcnkgcGFyYW1ldGVyIHRvIGNyZWF0ZSA2NS1ieXRlIHNpZ25hdHVyZVxuICAgIGNvbnN0IHNpZ1dpdGhSZWNvdmVyeSA9IEJ1ZmZlci5hbGxvYyg2NSk7XG4gICAgQnVmZmVyLmZyb20oc2lnbmF0dXJlKS5jb3B5KHNpZ1dpdGhSZWNvdmVyeSwgMCk7XG4gICAgc2lnV2l0aFJlY292ZXJ5WzY0XSA9IHJlY292ZXJ5UGFyYW07XG5cbiAgICByZXR1cm4gc2lnV2l0aFJlY292ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIGEgc2lnbmF0dXJlXG4gICAqL1xuICB2ZXJpZnlTaWduYXR1cmUobmV0d29yazogRmxhcmVOZXR3b3JrLCBtZXNzYWdlOiBCdWZmZXIsIHNpZ25hdHVyZTogQnVmZmVyLCBwdWJsaWNLZXk6IEJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBtZXNzYWdlSGFzaCA9IHRoaXMuc2hhMjU2KG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIGVjYy52ZXJpZnkoc2lnbmF0dXJlLCBtZXNzYWdlSGFzaCwgcHVibGljS2V5KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgc2lnbmF0dXJlIG9iamVjdFxuICAgKi9cbiAgY3JlYXRlTmV3U2lnKHNpZ0hleDogc3RyaW5nKTogU2lnbmF0dXJlIHtcbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuZnJvbShzaWdIZXgucGFkU3RhcnQoMTMwLCAnMCcpLCAnaGV4Jyk7XG4gICAgcmV0dXJuIG5ldyBTaWduYXR1cmUoYnVmZmVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGVtcHR5IHNpZ25hdHVyZSB3aXRoIGVtYmVkZGVkIGFkZHJlc3MgZm9yIHNpZ25hdHVyZSBzbG90IGlkZW50aWZpY2F0aW9uLlxuICAgKiBUaGUgYWRkcmVzcyBpcyBlbWJlZGRlZCBhdCBwb3NpdGlvbiA5MCAoYWZ0ZXIgdGhlIGZpcnN0IDQ1IHplcm8gYnl0ZXMpLlxuICAgKiBUaGlzIGFsbG93cyB0aGUgc2lnbmluZyBsb2dpYyB0byBkZXRlcm1pbmUgd2hpY2ggc2xvdCBiZWxvbmdzIHRvIHdoaWNoIGFkZHJlc3MuXG4gICAqIEBwYXJhbSBhZGRyZXNzSGV4IFRoZSAyMC1ieXRlIGFkZHJlc3MgaW4gaGV4IGZvcm1hdCAoNDAgY2hhcnMsIHdpdGhvdXQgMHggcHJlZml4KVxuICAgKi9cbiAgY3JlYXRlRW1wdHlTaWdXaXRoQWRkcmVzcyhhZGRyZXNzSGV4OiBzdHJpbmcpOiBTaWduYXR1cmUge1xuICAgIC8vIEZpcnN0IDQ1IGJ5dGVzICg5MCBoZXggY2hhcnMpIGFyZSB6ZXJvcywgZm9sbG93ZWQgYnkgMjAtYnl0ZSBhZGRyZXNzICg0MCBoZXggY2hhcnMpXG4gICAgY29uc3QgY2xlYW5BZGRyID0gdGhpcy5yZW1vdmVIZXhQcmVmaXgoYWRkcmVzc0hleCkudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBzaWdIZXggPSAnMCcucmVwZWF0KDkwKSArIGNsZWFuQWRkci5wYWRTdGFydCg0MCwgJzAnKTtcbiAgICBjb25zdCBidWZmZXIgPSBCdWZmZXIuZnJvbShzaWdIZXgsICdoZXgnKTtcbiAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShidWZmZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3RzIHRoZSBlbWJlZGRlZCBhZGRyZXNzIGZyb20gYW4gZW1wdHkgc2lnbmF0dXJlLlxuICAgKiBSZXR1cm5zIHRoZSBhZGRyZXNzIGhleCBzdHJpbmcgKDQwIGNoYXJzKSBvciBlbXB0eSBzdHJpbmcgaWYgbm90IGZvdW5kLlxuICAgKi9cbiAgZ2V0QWRkcmVzc0Zyb21FbXB0eVNpZyhzaWc6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgY2xlYW5TaWcgPSB0aGlzLnJlbW92ZUhleFByZWZpeChzaWcpO1xuICAgIGlmIChjbGVhblNpZy5sZW5ndGggPj0gMTMwKSB7XG4gICAgICAvLyBBZGRyZXNzIGlzIGF0IHBvc2l0aW9uIDkwLTEzMCAobGFzdCA0MCBoZXggY2hhcnMgPSAyMCBieXRlcylcbiAgICAgIHJldHVybiBjbGVhblNpZy5zdWJzdHJpbmcoOTAsIDEzMCkudG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbXB1dGVzIFNIQTI1NiBoYXNoXG4gICAqL1xuICBzaGEyNTYoYnVmOiBVaW50OEFycmF5KTogQnVmZmVyIHtcbiAgICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGJ1ZikuZGlnZXN0KCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHJhdyB0cmFuc2FjdGlvbiBmb3JtYXRcbiAgICovXG4gIHZhbGlkYXRlUmF3VHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghcmF3VHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignUmF3IHRyYW5zYWN0aW9uIGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5hbGxIZXhDaGFycyhyYXdUcmFuc2FjdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ1JhdyB0cmFuc2FjdGlvbiBpcyBub3QgaGV4IHN0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgb3V0cHV0IGlzIFRyYW5zZmVyYWJsZU91dHB1dCB0eXBlXG4gICAqL1xuICBpc1RyYW5zZmVyYWJsZU91dHB1dChvdXRwdXQ6IE91dHB1dCk6IG91dHB1dCBpcyBUcmFuc2ZlcmFibGVPdXRwdXQge1xuICAgIHJldHVybiBvdXRwdXQ/Ll90eXBlID09PSBUeXBlU3ltYm9scy5UcmFuc2ZlcmFibGVPdXRwdXQ7XG4gIH1cblxuICAvKipcbiAgICogTWFwcyBvdXRwdXRzIHRvIGVudHJ5IGZvcm1hdFxuICAgKi9cbiAgbWFwT3V0cHV0VG9FbnRyeShuZXR3b3JrOiBGbGFyZU5ldHdvcmspOiAoT3V0cHV0KSA9PiBFbnRyeSB7XG4gICAgcmV0dXJuIChvdXRwdXQ6IE91dHB1dCkgPT4ge1xuICAgICAgaWYgKHRoaXMuaXNUcmFuc2ZlcmFibGVPdXRwdXQob3V0cHV0KSkge1xuICAgICAgICBjb25zdCBvdXRwdXRBbW91bnQgPSBvdXRwdXQuYW1vdW50KCk7XG4gICAgICAgIGNvbnN0IGFkZHJlc3MgPSAob3V0cHV0Lm91dHB1dCBhcyBUcmFuc2Zlck91dHB1dClcbiAgICAgICAgICAuZ2V0T3duZXJzKClcbiAgICAgICAgICAubWFwKChhKSA9PiB0aGlzLmFkZHJlc3NUb1N0cmluZyhuZXR3b3JrLmhycCwgbmV0d29yay5hbGlhcywgQnVmZmVyLmZyb20oYSkpKVxuICAgICAgICAgIC5zb3J0KClcbiAgICAgICAgICAuam9pbihBRERSRVNTX1NFUEFSQVRPUik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmFsdWU6IG91dHB1dEFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgIGFkZHJlc3MsXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgb3V0cHV0IHR5cGUnKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgMHggcHJlZml4IGZyb20gaGV4IHN0cmluZ1xuICAgKi9cbiAgcmVtb3ZlSGV4UHJlZml4KGhleDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gaGV4LnN0YXJ0c1dpdGgoJzB4JykgPyBoZXguc3Vic3RyaW5nKDIpIDogaGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIG91dHB1dCBpbmRleCB0byBidWZmZXJcbiAgICovXG4gIG91dHB1dGlkeE51bWJlclRvQnVmZmVyKG91dHB1dGlkeDogc3RyaW5nKTogQnVmZmVyIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oTnVtYmVyKG91dHB1dGlkeCkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDgsICcwJyksICdoZXgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBvdXRwdXQgaW5kZXggYnVmZmVyIHRvIG51bWJlciBzdHJpbmdcbiAgICovXG4gIG91dHB1dGlkeEJ1ZmZlclRvTnVtYmVyKG91dHB1dGlkeDogQnVmZmVyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcGFyc2VJbnQob3V0cHV0aWR4LnRvU3RyaW5nKCdoZXgnKSwgMTYpLnRvU3RyaW5nKCk7XG4gIH1cblxuICAvLyBSZXF1aXJlZCBieSBCYXNlVXRpbHMgaW50ZXJmYWNlIGJ1dCBub3QgaW1wbGVtZW50ZWRcbiAgaXNWYWxpZFNpZ25hdHVyZShzaWduYXR1cmU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKCdpc1ZhbGlkU2lnbmF0dXJlIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgaXNWYWxpZFRyYW5zYWN0aW9uSWQodHhJZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoJ2lzVmFsaWRUcmFuc2FjdGlvbklkIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciBtZXRob2QgdG8gY29udmVydCBhZGRyZXNzIGNvbXBvbmVudHMgdG8gc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgYWRkcmVzc1RvU3RyaW5nID0gKGhycDogc3RyaW5nLCBwcmVmaXg6IHN0cmluZywgYWRkcmVzczogQnVmZmVyKTogc3RyaW5nID0+IHtcbiAgICAvLyBDb252ZXJ0IHRoZSBhZGRyZXNzIGJ5dGVzIHRvIDUtYml0IHdvcmRzIGZvciBiZWNoMzIgZW5jb2RpbmdcbiAgICBjb25zdCB3b3JkcyA9IGJlY2gzMi50b1dvcmRzKGFkZHJlc3MpO1xuICAgIC8vIENyZWF0ZSB0aGUgZnVsbCBiZWNoMzIgYWRkcmVzcyB3aXRoIGZvcm1hdDogUC17aHJwfTF7YmVjaDMyX2VuY29kZWRfYWRkcmVzc31cbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke2JlY2gzMi5lbmNvZGUoaHJwLCB3b3Jkcyl9YDtcbiAgfTtcblxuICAvKipcbiAgICogRGVjb2RlcyBhIGJhc2U1OCBzdHJpbmcgd2l0aCBjaGVja3N1bSB0byBhIEJ1ZmZlclxuICAgKi9cbiAgcHVibGljIGNiNThEZWNvZGUoc3RyOiBzdHJpbmcpOiBCdWZmZXIge1xuICAgIGNvbnN0IGRlY29kZWQgPSBiczU4LmRlY29kZShzdHIpO1xuICAgIGlmICghdGhpcy52YWxpZGF0ZUNoZWNrc3VtKEJ1ZmZlci5mcm9tKGRlY29kZWQpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNoZWNrc3VtJyk7XG4gICAgfVxuICAgIHJldHVybiBCdWZmZXIuZnJvbShkZWNvZGVkLnNsaWNlKDAsIGRlY29kZWQubGVuZ3RoIC0gNCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhIGNoZWNrc3VtIG9uIGEgQnVmZmVyIGFuZCByZXR1cm5zIHRydWUgaWYgdmFsaWQsIGZhbHNlIGlmIG5vdFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUNoZWNrc3VtKGJ1ZmY6IEJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGhhc2hTbGljZSA9IGJ1ZmYuc2xpY2UoYnVmZi5sZW5ndGggLSA0KTtcbiAgICBjb25zdCBjYWxjdWxhdGVkSGFzaFNsaWNlID0gY3JlYXRlSGFzaCgnc2hhMjU2JylcbiAgICAgIC51cGRhdGUoYnVmZi5zbGljZSgwLCBidWZmLmxlbmd0aCAtIDQpKVxuICAgICAgLmRpZ2VzdCgpXG4gICAgICAuc2xpY2UoMjgpO1xuICAgIHJldHVybiBoYXNoU2xpY2UudG9TdHJpbmcoJ2hleCcpID09PSBjYWxjdWxhdGVkSGFzaFNsaWNlLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmNvZGVzIGEgQnVmZmVyIGFzIGEgYmFzZTU4IHN0cmluZyB3aXRoIGNoZWNrc3VtXG4gICAqL1xuICBwdWJsaWMgY2I1OEVuY29kZShieXRlczogQnVmZmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCB3aXRoQ2hlY2tzdW0gPSB0aGlzLmFkZENoZWNrc3VtKGJ5dGVzKTtcbiAgICByZXR1cm4gYnM1OC5lbmNvZGUod2l0aENoZWNrc3VtKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgY2hlY2tzdW0gdG8gYSBCdWZmZXIgYW5kIHJldHVybnMgdGhlIGNvbmNhdGVuYXRlZCByZXN1bHRcbiAgICovXG4gIHByaXZhdGUgYWRkQ2hlY2tzdW0oYnVmZjogQnVmZmVyKTogQnVmZmVyIHtcbiAgICBjb25zdCBoYXNoU2xpY2UgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoYnVmZikuZGlnZXN0KCkuc2xpY2UoMjgpO1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtidWZmLCBoYXNoU2xpY2VdKTtcbiAgfVxuXG4gIC8vIEluIHV0aWxzLnRzLCBhZGQgdGhpcyBtZXRob2QgdG8gdGhlIFV0aWxzIGNsYXNzOlxuXG4gIC8qKlxuICAgKiBQYXJzZSBhbiBhZGRyZXNzIHN0cmluZyBpbnRvIGEgQnVmZmVyXG4gICAqIEBwYXJhbSBhZGRyZXNzIC0gVGhlIGFkZHJlc3MgdG8gcGFyc2VcbiAgICogQHJldHVybnMgQnVmZmVyIGNvbnRhaW5pbmcgdGhlIHBhcnNlZCBhZGRyZXNzXG4gICAqL1xuICAvL1RPRE86IG5lZWQgY2hlY2sgYW5kIHZhbGlkYXRlIHRoaXMgbWV0aG9kXG4gIHB1YmxpYyBwYXJzZUFkZHJlc3MgPSAoYWRkcmVzczogc3RyaW5nKTogQnVmZmVyID0+IHtcbiAgICByZXR1cm4gdGhpcy5zdHJpbmdUb0FkZHJlc3MoYWRkcmVzcyk7XG4gIH07XG5cbiAgcHVibGljIHN0cmluZ1RvQWRkcmVzcyA9IChhZGRyZXNzOiBzdHJpbmcsIGhycD86IHN0cmluZyk6IEJ1ZmZlciA9PiB7XG4gICAgLy8gSGFuZGxlIGhleCBhZGRyZXNzZXNcbiAgICBpZiAoYWRkcmVzcy5zdGFydHNXaXRoKCcweCcpKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20oYWRkcmVzcy5zbGljZSgyKSwgJ2hleCcpO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSByYXcgaGV4IHdpdGhvdXQgMHggcHJlZml4XG4gICAgaWYgKC9eWzAtOWEtZkEtRl17NDB9JC8udGVzdChhZGRyZXNzKSkge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGFkZHJlc3MsICdoZXgnKTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgQmVjaDMyIGFkZHJlc3Nlc1xuICAgIGNvbnN0IHBhcnRzID0gYWRkcmVzcy50cmltKCkuc3BsaXQoJy0nKTtcbiAgICBpZiAocGFydHMubGVuZ3RoIDwgMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFcnJvciAtIFZhbGlkIGFkZHJlc3Mgc2hvdWxkIGluY2x1ZGUgLScpO1xuICAgIH1cblxuICAgIGNvbnN0IHNwbGl0ID0gcGFydHNbMV0ubGFzdEluZGV4T2YoJzEnKTtcbiAgICBpZiAoc3BsaXQgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIC0gVmFsaWQgYmVjaDMyIGFkZHJlc3MgbXVzdCBpbmNsdWRlIHNlcGFyYXRvciAoMSknKTtcbiAgICB9XG5cbiAgICBjb25zdCBodW1hblJlYWRhYmxlUGFydCA9IHBhcnRzWzFdLnNsaWNlKDAsIHNwbGl0KTtcbiAgICBpZiAoaHVtYW5SZWFkYWJsZVBhcnQgIT09ICdmbGFyZScgJiYgaHVtYW5SZWFkYWJsZVBhcnQgIT09ICdjb3N0d28nKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIC0gSW52YWxpZCBIUlAnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gQnVmZmVyLmZyb20oYmVjaDMyLmZyb21Xb3JkcyhiZWNoMzIuZGVjb2RlKHBhcnRzWzFdKS53b3JkcykpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0eCBpcyBmb3IgdGhlIGJsb2NrY2hhaW5JZFxuICAgKlxuICAgKiBAcGFyYW0ge0RlcHJlY2F0ZWRUeH0gdHhcbiAgICogQHBhcmFtIHtzdHJpbmd9IGJsb2NrY2hhaW5JZFxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHR4IGlzIGZvciBibG9ja2NoYWluSWRcbiAgICovXG4gIC8vIFRPRE86IHJlbW92ZSBEZXByZWNhdGVkVHggdXNhZ2VcbiAgaXNUcmFuc2FjdGlvbk9mKHR4OiBEZXByZWNhdGVkVHgsIGJsb2NrY2hhaW5JZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgLy8gRmxhcmVKUyBlcXVpdmFsZW50IC0gdGhpcyB3b3VsZCBuZWVkIHByb3BlciBDQjU4IGVuY29kaW5nIGltcGxlbWVudGF0aW9uXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHR4UmVjb3JkID0gdHggYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHggPSAodHhSZWNvcmQuZ2V0VW5zaWduZWRUeCBhcyAoKSA9PiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikoKTtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKHVuc2lnbmVkVHguZ2V0VHJhbnNhY3Rpb24gYXMgKCkgPT4gUmVjb3JkPHN0cmluZywgdW5rbm93bj4pKCk7XG4gICAgICBjb25zdCB0eEJsb2NrY2hhaW5JZCA9ICh0cmFuc2FjdGlvbi5nZXRCbG9ja2NoYWluSUQgYXMgKCkgPT4gdW5rbm93bikoKTtcbiAgICAgIHJldHVybiBCdWZmZXIuZnJvbSh0eEJsb2NrY2hhaW5JZCBhcyBzdHJpbmcpLnRvU3RyaW5nKCdoZXgnKSA9PT0gYmxvY2tjaGFpbklkO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgZmxhcmVJZFN0cmluZyh2YWx1ZTogc3RyaW5nKTogSWQge1xuICAgIHJldHVybiBuZXcgSWQoQnVmZmVyLmZyb20odmFsdWUsICdoZXgnKSk7XG4gIH1cblxuICAvKipcbiAgICogRmxhcmVKUyB3cmFwcGVyIHRvIHJlY292ZXIgc2lnbmF0dXJlXG4gICAqIEBwYXJhbSBuZXR3b3JrXG4gICAqIEBwYXJhbSBtZXNzYWdlXG4gICAqIEBwYXJhbSBzaWduYXR1cmVcbiAgICogQHJldHVybiByZWNvdmVyZWQgcHVibGljIGtleVxuICAgKi9cbiAgcmVjb3ZlcnlTaWduYXR1cmUobmV0d29yazogRmxhcmVOZXR3b3JrLCBtZXNzYWdlOiBCdWZmZXIsIHNpZ25hdHVyZTogQnVmZmVyKTogQnVmZmVyIHtcbiAgICB0cnkge1xuICAgICAgLy8gSGFzaCB0aGUgbWVzc2FnZSBmaXJzdCAtIG11c3QgbWF0Y2ggdGhlIGhhc2ggdXNlZCBpbiBzaWduaW5nXG4gICAgICBjb25zdCBtZXNzYWdlSGFzaCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShtZXNzYWdlKS5kaWdlc3QoKTtcblxuICAgICAgLy8gRXh0cmFjdCByZWNvdmVyeSBwYXJhbWV0ZXIgYW5kIHNpZ25hdHVyZVxuICAgICAgaWYgKHNpZ25hdHVyZS5sZW5ndGggIT09IDY1KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzaWduYXR1cmUgbGVuZ3RoIC0gZXhwZWN0ZWQgNjUgYnl0ZXMgKDY0IGJ5dGVzIHNpZ25hdHVyZSArIDEgYnl0ZSByZWNvdmVyeSknKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVjb3ZlcnlQYXJhbSA9IHNpZ25hdHVyZVs2NF07XG4gICAgICBjb25zdCBzaWdPbmx5ID0gc2lnbmF0dXJlLnNsaWNlKDAsIDY0KTtcblxuICAgICAgLy8gUmVjb3ZlciBwdWJsaWMga2V5IHVzaW5nIHRoZSBwcm92aWRlZCByZWNvdmVyeSBwYXJhbWV0ZXJcbiAgICAgIGNvbnN0IHJlY292ZXJlZCA9IGVjYy5yZWNvdmVyUHVibGljS2V5KG1lc3NhZ2VIYXNoLCBzaWdPbmx5LCByZWNvdmVyeVBhcmFtLCB0cnVlKTtcbiAgICAgIGlmICghcmVjb3ZlcmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIHJlY292ZXIgcHVibGljIGtleScpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20ocmVjb3ZlcmVkKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmVjb3ZlciBzaWduYXR1cmU6ICR7ZXJyb3J9YCk7XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IHV0aWxzID0gbmV3IFV0aWxzKCk7XG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==