@ksangkuk10/wallet-controller 1.7.14

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 (124) hide show
  1. package/README.md +7 -0
  2. package/_commonjs/controller.js +704 -0
  3. package/_commonjs/env.js +9 -0
  4. package/_commonjs/exception/isError.js +15 -0
  5. package/_commonjs/exception/mapExtensionTxError.js +46 -0
  6. package/_commonjs/exception/mapWalletConnectError.js +69 -0
  7. package/_commonjs/getChainOptions.js +57 -0
  8. package/_commonjs/index.js +22 -0
  9. package/_commonjs/modules/connect-modal/index.js +80 -0
  10. package/_commonjs/modules/connect-modal/style.js +161 -0
  11. package/_commonjs/modules/extension-router/ExtensionRouter.js +241 -0
  12. package/_commonjs/modules/extension-router/index.js +19 -0
  13. package/_commonjs/modules/extension-router/modal.js +80 -0
  14. package/_commonjs/modules/extension-router/modal.style.js +161 -0
  15. package/_commonjs/modules/extension-router/multiChannel.js +18 -0
  16. package/_commonjs/modules/extension-router/session.js +37 -0
  17. package/_commonjs/modules/extension-router/types.js +16 -0
  18. package/_commonjs/modules/legacy-extension/LegacyExtensionConnector.js +143 -0
  19. package/_commonjs/modules/legacy-extension/createFixedExtension.js +236 -0
  20. package/_commonjs/modules/legacy-extension/index.js +19 -0
  21. package/_commonjs/modules/readonly-wallet/connect.js +24 -0
  22. package/_commonjs/modules/readonly-wallet/index.js +20 -0
  23. package/_commonjs/modules/readonly-wallet/modal.js +123 -0
  24. package/_commonjs/modules/readonly-wallet/modal.style.js +204 -0
  25. package/_commonjs/modules/readonly-wallet/storage.js +40 -0
  26. package/_commonjs/modules/readonly-wallet/types.js +3 -0
  27. package/_commonjs/modules/walletconnect/connect.js +421 -0
  28. package/_commonjs/modules/walletconnect/errors.js +51 -0
  29. package/_commonjs/modules/walletconnect/impl/socket-transport/index.js +204 -0
  30. package/_commonjs/modules/walletconnect/impl/socket-transport/network.js +30 -0
  31. package/_commonjs/modules/walletconnect/index.js +22 -0
  32. package/_commonjs/modules/walletconnect/modal.js +147 -0
  33. package/_commonjs/modules/walletconnect/modal.style.js +138 -0
  34. package/_commonjs/modules/walletconnect/types.js +13 -0
  35. package/_commonjs/operators/getExtensions.js +55 -0
  36. package/_commonjs/operators/toConnectedWallet.js +24 -0
  37. package/_commonjs/operators/toLcdClient.js +15 -0
  38. package/_commonjs/utils/browser-check.js +47 -0
  39. package/_commonjs/utils/checkExtensionReady.js +28 -0
  40. package/_commonjs/utils/sortConnections.js +13 -0
  41. package/_commonjs/verifyBytes.js +19 -0
  42. package/controller.d.ts +220 -0
  43. package/controller.js +697 -0
  44. package/env.d.ts +2 -0
  45. package/env.js +5 -0
  46. package/exception/isError.d.ts +3 -0
  47. package/exception/isError.js +11 -0
  48. package/exception/mapExtensionTxError.d.ts +5 -0
  49. package/exception/mapExtensionTxError.js +41 -0
  50. package/exception/mapWalletConnectError.d.ts +6 -0
  51. package/exception/mapWalletConnectError.js +63 -0
  52. package/getChainOptions.d.ts +3 -0
  53. package/getChainOptions.js +53 -0
  54. package/index.d.ts +6 -0
  55. package/index.js +6 -0
  56. package/modules/connect-modal/index.d.ts +2 -0
  57. package/modules/connect-modal/index.js +76 -0
  58. package/modules/connect-modal/style.d.ts +1 -0
  59. package/modules/connect-modal/style.js +158 -0
  60. package/modules/extension-router/ExtensionRouter.d.ts +43 -0
  61. package/modules/extension-router/ExtensionRouter.js +237 -0
  62. package/modules/extension-router/index.d.ts +2 -0
  63. package/modules/extension-router/index.js +3 -0
  64. package/modules/extension-router/modal.d.ts +2 -0
  65. package/modules/extension-router/modal.js +76 -0
  66. package/modules/extension-router/modal.style.d.ts +1 -0
  67. package/modules/extension-router/modal.style.js +158 -0
  68. package/modules/extension-router/multiChannel.d.ts +13 -0
  69. package/modules/extension-router/multiChannel.js +14 -0
  70. package/modules/extension-router/session.d.ts +8 -0
  71. package/modules/extension-router/session.js +31 -0
  72. package/modules/extension-router/types.d.ts +35 -0
  73. package/modules/extension-router/types.js +13 -0
  74. package/modules/legacy-extension/LegacyExtensionConnector.d.ts +30 -0
  75. package/modules/legacy-extension/LegacyExtensionConnector.js +139 -0
  76. package/modules/legacy-extension/createFixedExtension.d.ts +46 -0
  77. package/modules/legacy-extension/createFixedExtension.js +232 -0
  78. package/modules/legacy-extension/index.d.ts +2 -0
  79. package/modules/legacy-extension/index.js +3 -0
  80. package/modules/readonly-wallet/connect.d.ts +8 -0
  81. package/modules/readonly-wallet/connect.js +19 -0
  82. package/modules/readonly-wallet/index.d.ts +3 -0
  83. package/modules/readonly-wallet/index.js +4 -0
  84. package/modules/readonly-wallet/modal.d.ts +7 -0
  85. package/modules/readonly-wallet/modal.js +119 -0
  86. package/modules/readonly-wallet/modal.style.d.ts +1 -0
  87. package/modules/readonly-wallet/modal.style.js +201 -0
  88. package/modules/readonly-wallet/storage.d.ts +4 -0
  89. package/modules/readonly-wallet/storage.js +34 -0
  90. package/modules/readonly-wallet/types.d.ts +5 -0
  91. package/modules/readonly-wallet/types.js +2 -0
  92. package/modules/walletconnect/connect.d.ts +42 -0
  93. package/modules/walletconnect/connect.js +390 -0
  94. package/modules/walletconnect/errors.d.ts +22 -0
  95. package/modules/walletconnect/errors.js +41 -0
  96. package/modules/walletconnect/impl/socket-transport/index.d.ts +39 -0
  97. package/modules/walletconnect/impl/socket-transport/index.js +199 -0
  98. package/modules/walletconnect/impl/socket-transport/network.d.ts +8 -0
  99. package/modules/walletconnect/impl/socket-transport/network.js +28 -0
  100. package/modules/walletconnect/index.d.ts +5 -0
  101. package/modules/walletconnect/index.js +6 -0
  102. package/modules/walletconnect/modal.d.ts +12 -0
  103. package/modules/walletconnect/modal.js +143 -0
  104. package/modules/walletconnect/modal.style.d.ts +1 -0
  105. package/modules/walletconnect/modal.style.js +135 -0
  106. package/modules/walletconnect/types.d.ts +24 -0
  107. package/modules/walletconnect/types.js +10 -0
  108. package/operators/getExtensions.d.ts +9 -0
  109. package/operators/getExtensions.js +51 -0
  110. package/operators/toConnectedWallet.d.ts +4 -0
  111. package/operators/toConnectedWallet.js +20 -0
  112. package/operators/toLcdClient.d.ts +4 -0
  113. package/operators/toLcdClient.js +11 -0
  114. package/package.json +550 -0
  115. package/utils/browser-check.d.ts +3 -0
  116. package/utils/browser-check.js +38 -0
  117. package/utils/checkExtensionReady.d.ts +6 -0
  118. package/utils/checkExtensionReady.js +24 -0
  119. package/utils/sortConnections.d.ts +2 -0
  120. package/utils/sortConnections.js +9 -0
  121. package/verifyBytes.d.ts +4 -0
  122. package/verifyBytes.js +15 -0
  123. package/~/.npm/_cacache/content-v2/sha512/ad/b5/8c87dfae7c208906a88f1997b323933e7efb4e481bcfdc559cb13199d077e1b40abcb161561a293ca59cd98aae224cd0877555e6e7a2e11021bc55ebedf4 +0 -0
  124. package/~/.npm/_cacache/index-v5/6a/39/c03f62d7353a7cc1411e180ec37c393f9fedcfd081fa567f67bf32e6fb68 +2 -0
package/controller.js ADDED
@@ -0,0 +1,697 @@
1
+ import { AccAddress, PublicKey, SimplePublicKey, Tx, } from '@xpla/xpla.js';
2
+ import { ConnectType, WalletApp, WalletStatus, } from '@ksangkuk10/wallet-types';
3
+ import { WebExtensionTxStatus, } from '@ksangkuk10/web-extension-interface';
4
+ import deepEqual from 'fast-deep-equal';
5
+ import { BehaviorSubject, combineLatest, firstValueFrom, } from 'rxjs';
6
+ import { filter, map } from 'rxjs/operators';
7
+ import { CHROME_EXTENSION_INSTALL_URL, DEFAULT_CHROME_EXTENSION_COMPATIBLE_BROWSER_CHECK, } from './env';
8
+ import { mapExtensionSignBytesError, mapExtensionTxError, } from './exception/mapExtensionTxError';
9
+ import { mapWalletConnectError, mapWalletConnectSignError, mapWalletConnectSignBytesError, } from './exception/mapWalletConnectError';
10
+ import { selectConnection } from './modules/connect-modal';
11
+ import { ExtensionRouter, ExtensionRouterStatus, } from './modules/extension-router';
12
+ import { getXplaExtensions, } from './modules/extension-router/multiChannel';
13
+ import { connect as reConnect, connectIfSessionExists as reConnectIfSessionExists, readonlyWalletModal, } from './modules/readonly-wallet';
14
+ import { connect as wcConnect, connectIfSessionExists as wcConnectIfSessionExists, WalletConnectSessionStatus, } from './modules/walletconnect';
15
+ import { getExtensions } from './operators/getExtensions';
16
+ import { toConnectedWallet } from './operators/toConnectedWallet';
17
+ import { toLcdClient } from './operators/toLcdClient';
18
+ import { isDesktopChrome } from './utils/browser-check';
19
+ import { checkExtensionReady } from './utils/checkExtensionReady';
20
+ import { sortConnections } from './utils/sortConnections';
21
+ const CONNECTIONS = {
22
+ [ConnectType.READONLY]: {
23
+ type: ConnectType.READONLY,
24
+ name: 'View an address',
25
+ icon: 'https://assets.xpla.io/icon/wallet-provider/readonly.svg',
26
+ },
27
+ [ConnectType.WALLETCONNECT]: {
28
+ type: ConnectType.WALLETCONNECT,
29
+ name: 'Wallet Connect',
30
+ icon: 'https://assets.xpla.io/icon/wallet-provider/walletconnect.svg',
31
+ },
32
+ };
33
+ const DEFAULT_WAITING_CHROME_EXTENSION_INSTALL_CHECK = 1000 * 3;
34
+ const WALLETCONNECT_SUPPORT_FEATURES = new Set([
35
+ 'post', 'sign', 'sign-bytes'
36
+ ]);
37
+ const EMPTY_SUPPORT_FEATURES = new Set();
38
+ //noinspection ES6MissingAwait
39
+ export class WalletController {
40
+ constructor(options) {
41
+ var _a;
42
+ this.options = options;
43
+ this.extension = null;
44
+ this.walletConnect = null;
45
+ this.readonlyWallet = null;
46
+ this.disableReadonlyWallet = null;
47
+ this.disableExtension = null;
48
+ this.disableWalletConnect = null;
49
+ /**
50
+ * Some mobile wallet emulates the behavior of chrome extension.
51
+ * It confirms that the current connection environment is such a wallet.
52
+ * (If you are running connect() by checking availableConnectType, you do not need to use this API.)
53
+ *
54
+ * @see Wallet#isChromeExtensionCompatibleBrowser
55
+ */
56
+ this.isChromeExtensionCompatibleBrowser = () => {
57
+ var _a;
58
+ return ((_a = this.options.dangerously__chromeExtensionCompatibleBrowserCheck) !== null && _a !== void 0 ? _a : DEFAULT_CHROME_EXTENSION_COMPATIBLE_BROWSER_CHECK)(navigator.userAgent);
59
+ };
60
+ /**
61
+ * available connect types on the browser
62
+ *
63
+ * @see Wallet#availableConnectTypes
64
+ */
65
+ this.availableConnectTypes = () => {
66
+ return this._availableConnectTypes.asObservable();
67
+ };
68
+ /**
69
+ * available connections includes identifier, name, icon
70
+ *
71
+ * @see Wallet#availableConnections
72
+ */
73
+ this.availableConnections = () => {
74
+ return this._availableConnectTypes.pipe(map((connectTypes) => {
75
+ const connections = [];
76
+ for (const connectType of connectTypes) {
77
+ if (connectType === ConnectType.EXTENSION) {
78
+ const xplaExtensions = getXplaExtensions();
79
+ for (const xplaExtension of xplaExtensions) {
80
+ connections.push(memoConnection(ConnectType.EXTENSION, xplaExtension.name, xplaExtension.icon, xplaExtension.identifier));
81
+ }
82
+ }
83
+ else {
84
+ connections.push(CONNECTIONS[connectType]);
85
+ }
86
+ }
87
+ return sortConnections(connections);
88
+ }));
89
+ };
90
+ /**
91
+ * available install types on the browser
92
+ *
93
+ * in this time, this only contains [ConnectType.EXTENSION]
94
+ *
95
+ * @see Wallet#availableInstallTypes
96
+ */
97
+ this.availableInstallTypes = () => {
98
+ return this._availableInstallTypes.asObservable();
99
+ };
100
+ /**
101
+ * available installations includes identifier, name, icon, url
102
+ *
103
+ * @see Wallet#availableInstallations
104
+ */
105
+ this.availableInstallations = () => {
106
+ return combineLatest([this.availableConnections(), getExtensions()]).pipe(map(([connections, extensions]) => {
107
+ const installedIdentifiers = new Set(connections
108
+ .filter(({ type, identifier }) => {
109
+ return type === ConnectType.EXTENSION && !!identifier;
110
+ })
111
+ .map(({ identifier }) => {
112
+ return identifier;
113
+ }));
114
+ return extensions
115
+ .filter(({ identifier }) => {
116
+ return !installedIdentifiers.has(identifier);
117
+ })
118
+ .map(({ name, identifier, icon, url }) => {
119
+ return {
120
+ type: ConnectType.EXTENSION,
121
+ identifier,
122
+ name,
123
+ icon,
124
+ url,
125
+ };
126
+ });
127
+ }));
128
+ };
129
+ /**
130
+ * @see Wallet#status
131
+ * @see Wallet#network
132
+ * @see Wallet#wallets
133
+ */
134
+ this.states = () => {
135
+ return this._states.asObservable();
136
+ };
137
+ /** get connectedWallet */
138
+ this.connectedWallet = () => {
139
+ return this._states.pipe(toConnectedWallet(this));
140
+ };
141
+ /** get lcdClient */
142
+ this.lcdClient = (lcdClientConfig) => {
143
+ return this._states.pipe(toLcdClient(lcdClientConfig));
144
+ };
145
+ /**
146
+ * reload the connected wallet states
147
+ *
148
+ * in this time, this only work on the ConnectType.EXTENSION
149
+ *
150
+ * @see Wallet#recheckStatus
151
+ */
152
+ this.refetchStates = () => {
153
+ var _a;
154
+ if (this.disableExtension) {
155
+ (_a = this.extension) === null || _a === void 0 ? void 0 : _a.refetchStates();
156
+ }
157
+ };
158
+ /**
159
+ * @deprecated Please use availableInstallations
160
+ *
161
+ * install for the connect type
162
+ *
163
+ * @see Wallet#install
164
+ */
165
+ this.install = (type) => {
166
+ if (type === ConnectType.EXTENSION) {
167
+ // TODO separate install links by browser types
168
+ window.open(CHROME_EXTENSION_INSTALL_URL, '_blank');
169
+ }
170
+ else {
171
+ console.warn(`[WalletController] ConnectType "${type}" does not support install() function`);
172
+ }
173
+ };
174
+ /**
175
+ * connect to wallet
176
+ *
177
+ * @see Wallet#connect
178
+ */
179
+ this.connect = async (_type, _identifier, _walletApp) => {
180
+ var _a, _b, _c, _d;
181
+ let type;
182
+ let identifier;
183
+ if (!!_type) {
184
+ type = _type;
185
+ identifier = _identifier;
186
+ }
187
+ else {
188
+ const connections = await firstValueFrom(this.availableConnections());
189
+ const selector = (_a = this.options.selectConnection) !== null && _a !== void 0 ? _a : selectConnection;
190
+ const selected = await selector(connections);
191
+ if (!selected) {
192
+ return;
193
+ }
194
+ type = selected[0];
195
+ identifier = selected[1];
196
+ }
197
+ switch (type) {
198
+ case ConnectType.READONLY:
199
+ const networks = Object.keys(this.options.walletConnectChainIds).map((chainId) => this.options.walletConnectChainIds[+chainId]);
200
+ const createReadonlyWalletSession = (_d = (_c = (_b = this.options).createReadonlyWalletSession) === null || _c === void 0 ? void 0 : _c.call(_b, networks)) !== null && _d !== void 0 ? _d : readonlyWalletModal({ networks });
201
+ const readonlyWalletSession = await createReadonlyWalletSession;
202
+ if (readonlyWalletSession) {
203
+ this.enableReadonlyWallet(reConnect(readonlyWalletSession));
204
+ }
205
+ break;
206
+ case ConnectType.WALLETCONNECT:
207
+ this.enableWalletConnect(wcConnect(this.options, false, _walletApp));
208
+ break;
209
+ case ConnectType.EXTENSION:
210
+ if (!this.extension) {
211
+ throw new Error(`extension instance is not created!`);
212
+ }
213
+ this.extension.connect(identifier);
214
+ this.enableExtension();
215
+ break;
216
+ default:
217
+ throw new Error(`Unknown ConnectType!`);
218
+ }
219
+ };
220
+ /**
221
+ * manual connect to read only session
222
+ *
223
+ * @see Wallet#connectReadonly
224
+ */
225
+ this.connectReadonly = (xplaAddress, network) => {
226
+ this.enableReadonlyWallet(reConnect({
227
+ xplaAddress,
228
+ network,
229
+ }));
230
+ };
231
+ /** @see Wallet#disconnect */
232
+ this.disconnect = () => {
233
+ var _a, _b, _c;
234
+ (_a = this.disableReadonlyWallet) === null || _a === void 0 ? void 0 : _a.call(this);
235
+ this.disableReadonlyWallet = null;
236
+ (_b = this.disableExtension) === null || _b === void 0 ? void 0 : _b.call(this);
237
+ this.disableExtension = null;
238
+ (_c = this.disableWalletConnect) === null || _c === void 0 ? void 0 : _c.call(this);
239
+ this.disableWalletConnect = null;
240
+ this.updateStates(this._notConnected);
241
+ };
242
+ /**
243
+ * @see Wallet#post
244
+ * @param tx
245
+ * @param xplaAddress only available new extension
246
+ */
247
+ this.post = async (tx, xplaAddress, walletApp) => {
248
+ // ---------------------------------------------
249
+ // extension
250
+ // ---------------------------------------------
251
+ if (this.disableExtension) {
252
+ return new Promise((resolve, reject) => {
253
+ if (!this.extension) {
254
+ reject(new Error(`extension instance not created!`));
255
+ return;
256
+ }
257
+ const subscription = this.extension.post(tx, xplaAddress).subscribe({
258
+ next: (txResult) => {
259
+ if (txResult.status === WebExtensionTxStatus.SUCCEED) {
260
+ resolve({
261
+ ...tx,
262
+ result: txResult.payload,
263
+ success: true,
264
+ });
265
+ subscription.unsubscribe();
266
+ }
267
+ },
268
+ error: (error) => {
269
+ reject(mapExtensionTxError(tx, error));
270
+ subscription.unsubscribe();
271
+ },
272
+ });
273
+ });
274
+ }
275
+ // ---------------------------------------------
276
+ // wallet connect
277
+ // ---------------------------------------------
278
+ else if (this.walletConnect) {
279
+ return this.walletConnect
280
+ .post(tx, walletApp)
281
+ .then((result) => ({
282
+ ...tx,
283
+ result,
284
+ success: true,
285
+ }))
286
+ .catch((error) => {
287
+ throw mapWalletConnectError(tx, error);
288
+ });
289
+ }
290
+ else {
291
+ throw new Error(`There are no connections that can be posting tx!`);
292
+ }
293
+ };
294
+ /**
295
+ * @see Wallet#sign
296
+ * @param tx
297
+ * @param xplaAddress only available new extension
298
+ */
299
+ this.sign = async (tx, xplaAddress, walletApp) => {
300
+ if (this.disableExtension) {
301
+ return new Promise((resolve, reject) => {
302
+ if (!this.extension) {
303
+ reject(new Error(`extension instance is not created!`));
304
+ return;
305
+ }
306
+ const subscription = this.extension.sign(tx, xplaAddress).subscribe({
307
+ next: (txResult) => {
308
+ if (txResult.status === WebExtensionTxStatus.SUCCEED) {
309
+ resolve({
310
+ ...tx,
311
+ result: Tx.fromData(txResult.payload),
312
+ success: true,
313
+ });
314
+ subscription.unsubscribe();
315
+ }
316
+ },
317
+ error: (error) => {
318
+ reject(mapExtensionTxError(tx, error));
319
+ subscription.unsubscribe();
320
+ },
321
+ });
322
+ });
323
+ }
324
+ // ---------------------------------------------
325
+ // wallet connect
326
+ // ---------------------------------------------
327
+ else if (this.walletConnect) {
328
+ if (walletApp && walletApp === WalletApp.XPLA_GAMES) {
329
+ throw new Error(`There are no connections that can be signing!`);
330
+ }
331
+ return this.walletConnect
332
+ .sign(tx, walletApp)
333
+ .then((result) => {
334
+ return {
335
+ ...tx,
336
+ result: Tx.fromData(result, false),
337
+ success: true,
338
+ };
339
+ })
340
+ .catch((error) => {
341
+ throw mapWalletConnectSignError(tx, error);
342
+ });
343
+ }
344
+ else {
345
+ throw new Error(`There are no connections that can be signing!`);
346
+ }
347
+ };
348
+ /**
349
+ * @see Wallet#signBytes
350
+ * @param bytes
351
+ * @param xplaAddress only available new extension
352
+ */
353
+ this.signBytes = async (bytes, xplaAddress, walletApp) => {
354
+ if (this.disableExtension) {
355
+ return new Promise((resolve, reject) => {
356
+ if (!this.extension) {
357
+ reject(new Error(`extension instance is not created!`));
358
+ return;
359
+ }
360
+ const subscription = this.extension
361
+ .signBytes(bytes, xplaAddress)
362
+ .subscribe({
363
+ next: (txResult) => {
364
+ if (txResult.status === WebExtensionTxStatus.SUCCEED) {
365
+ resolve({
366
+ result: {
367
+ recid: txResult.payload.recid,
368
+ signature: Uint8Array.from(Buffer.from(txResult.payload.signature, 'base64')),
369
+ public_key: txResult.payload.public_key
370
+ ? PublicKey.fromData(txResult.payload.public_key)
371
+ : undefined,
372
+ },
373
+ success: true,
374
+ });
375
+ subscription.unsubscribe();
376
+ }
377
+ },
378
+ error: (error) => {
379
+ reject(mapExtensionSignBytesError(bytes, error));
380
+ subscription.unsubscribe();
381
+ },
382
+ });
383
+ });
384
+ }
385
+ // ---------------------------------------------
386
+ // wallet connect
387
+ // ---------------------------------------------
388
+ else if (this.walletConnect) {
389
+ if (walletApp && walletApp === WalletApp.XPLA_GAMES) {
390
+ throw new Error(`There are no connections that can be signing bytes!`);
391
+ }
392
+ return this.walletConnect
393
+ .signBytes(bytes, walletApp)
394
+ .then((result) => {
395
+ const key = new SimplePublicKey(String(result.public_key)).toData();
396
+ return {
397
+ result: {
398
+ recid: result.recid,
399
+ signature: Uint8Array.from(Buffer.from(result.signature, 'base64')),
400
+ public_key: key
401
+ ? PublicKey.fromData(key)
402
+ : undefined,
403
+ },
404
+ success: true,
405
+ };
406
+ })
407
+ .catch((error) => {
408
+ throw mapWalletConnectSignBytesError(bytes, error);
409
+ });
410
+ }
411
+ else {
412
+ throw new Error(`There are no connections that can be signing bytes!`);
413
+ }
414
+ };
415
+ /**
416
+ * @see Wallet#hasCW20Tokens
417
+ * @param chainID
418
+ * @param tokenAddrs Token addresses
419
+ */
420
+ this.hasCW20Tokens = async (chainID, ...tokenAddrs) => {
421
+ if (this.availableExtensionFeature('cw20-token')) {
422
+ return this.extension.hasCW20Tokens(chainID, ...tokenAddrs);
423
+ }
424
+ throw new Error(`Does not support hasCW20Tokens() on this connection`);
425
+ };
426
+ /**
427
+ * @see Wallet#addCW20Tokens
428
+ * @param chainID
429
+ * @param tokenAddrs Token addresses
430
+ */
431
+ this.addCW20Tokens = async (chainID, ...tokenAddrs) => {
432
+ if (this.availableExtensionFeature('cw20-token')) {
433
+ return this.extension.addCW20Tokens(chainID, ...tokenAddrs);
434
+ }
435
+ throw new Error(`Does not support addCW20Tokens() on this connection`);
436
+ };
437
+ /**
438
+ * @see Wallet#hasNetwork
439
+ * @param network
440
+ */
441
+ this.hasNetwork = (network) => {
442
+ if (this.availableExtensionFeature('network')) {
443
+ return this.extension.hasNetwork(network);
444
+ }
445
+ throw new Error(`Does not support hasNetwork() on this connection`);
446
+ };
447
+ /**
448
+ * @see Wallet#hasNetwork
449
+ * @param network
450
+ */
451
+ this.addNetwork = (network) => {
452
+ if (this.availableExtensionFeature('network')) {
453
+ return this.extension.addNetwork(network);
454
+ }
455
+ throw new Error(`Does not support addNetwork() on this connection`);
456
+ };
457
+ // ================================================================
458
+ // internal
459
+ // connect type changing
460
+ // ================================================================
461
+ this.availableExtensionFeature = (feature) => {
462
+ if (this.disableExtension && this.extension) {
463
+ const states = this.extension.getLastStates();
464
+ return (states.type === ExtensionRouterStatus.WALLET_CONNECTED &&
465
+ states.supportFeatures.has(feature));
466
+ }
467
+ };
468
+ this.updateStates = (next) => {
469
+ const prev = this._states.getValue();
470
+ if (next.status === WalletStatus.WALLET_CONNECTED &&
471
+ next.wallets.length === 0) {
472
+ next = {
473
+ status: WalletStatus.WALLET_NOT_CONNECTED,
474
+ network: next.network,
475
+ };
476
+ }
477
+ if (prev.status !== next.status || !deepEqual(prev, next)) {
478
+ this._states.next(next);
479
+ }
480
+ };
481
+ this.enableReadonlyWallet = (readonlyWallet) => {
482
+ var _a, _b, _c;
483
+ (_a = this.disableWalletConnect) === null || _a === void 0 ? void 0 : _a.call(this);
484
+ (_b = this.disableExtension) === null || _b === void 0 ? void 0 : _b.call(this);
485
+ if (this.readonlyWallet === readonlyWallet ||
486
+ (((_c = this.readonlyWallet) === null || _c === void 0 ? void 0 : _c.xplaAddress) === readonlyWallet.xplaAddress &&
487
+ this.readonlyWallet.network === readonlyWallet.network)) {
488
+ return;
489
+ }
490
+ if (this.readonlyWallet) {
491
+ this.readonlyWallet.disconnect();
492
+ }
493
+ this.readonlyWallet = readonlyWallet;
494
+ this.updateStates({
495
+ status: WalletStatus.WALLET_CONNECTED,
496
+ network: readonlyWallet.network,
497
+ wallets: [
498
+ {
499
+ connectType: ConnectType.READONLY,
500
+ xplaAddress: readonlyWallet.xplaAddress,
501
+ design: 'readonly',
502
+ },
503
+ ],
504
+ supportFeatures: EMPTY_SUPPORT_FEATURES,
505
+ connection: CONNECTIONS.READONLY,
506
+ });
507
+ this.disableReadonlyWallet = () => {
508
+ readonlyWallet.disconnect();
509
+ this.readonlyWallet = null;
510
+ this.disableReadonlyWallet = null;
511
+ };
512
+ };
513
+ this.enableExtension = () => {
514
+ var _a, _b;
515
+ (_a = this.disableReadonlyWallet) === null || _a === void 0 ? void 0 : _a.call(this);
516
+ (_b = this.disableWalletConnect) === null || _b === void 0 ? void 0 : _b.call(this);
517
+ if (this.disableExtension || !this.extension) {
518
+ return;
519
+ }
520
+ const extensionSubscription = this.extension.states().subscribe({
521
+ next: (extensionStates) => {
522
+ if (extensionStates.type === ExtensionRouterStatus.WALLET_CONNECTED &&
523
+ AccAddress.validate(extensionStates.wallet.xplaAddress)) {
524
+ this.updateStates({
525
+ status: WalletStatus.WALLET_CONNECTED,
526
+ network: extensionStates.network,
527
+ wallets: [
528
+ {
529
+ connectType: ConnectType.EXTENSION,
530
+ xplaAddress: extensionStates.wallet.xplaAddress,
531
+ design: extensionStates.wallet.design,
532
+ },
533
+ ],
534
+ supportFeatures: extensionStates.supportFeatures,
535
+ connection: memoConnection(ConnectType.EXTENSION, extensionStates.extensionInfo.name, extensionStates.extensionInfo.icon, extensionStates.extensionInfo.identifier),
536
+ });
537
+ }
538
+ else {
539
+ this.updateStates(this._notConnected);
540
+ }
541
+ },
542
+ });
543
+ this.disableExtension = () => {
544
+ var _a;
545
+ (_a = this.extension) === null || _a === void 0 ? void 0 : _a.disconnect();
546
+ extensionSubscription.unsubscribe();
547
+ this.disableExtension = null;
548
+ };
549
+ };
550
+ this.enableWalletConnect = (walletConnect) => {
551
+ var _a, _b;
552
+ (_a = this.disableReadonlyWallet) === null || _a === void 0 ? void 0 : _a.call(this);
553
+ (_b = this.disableExtension) === null || _b === void 0 ? void 0 : _b.call(this);
554
+ if (this.walletConnect === walletConnect) {
555
+ return;
556
+ }
557
+ if (this.walletConnect) {
558
+ this.walletConnect.disconnect();
559
+ }
560
+ this.walletConnect = walletConnect;
561
+ const subscribeWalletConnect = (wc) => {
562
+ return wc.session().subscribe({
563
+ next: (status) => {
564
+ var _a;
565
+ switch (status.status) {
566
+ case WalletConnectSessionStatus.CONNECTED:
567
+ this.updateStates({
568
+ status: WalletStatus.WALLET_CONNECTED,
569
+ network: (_a = this.options.walletConnectChainIds[status.chainId]) !== null && _a !== void 0 ? _a : this.options.defaultNetwork,
570
+ wallets: [
571
+ {
572
+ connectType: ConnectType.WALLETCONNECT,
573
+ xplaAddress: status.xplaAddress,
574
+ design: 'walletconnect',
575
+ },
576
+ ],
577
+ supportFeatures: WALLETCONNECT_SUPPORT_FEATURES,
578
+ connection: CONNECTIONS.WALLETCONNECT,
579
+ });
580
+ break;
581
+ default:
582
+ this.updateStates(this._notConnected);
583
+ break;
584
+ }
585
+ },
586
+ });
587
+ };
588
+ const walletConnectSessionSubscription = subscribeWalletConnect(walletConnect);
589
+ this.disableWalletConnect = () => {
590
+ var _a;
591
+ (_a = this.walletConnect) === null || _a === void 0 ? void 0 : _a.disconnect();
592
+ this.walletConnect = null;
593
+ walletConnectSessionSubscription.unsubscribe();
594
+ this.disableWalletConnect = null;
595
+ };
596
+ };
597
+ this._notConnected = {
598
+ status: WalletStatus.WALLET_NOT_CONNECTED,
599
+ network: options.defaultNetwork,
600
+ };
601
+ this._initializing = {
602
+ status: WalletStatus.INITIALIZING,
603
+ network: options.defaultNetwork,
604
+ };
605
+ this._availableConnectTypes = new BehaviorSubject([
606
+ ConnectType.READONLY,
607
+ ConnectType.WALLETCONNECT,
608
+ ]);
609
+ this._availableInstallTypes = new BehaviorSubject([]);
610
+ this._states = new BehaviorSubject(this._initializing);
611
+ let numSessionCheck = 0;
612
+ // wait checking the availability of the chrome extension
613
+ // 0. check if extension wallet session is exists
614
+ checkExtensionReady((_a = options.waitingChromeExtensionInstallCheck) !== null && _a !== void 0 ? _a : DEFAULT_WAITING_CHROME_EXTENSION_INSTALL_CHECK, this.isChromeExtensionCompatibleBrowser()).then((ready) => {
615
+ var _a;
616
+ if (ready) {
617
+ this._availableConnectTypes.next([
618
+ ConnectType.EXTENSION,
619
+ ConnectType.WALLETCONNECT,
620
+ ConnectType.READONLY,
621
+ ]);
622
+ this.extension = new ExtensionRouter({
623
+ hostWindow: window,
624
+ selectExtension: options.selectExtension,
625
+ dangerously__chromeExtensionCompatibleBrowserCheck: (_a = options.dangerously__chromeExtensionCompatibleBrowserCheck) !== null && _a !== void 0 ? _a : DEFAULT_CHROME_EXTENSION_COMPATIBLE_BROWSER_CHECK,
626
+ defaultNetwork: options.defaultNetwork,
627
+ });
628
+ const subscription = this.extension
629
+ .states()
630
+ .pipe(filter(({ type }) => type !== ExtensionRouterStatus.INITIALIZING))
631
+ .subscribe((extensionStates) => {
632
+ try {
633
+ subscription.unsubscribe();
634
+ }
635
+ catch (_a) { }
636
+ if (extensionStates.type === ExtensionRouterStatus.WALLET_CONNECTED &&
637
+ !this.disableWalletConnect &&
638
+ !this.disableReadonlyWallet) {
639
+ this.enableExtension();
640
+ }
641
+ else if (numSessionCheck === 0) {
642
+ numSessionCheck += 1;
643
+ }
644
+ else {
645
+ this.updateStates(this._notConnected);
646
+ }
647
+ });
648
+ }
649
+ else {
650
+ if (isDesktopChrome(this.isChromeExtensionCompatibleBrowser())) {
651
+ this._availableInstallTypes.next([ConnectType.EXTENSION]);
652
+ }
653
+ if (numSessionCheck === 0) {
654
+ numSessionCheck += 1;
655
+ }
656
+ else {
657
+ this.updateStates(this._notConnected);
658
+ }
659
+ }
660
+ });
661
+ // 1. check if readonly wallet session is exists
662
+ const draftReadonlyWallet = reConnectIfSessionExists();
663
+ if (draftReadonlyWallet) {
664
+ this.enableReadonlyWallet(draftReadonlyWallet);
665
+ return;
666
+ }
667
+ // 2. check if walletconnect sesison is exists
668
+ const draftWalletConnect = wcConnectIfSessionExists(options);
669
+ if (draftWalletConnect &&
670
+ draftWalletConnect.getLatestSession().status ===
671
+ WalletConnectSessionStatus.CONNECTED) {
672
+ this.enableWalletConnect(draftWalletConnect);
673
+ }
674
+ else if (numSessionCheck === 0) {
675
+ numSessionCheck += 1;
676
+ }
677
+ else {
678
+ this.updateStates(this._notConnected);
679
+ }
680
+ }
681
+ }
682
+ const memoizedConnections = new Map();
683
+ function memoConnection(connectType, name, icon, identifier = '') {
684
+ const key = [connectType, name, icon, identifier].join(';');
685
+ if (memoizedConnections.has(key)) {
686
+ return memoizedConnections.get(key);
687
+ }
688
+ const connection = {
689
+ type: connectType,
690
+ name,
691
+ icon,
692
+ identifier,
693
+ };
694
+ memoizedConnections.set(key, connection);
695
+ return connection;
696
+ }
697
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9Aa3NhbmdrdWsxMC93YWxsZXQtY29udHJvbGxlci9jb250cm9sbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxVQUFVLEVBR1YsU0FBUyxFQUNULGVBQWUsRUFDZixFQUFFLEdBRUgsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUdMLFdBQVcsRUFNWCxTQUFTLEVBR1QsWUFBWSxHQUNiLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUVMLG9CQUFvQixHQUNyQixNQUFNLHFDQUFxQyxDQUFDO0FBQzdDLE9BQU8sU0FBUyxNQUFNLGlCQUFpQixDQUFDO0FBQ3hDLE9BQU8sRUFDTCxlQUFlLEVBQ2YsYUFBYSxFQUNiLGNBQWMsR0FHZixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUNMLDRCQUE0QixFQUM1QixpREFBaUQsR0FDbEQsTUFBTSxPQUFPLENBQUM7QUFDZixPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLG1CQUFtQixHQUNwQixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIseUJBQXlCLEVBQ3pCLDhCQUE4QixHQUMvQixNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzNELE9BQU8sRUFDTCxlQUFlLEVBQ2YscUJBQXFCLEdBQ3RCLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUVMLGlCQUFpQixHQUNsQixNQUFNLHlDQUF5QyxDQUFDO0FBQ2pELE9BQU8sRUFDTCxPQUFPLElBQUksU0FBUyxFQUNwQixzQkFBc0IsSUFBSSx3QkFBd0IsRUFFbEQsbUJBQW1CLEdBRXBCLE1BQU0sMkJBQTJCLENBQUM7QUFDbkMsT0FBTyxFQUNMLE9BQU8sSUFBSSxTQUFTLEVBQ3BCLHNCQUFzQixJQUFJLHdCQUF3QixFQUdsRCwwQkFBMEIsR0FDM0IsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUF3RjFELE1BQU0sV0FBVyxHQUFHO0lBQ2xCLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1FBQ3RCLElBQUksRUFBRSxXQUFXLENBQUMsUUFBUTtRQUMxQixJQUFJLEVBQUUsaUJBQWlCO1FBQ3ZCLElBQUksRUFBRSwwREFBMEQ7S0FDbkQ7SUFDZixDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsRUFBRTtRQUMzQixJQUFJLEVBQUUsV0FBVyxDQUFDLGFBQWE7UUFDL0IsSUFBSSxFQUFFLGdCQUFnQjtRQUN0QixJQUFJLEVBQUUsK0RBQStEO0tBQ3hEO0NBQ1AsQ0FBQztBQUVYLE1BQU0sOENBQThDLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQztBQUVoRSxNQUFNLDhCQUE4QixHQUFHLElBQUksR0FBRyxDQUEyQjtJQUN2RSxNQUFNLEVBQUUsTUFBTSxFQUFFLFlBQVk7Q0FDN0IsQ0FBQyxDQUFDO0FBRUgsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsRUFBNEIsQ0FBQztBQUVuRSw4QkFBOEI7QUFDOUIsTUFBTSxPQUFPLGdCQUFnQjtJQWdCM0IsWUFBcUIsT0FBZ0M7O1FBQWhDLFlBQU8sR0FBUCxPQUFPLENBQXlCO1FBZjdDLGNBQVMsR0FBMkIsSUFBSSxDQUFDO1FBQ3pDLGtCQUFhLEdBQW1DLElBQUksQ0FBQztRQUNyRCxtQkFBYyxHQUFvQyxJQUFJLENBQUM7UUFNdkQsMEJBQXFCLEdBQXdCLElBQUksQ0FBQztRQUNsRCxxQkFBZ0IsR0FBd0IsSUFBSSxDQUFDO1FBQzdDLHlCQUFvQixHQUF3QixJQUFJLENBQUM7UUE2R3pEOzs7Ozs7V0FNRztRQUNILHVDQUFrQyxHQUFHLEdBQVksRUFBRTs7WUFDakQsT0FBTyxDQUNMLE1BQUEsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrREFBa0QsbUNBQy9ELGlEQUFpRCxDQUNsRCxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN6QixDQUFDLENBQUM7UUFFRjs7OztXQUlHO1FBQ0gsMEJBQXFCLEdBQUcsR0FBOEIsRUFBRTtZQUN0RCxPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNwRCxDQUFDLENBQUM7UUFFRjs7OztXQUlHO1FBQ0gseUJBQW9CLEdBQUcsR0FBNkIsRUFBRTtZQUNwRCxPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQ3JDLEdBQUcsQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFO2dCQUNuQixNQUFNLFdBQVcsR0FBaUIsRUFBRSxDQUFDO2dCQUVyQyxLQUFLLE1BQU0sV0FBVyxJQUFJLFlBQVksRUFBRTtvQkFDdEMsSUFBSSxXQUFXLEtBQUssV0FBVyxDQUFDLFNBQVMsRUFBRTt3QkFDekMsTUFBTSxjQUFjLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQzt3QkFFM0MsS0FBSyxNQUFNLGFBQWEsSUFBSSxjQUFjLEVBQUU7NEJBQzFDLFdBQVcsQ0FBQyxJQUFJLENBQ2QsY0FBYyxDQUNaLFdBQVcsQ0FBQyxTQUFTLEVBQ3JCLGFBQWEsQ0FBQyxJQUFJLEVBQ2xCLGFBQWEsQ0FBQyxJQUFJLEVBQ2xCLGFBQWEsQ0FBQyxVQUFVLENBQ3pCLENBQ0YsQ0FBQzt5QkFDSDtxQkFDRjt5QkFBTTt3QkFDTCxXQUFXLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO3FCQUM1QztpQkFDRjtnQkFFRCxPQUFPLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN0QyxDQUFDLENBQUMsQ0FDSCxDQUFDO1FBQ0osQ0FBQyxDQUFDO1FBRUY7Ozs7OztXQU1HO1FBQ0gsMEJBQXFCLEdBQUcsR0FBOEIsRUFBRTtZQUN0RCxPQUFPLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNwRCxDQUFDLENBQUM7UUFFRjs7OztXQUlHO1FBQ0gsMkJBQXNCLEdBQUcsR0FBK0IsRUFBRTtZQUN4RCxPQUFPLGFBQWEsQ0FBQyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQ3ZFLEdBQUcsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2hDLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQ2xDLFdBQVc7cUJBQ1IsTUFBTSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRTtvQkFDL0IsT0FBTyxJQUFJLEtBQUssV0FBVyxDQUFDLFNBQVMsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDO2dCQUN4RCxDQUFDLENBQUM7cUJBQ0QsR0FBRyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFO29CQUN0QixPQUFPLFVBQVcsQ0FBQztnQkFDckIsQ0FBQyxDQUFDLENBQ0wsQ0FBQztnQkFFRixPQUFPLFVBQVU7cUJBQ2QsTUFBTSxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFO29CQUN6QixPQUFPLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUMvQyxDQUFDLENBQUM7cUJBQ0QsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFO29CQUN2QyxPQUFPO3dCQUNMLElBQUksRUFBRSxXQUFXLENBQUMsU0FBUzt3QkFDM0IsVUFBVTt3QkFDVixJQUFJO3dCQUNKLElBQUk7d0JBQ0osR0FBRztxQkFDSixDQUFDO2dCQUNKLENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUNKLENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSCxXQUFNLEdBQUcsR0FBNkIsRUFBRTtZQUN0QyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDckMsQ0FBQyxDQUFDO1FBRUYsMEJBQTBCO1FBQzFCLG9CQUFlLEdBQUcsR0FBNEMsRUFBRTtZQUM5RCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDcEQsQ0FBQyxDQUFDO1FBRUYsb0JBQW9CO1FBQ3BCLGNBQVMsR0FBRyxDQUNWLGVBQXVDLEVBQ2hCLEVBQUU7WUFDekIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztRQUN6RCxDQUFDLENBQUM7UUFFRjs7Ozs7O1dBTUc7UUFDSCxrQkFBYSxHQUFHLEdBQUcsRUFBRTs7WUFDbkIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3pCLE1BQUEsSUFBSSxDQUFDLFNBQVMsMENBQUUsYUFBYSxFQUFFLENBQUM7YUFDakM7UUFDSCxDQUFDLENBQUM7UUFFRjs7Ozs7O1dBTUc7UUFDSCxZQUFPLEdBQUcsQ0FBQyxJQUFpQixFQUFFLEVBQUU7WUFDOUIsSUFBSSxJQUFJLEtBQUssV0FBVyxDQUFDLFNBQVMsRUFBRTtnQkFDbEMsK0NBQStDO2dCQUMvQyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFLFFBQVEsQ0FBQyxDQUFDO2FBQ3JEO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxJQUFJLENBQ1YsbUNBQW1DLElBQUksdUNBQXVDLENBQy9FLENBQUM7YUFDSDtRQUNILENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSCxZQUFPLEdBQUcsS0FBSyxFQUFFLEtBQW1CLEVBQUUsV0FBb0IsRUFBRSxVQUFnQyxFQUFFLEVBQUU7O1lBQzlGLElBQUksSUFBaUIsQ0FBQztZQUN0QixJQUFJLFVBQThCLENBQUM7WUFFbkMsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFO2dCQUNYLElBQUksR0FBRyxLQUFLLENBQUM7Z0JBQ2IsVUFBVSxHQUFHLFdBQVcsQ0FBQzthQUMxQjtpQkFBTTtnQkFDTCxNQUFNLFdBQVcsR0FBRyxNQUFNLGNBQWMsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO2dCQUN0RSxNQUFNLFFBQVEsR0FBRyxNQUFBLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLG1DQUFJLGdCQUFnQixDQUFDO2dCQUNuRSxNQUFNLFFBQVEsR0FBRyxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFFN0MsSUFBSSxDQUFDLFFBQVEsRUFBRTtvQkFDYixPQUFPO2lCQUNSO2dCQUVELElBQUksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25CLFVBQVUsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDMUI7WUFFRCxRQUFRLElBQUksRUFBRTtnQkFDWixLQUFLLFdBQVcsQ0FBQyxRQUFRO29CQUN2QixNQUFNLFFBQVEsR0FBa0IsTUFBTSxDQUFDLElBQUksQ0FDekMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FDbkMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUVqRSxNQUFNLDJCQUEyQixHQUMvQixNQUFBLE1BQUEsTUFBQSxJQUFJLENBQUMsT0FBTyxFQUFDLDJCQUEyQixtREFBRyxRQUFRLENBQUMsbUNBQ3BELG1CQUFtQixDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztvQkFFcEMsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLDJCQUEyQixDQUFDO29CQUVoRSxJQUFJLHFCQUFxQixFQUFFO3dCQUN6QixJQUFJLENBQUMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQztxQkFDN0Q7b0JBQ0QsTUFBTTtnQkFDUixLQUFLLFdBQVcsQ0FBQyxhQUFhO29CQUM1QixJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUM7b0JBQ3JFLE1BQU07Z0JBQ1IsS0FBSyxXQUFXLENBQUMsU0FBUztvQkFDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7d0JBQ25CLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztxQkFDdkQ7b0JBRUQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ25DLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQkFDdkIsTUFBTTtnQkFDUjtvQkFDRSxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUM7YUFDM0M7UUFDSCxDQUFDLENBQUM7UUFFRjs7OztXQUlHO1FBQ0gsb0JBQWUsR0FBRyxDQUFDLFdBQW1CLEVBQUUsT0FBb0IsRUFBRSxFQUFFO1lBQzlELElBQUksQ0FBQyxvQkFBb0IsQ0FDdkIsU0FBUyxDQUFDO2dCQUNSLFdBQVc7Z0JBQ1gsT0FBTzthQUNSLENBQUMsQ0FDSCxDQUFDO1FBQ0osQ0FBQyxDQUFDO1FBRUYsNkJBQTZCO1FBQzdCLGVBQVUsR0FBRyxHQUFHLEVBQUU7O1lBQ2hCLE1BQUEsSUFBSSxDQUFDLHFCQUFxQixvREFBSSxDQUFDO1lBQy9CLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLENBQUM7WUFFbEMsTUFBQSxJQUFJLENBQUMsZ0JBQWdCLG9EQUFJLENBQUM7WUFDMUIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUU3QixNQUFBLElBQUksQ0FBQyxvQkFBb0Isb0RBQUksQ0FBQztZQUM5QixJQUFJLENBQUMsb0JBQW9CLEdBQUcsSUFBSSxDQUFDO1lBRWpDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSCxTQUFJLEdBQUcsS0FBSyxFQUNWLEVBQW1CLEVBQ25CLFdBQW9CLEVBQ3BCLFNBQStCLEVBQ1osRUFBRTtZQUNyQixnREFBZ0Q7WUFDaEQsWUFBWTtZQUNaLGdEQUFnRDtZQUNoRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDekIsT0FBTyxJQUFJLE9BQU8sQ0FBVyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtvQkFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7d0JBQ25CLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUM7d0JBQ3JELE9BQU87cUJBQ1I7b0JBRUQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFNBQVMsQ0FBQzt3QkFDbEUsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUU7NEJBQ2pCLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUU7Z0NBQ3BELE9BQU8sQ0FBQztvQ0FDTixHQUFHLEVBQUU7b0NBQ0wsTUFBTSxFQUFFLFFBQVEsQ0FBQyxPQUFPO29DQUN4QixPQUFPLEVBQUUsSUFBSTtpQ0FDZCxDQUFDLENBQUM7Z0NBQ0gsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDOzZCQUM1Qjt3QkFDSCxDQUFDO3dCQUNELEtBQUssRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFOzRCQUNmLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQzs0QkFDdkMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO3dCQUM3QixDQUFDO3FCQUNGLENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQUMsQ0FBQzthQUNKO1lBQ0QsZ0RBQWdEO1lBQ2hELGlCQUFpQjtZQUNqQixnREFBZ0Q7aUJBQzNDLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtnQkFDM0IsT0FBTyxJQUFJLENBQUMsYUFBYTtxQkFDdEIsSUFBSSxDQUFDLEVBQUUsRUFBRSxTQUFTLENBQUM7cUJBQ25CLElBQUksQ0FDSCxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQ1QsQ0FBQztvQkFDQyxHQUFHLEVBQUU7b0JBQ0wsTUFBTTtvQkFDTixPQUFPLEVBQUUsSUFBSTtpQkFDRCxDQUFBLENBQ2pCO3FCQUNBLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO29CQUNmLE1BQU0scUJBQXFCLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN6QyxDQUFDLENBQUMsQ0FBQzthQUNOO2lCQUFNO2dCQUNMLE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELENBQUMsQ0FBQzthQUNyRTtRQUNILENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSCxTQUFJLEdBQUcsS0FBSyxFQUNWLEVBSUMsRUFDRCxXQUFvQixFQUNwQixTQUErQixFQUNWLEVBQUU7WUFDdkIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3pCLE9BQU8sSUFBSSxPQUFPLENBQWEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7b0JBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO3dCQUNuQixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQyxDQUFDO3dCQUN4RCxPQUFPO3FCQUNSO29CQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQyxTQUFTLENBQUM7d0JBQ2xFLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFOzRCQUNqQixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssb0JBQW9CLENBQUMsT0FBTyxFQUFFO2dDQUNwRCxPQUFPLENBQUM7b0NBQ04sR0FBRyxFQUFFO29DQUNMLE1BQU0sRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7b0NBQ3JDLE9BQU8sRUFBRSxJQUFJO2lDQUNkLENBQUMsQ0FBQztnQ0FDSCxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7NkJBQzVCO3dCQUNILENBQUM7d0JBQ0QsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7NEJBQ2YsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDOzRCQUN2QyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7d0JBQzdCLENBQUM7cUJBQ0YsQ0FBQyxDQUFDO2dCQUNMLENBQUMsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxnREFBZ0Q7WUFDaEQsaUJBQWlCO1lBQ2pCLGdEQUFnRDtpQkFDM0MsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUMzQixJQUFJLFNBQVMsSUFBSSxTQUFTLEtBQUssU0FBUyxDQUFDLFVBQVUsRUFBRTtvQkFDbkQsTUFBTSxJQUFJLEtBQUssQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO2lCQUNsRTtnQkFFRCxPQUFPLElBQUksQ0FBQyxhQUFhO3FCQUN0QixJQUFJLENBQUMsRUFBRSxFQUFFLFNBQVMsQ0FBQztxQkFDbkIsSUFBSSxDQUNILENBQUMsTUFBTSxFQUFFLEVBQUU7b0JBQ1QsT0FBTzt3QkFDSCxHQUFHLEVBQUU7d0JBQ0wsTUFBTSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQzt3QkFDbEMsT0FBTyxFQUFFLElBQUk7cUJBQ2hCLENBQUE7Z0JBQ0gsQ0FBQyxDQUNGO3FCQUNBLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO29CQUNmLE1BQU0seUJBQXlCLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM3QyxDQUFDLENBQUMsQ0FBQzthQUNOO2lCQUFNO2dCQUNMLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQzthQUNsRTtRQUNILENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSCxjQUFTLEdBQUcsS0FBSyxFQUNmLEtBQWEsRUFDYixXQUFvQixFQUNwQixTQUErQixFQUNMLEVBQUU7WUFDNUIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ3pCLE9BQU8sSUFBSSxPQUFPLENBQWtCLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO29CQUN0RCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRTt3QkFDbkIsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUMsQ0FBQzt3QkFDeEQsT0FBTztxQkFDUjtvQkFFRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUzt5QkFDaEMsU0FBUyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUM7eUJBQzdCLFNBQVMsQ0FBQzt3QkFDVCxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUUsRUFBRTs0QkFDakIsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLG9CQUFvQixDQUFDLE9BQU8sRUFBRTtnQ0FDcEQsT0FBTyxDQUFDO29DQUNOLE1BQU0sRUFBRTt3Q0FDTixLQUFLLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLO3dDQUM3QixTQUFTLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FDbEQ7d0NBQ0QsVUFBVSxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBVTs0Q0FDckMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7NENBQ2pELENBQUMsQ0FBQyxTQUFTO3FDQUNkO29DQUNELE9BQU8sRUFBRSxJQUFJO2lDQUNkLENBQUMsQ0FBQztnQ0FDSCxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7NkJBQzVCO3dCQUNILENBQUM7d0JBQ0QsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7NEJBQ2YsTUFBTSxDQUFDLDBCQUEwQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDOzRCQUNqRCxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7d0JBQzdCLENBQUM7cUJBQ0YsQ0FBQyxDQUFDO2dCQUNQLENBQUMsQ0FBQyxDQUFDO2FBQ0o7WUFDRCxnREFBZ0Q7WUFDaEQsaUJBQWlCO1lBQ2pCLGdEQUFnRDtpQkFDM0MsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUMzQixJQUFJLFNBQVMsSUFBSSxTQUFTLEtBQUssU0FBUyxDQUFDLFVBQVUsRUFBRTtvQkFDbkQsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO2lCQUN4RTtnQkFFRCxPQUFPLElBQUksQ0FBQyxhQUFhO3FCQUN0QixTQUFTLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQztxQkFDM0IsSUFBSSxDQUNILENBQUMsTUFBTSxFQUFFLEVBQUU7b0JBQ1QsTUFBTSxHQUFHLEdBQUcsSUFBSSxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFBO29CQUNuRSxPQUFPO3dCQUNMLE1BQU0sRUFBRTs0QkFDTixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7NEJBQ25CLFNBQVMsRUFBRSxVQUFVLENBQUMsSUFBSSxDQUN4QixNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQ3hDOzRCQUNELFVBQVUsRUFBRSxHQUFHO2dDQUNiLENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQztnQ0FDekIsQ0FBQyxDQUFDLFNBQVM7eUJBQ2Q7d0JBQ0QsT0FBTyxFQUFFLElBQUk7cUJBQ2QsQ0FBQTtnQkFDSCxDQUFDLENBQ0Y7cUJBQ0EsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7b0JBQ2YsTUFBTSw4QkFBOEIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ3JELENBQUMsQ0FBQyxDQUFDO2FBQ047aUJBQU07Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO2FBQ3hFO1FBQ0gsQ0FBQyxDQUFDO1FBRUY7Ozs7V0FJRztRQUNILGtCQUFhLEdBQUcsS0FBSyxFQUNuQixPQUFlLEVBQ2YsR0FBRyxVQUFvQixFQUNvQixFQUFFO1lBQzdDLElBQUksSUFBSSxDQUFDLHlCQUF5QixDQUFDLFlBQVksQ0FBQyxFQUFFO2dCQUNoRCxPQUFPLElBQUksQ0FBQyxTQUFVLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxHQUFHLFVBQVUsQ0FBQyxDQUFDO2FBQzlEO1lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxxREFBcUQsQ0FBQyxDQUFDO1FBQ3pFLENBQUMsQ0FBQztRQUVGOzs7O1dBSUc7UUFDSCxrQkFBYSxHQUFHLEtBQUssRUFDbkIsT0FBZSxFQUNmLEdBQUcsVUFBb0IsRUFDb0IsRUFBRTtZQUM3QyxJQUFJLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxZQUFZLENBQUMsRUFBRTtnQkFDaEQsT0FBTyxJQUFJLENBQUMsU0FBVSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsR0FBRyxVQUFVLENBQUMsQ0FBQzthQUM5RDtZQUVELE1BQU0sSUFBSSxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztRQUN6RSxDQUFDLENBQUM7UUFFRjs7O1dBR0c7UUFDSCxlQUFVLEdBQUcsQ0FBQyxPQUFrQyxFQUFvQixFQUFFO1lBQ3BFLElBQUksSUFBSSxDQUFDLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUM3QyxPQUFPLElBQUksQ0FBQyxTQUFVLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2FBQzVDO1lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO1FBQ3RFLENBQUMsQ0FBQztRQUVGOzs7V0FHRztRQUNILGVBQVUsR0FBRyxDQUFDLE9BQW9CLEVBQW9CLEVBQUU7WUFDdEQsSUFBSSxJQUFJLENBQUMseUJBQXlCLENBQUMsU0FBUyxDQUFDLEVBQUU7Z0JBQzdDLE9BQU8sSUFBSSxDQUFDLFNBQVUsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDNUM7WUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7UUFDdEUsQ0FBQyxDQUFDO1FBRUYsbUVBQW1FO1FBQ25FLFdBQVc7UUFDWCx3QkFBd0I7UUFDeEIsbUVBQW1FO1FBQzNELDhCQUF5QixHQUFHLENBQUMsT0FBaUMsRUFBRSxFQUFFO1lBQ3hFLElBQUksSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQzNDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBRTlDLE9BQU8sQ0FDTCxNQUFNLENBQUMsSUFBSSxLQUFLLHFCQUFxQixDQUFDLGdCQUFnQjtvQkFDdEQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQ3BDLENBQUM7YUFDSDtRQUNILENBQUMsQ0FBQztRQUVNLGlCQUFZLEdBQUcsQ0FBQyxJQUFrQixFQUFFLEVBQUU7WUFDNUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUVyQyxJQUNFLElBQUksQ0FBQyxNQUFNLEtBQUssWUFBWSxDQUFDLGdCQUFnQjtnQkFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUN6QjtnQkFDQSxJQUFJLEdBQUc7b0JBQ0wsTUFBTSxFQUFFLFlBQVksQ0FBQyxvQkFBb0I7b0JBQ3pDLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztpQkFDdEIsQ0FBQzthQUNIO1lBRUQsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFO2dCQUN6RCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN6QjtRQUNILENBQUMsQ0FBQztRQUVNLHlCQUFvQixHQUFHLENBQUMsY0FBd0MsRUFBRSxFQUFFOztZQUMxRSxNQUFBLElBQUksQ0FBQyxvQkFBb0Isb0RBQUksQ0FBQztZQUM5QixNQUFBLElBQUksQ0FBQyxnQkFBZ0Isb0RBQUksQ0FBQztZQUUxQixJQUNFLElBQUksQ0FBQyxjQUFjLEtBQUssY0FBYztnQkFDdEMsQ0FBQyxDQUFBLE1BQUEsSUFBSSxDQUFDLGNBQWMsMENBQUUsV0FBVyxNQUFLLGNBQWMsQ0FBQyxXQUFXO29CQUM5RCxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sS0FBSyxjQUFjLENBQUMsT0FBTyxDQUFDLEVBQ3pEO2dCQUNBLE9BQU87YUFDUjtZQUVELElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtnQkFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsQ0FBQzthQUNsQztZQUVELElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1lBRXJDLElBQUksQ0FBQyxZQUFZLENBQUM7Z0JBQ2hCLE1BQU0sRUFBRSxZQUFZLENBQUMsZ0JBQWdCO2dCQUNyQyxPQUFPLEVBQUUsY0FBYyxDQUFDLE9BQU87Z0JBQy9CLE9BQU8sRUFBRTtvQkFDUDt3QkFDRSxXQUFXLEVBQUUsV0FBVyxDQUFDLFFBQVE7d0JBQ2pDLFdBQVcsRUFBRSxjQUFjLENBQUMsV0FBVzt3QkFDdkMsTUFBTSxFQUFFLFVBQVU7cUJBQ25CO2lCQUNGO2dCQUNELGVBQWUsRUFBRSxzQkFBc0I7Z0JBQ3ZDLFVBQVUsRUFBRSxXQUFXLENBQUMsUUFBUTthQUNqQyxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMscUJBQXFCLEdBQUcsR0FBRyxFQUFFO2dCQUNoQyxjQUFjLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQzVCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUMzQixJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDO1lBQ3BDLENBQUMsQ0FBQztRQUNKLENBQUMsQ0FBQztRQUVNLG9CQUFlLEdBQUcsR0FBRyxFQUFFOztZQUM3QixNQUFBLElBQUksQ0FBQyxxQkFBcUIsb0RBQUksQ0FBQztZQUMvQixNQUFBLElBQUksQ0FBQyxvQkFBb0Isb0RBQUksQ0FBQztZQUU5QixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQzVDLE9BQU87YUFDUjtZQUVELE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUM7Z0JBQzlELElBQUksRUFBRSxDQUFDLGVBQWUsRUFBRSxFQUFFO29CQUN4QixJQUNFLGVBQWUsQ0FBQyxJQUFJLEtBQUsscUJBQXFCLENBQUMsZ0JBQWdCO3dCQUMvRCxVQUFVLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQ3ZEO3dCQUNBLElBQUksQ0FBQyxZQUFZLENBQUM7NEJBQ2hCLE1BQU0sRUFBRSxZQUFZLENBQUMsZ0JBQWdCOzRCQUNyQyxPQUFPLEVBQUUsZUFBZSxDQUFDLE9BQU87NEJBQ2hDLE9BQU8sRUFBRTtnQ0FDUDtvQ0FDRSxXQUFXLEVBQUUsV0FBVyxDQUFDLFNBQVM7b0NBQ2xDLFdBQVcsRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDLFdBQVc7b0NBQy9DLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU07aUNBQ3RDOzZCQUNGOzRCQUNELGVBQWUsRUFBRSxlQUFlLENBQUMsZUFBZTs0QkFDaEQsVUFBVSxFQUFFLGNBQWMsQ0FDeEIsV0FBVyxDQUFDLFNBQVMsRUFDckIsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQ2xDLGVBQWUsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUNsQyxlQUFlLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FDekM7eUJBQ0YsQ0FBQyxDQUFDO3FCQUNKO3lCQUFNO3dCQUNMLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO3FCQUN2QztnQkFDSCxDQUFDO2FBQ0YsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEdBQUcsRUFBRTs7Z0JBQzNCLE1BQUEsSUFBSSxDQUFDLFNBQVMsMENBQUUsVUFBVSxFQUFFLENBQUM7Z0JBQzdCLHFCQUFxQixDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNwQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1lBQy9CLENBQUMsQ0FBQztRQUNKLENBQUMsQ0FBQztRQUVNLHdCQUFtQixHQUFHLENBQUMsYUFBc0MsRUFBRSxFQUFFOztZQUN2RSxNQUFBLElBQUksQ0FBQyxxQkFBcUIsb0RBQUksQ0FBQztZQUMvQixNQUFBLElBQUksQ0FBQyxnQkFBZ0Isb0RBQUksQ0FBQztZQUUxQixJQUFJLElBQUksQ0FBQyxhQUFhLEtBQUssYUFBYSxFQUFFO2dCQUN4QyxPQUFPO2FBQ1I7WUFFRCxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUU7Z0JBQ3RCLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLENBQUM7YUFDakM7WUFFRCxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztZQUVuQyxNQUFNLHNCQUFzQixHQUFHLENBQzdCLEVBQTJCLEVBQ2IsRUFBRTtnQkFDaEIsT0FBTyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsU0FBUyxDQUFDO29CQUM1QixJQUFJLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRTs7d0JBQ2YsUUFBUSxNQUFNLENBQUMsTUFBTSxFQUFFOzRCQUNyQixLQUFLLDBCQUEwQixDQUFDLFNBQVM7Z0NBQ3ZDLElBQUksQ0FBQyxZQUFZLENBQUM7b0NBQ2hCLE1BQU0sRUFBRSxZQUFZLENBQUMsZ0JBQWdCO29DQUNyQyxPQUFPLEVBQ0wsTUFBQSxJQUFJLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsbUNBQ2xELElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYztvQ0FDN0IsT0FBTyxFQUFFO3dDQUNQOzRDQUNFLFdBQVcsRUFBRSxXQUFXLENBQUMsYUFBYTs0Q0FDdEMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXOzRDQUMvQixNQUFNLEVBQUUsZUFBZTt5Q0FDeEI7cUNBQ0Y7b0NBQ0QsZUFBZSxFQUFFLDhCQUE4QjtvQ0FDL0MsVUFBVSxFQUFFLFdBQVcsQ0FBQyxhQUFhO2lDQUN0QyxDQUFDLENBQUM7Z0NBQ0gsTUFBTTs0QkFDUjtnQ0FDRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztnQ0FDdEMsTUFBTTt5QkFDVDtvQkFDSCxDQUFDO2lCQUNGLENBQUMsQ0FBQztZQUNMLENBQUMsQ0FBQztZQUVGLE1BQU0sZ0NBQWdDLEdBQ3BDLHNCQUFzQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBRXhDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxHQUFHLEVBQUU7O2dCQUMvQixNQUFBLElBQUksQ0FBQyxhQUFhLDBDQUFFLFVBQVUsRUFBRSxDQUFDO2dCQUNqQyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztnQkFDMUIsZ0NBQWdDLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQy9DLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUM7WUFDbkMsQ0FBQyxDQUFDO1FBQ0osQ0FBQyxDQUFDO1FBdndCQSxJQUFJLENBQUMsYUFBYSxHQUFHO1lBQ25CLE1BQU0sRUFBRSxZQUFZLENBQUMsb0JBQW9CO1lBQ3pDLE9BQU8sRUFBRSxPQUFPLENBQUMsY0FBYztTQUNoQyxDQUFDO1FBRUYsSUFBSSxDQUFDLGFBQWEsR0FBRztZQUNuQixNQUFNLEVBQUUsWUFBWSxDQUFDLFlBQVk7WUFDakMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxjQUFjO1NBQ2hDLENBQUM7UUFFRixJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxlQUFlLENBQWdCO1lBQy9ELFdBQVcsQ0FBQyxRQUFRO1lBQ3BCLFdBQVcsQ0FBQyxhQUFhO1NBQzFCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsRUFBRSxDQUFDLENBQUM7UUFFckUsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLGVBQWUsQ0FBZSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFckUsSUFBSSxlQUFlLEdBQVcsQ0FBQyxDQUFDO1FBRWhDLHlEQUF5RDtRQUN6RCxpREFBaUQ7UUFDakQsbUJBQW1CLENBQ2pCLE1BQUEsT0FBTyxDQUFDLGtDQUFrQyxtQ0FDeEMsOENBQThDLEVBQ2hELElBQUksQ0FBQyxrQ0FBa0MsRUFBRSxDQUMxQyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQWMsRUFBRSxFQUFFOztZQUN4QixJQUFJLEtBQUssRUFBRTtnQkFDVCxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDO29CQUMvQixXQUFXLENBQUMsU0FBUztvQkFDckIsV0FBVyxDQUFDLGFBQWE7b0JBQ3pCLFdBQVcsQ0FBQyxRQUFRO2lCQUNyQixDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLGVBQWUsQ0FBQztvQkFDbkMsVUFBVSxFQUFFLE1BQU07b0JBQ2xCLGVBQWUsRUFBRSxPQUFPLENBQUMsZUFBZTtvQkFDeEMsa0RBQWtELEVBQ2hELE1BQUEsT0FBTyxDQUFDLGtEQUFrRCxtQ0FDMUQsaURBQWlEO29CQUNuRCxjQUFjLEVBQUUsT0FBTyxDQUFDLGNBQWM7aUJBQ3ZDLENBQUMsQ0FBQztnQkFFSCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUztxQkFDaEMsTUFBTSxFQUFFO3FCQUNSLElBQUksQ0FDSCxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFJLEtBQUsscUJBQXFCLENBQUMsWUFBWSxDQUFDLENBQ2xFO3FCQUNBLFNBQVMsQ0FBQyxDQUFDLGVBQWUsRUFBRSxFQUFFO29CQUM3QixJQUFJO3dCQUNGLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztxQkFDNUI7b0JBQUMsV0FBTSxHQUFFO29CQUVWLElBQ0UsZUFBZSxDQUFDLElBQUksS0FBSyxxQkFBcUIsQ0FBQyxnQkFBZ0I7d0JBQy9ELENBQUMsSUFBSSxDQUFDLG9CQUFvQjt3QkFDMUIsQ0FBQyxJQUFJLENBQUMscUJBQXFCLEVBQzNCO3dCQUNBLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztxQkFDeEI7eUJBQU0sSUFBSSxlQUFlLEtBQUssQ0FBQyxFQUFFO3dCQUNoQyxlQUFlLElBQUksQ0FBQyxDQUFDO3FCQUN0Qjt5QkFBTTt3QkFDTCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztxQkFDdkM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7YUFDTjtpQkFBTTtnQkFDTCxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsa0NBQWtDLEVBQUUsQ0FBQyxFQUFFO29CQUM5RCxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7aUJBQzNEO2dCQUVELElBQUksZUFBZSxLQUFLLENBQUMsRUFBRTtvQkFDekIsZUFBZSxJQUFJLENBQUMsQ0FBQztpQkFDdEI7cUJBQU07b0JBQ0wsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7aUJBQ3ZDO2FBQ0Y7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILGdEQUFnRDtRQUNoRCxNQUFNLG1CQUFtQixHQUFHLHdCQUF3QixFQUFFLENBQUM7UUFFdkQsSUFBSSxtQkFBbUIsRUFBRTtZQUN2QixJQUFJLENBQUMsb0JBQW9CLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUMvQyxPQUFPO1NBQ1I7UUFFRCw4Q0FBOEM7UUFDOUMsTUFBTSxrQkFBa0IsR0FBRyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU3RCxJQUNFLGtCQUFrQjtZQUNsQixrQkFBa0IsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLE1BQU07Z0JBQzFDLDBCQUEwQixDQUFDLFNBQVMsRUFDdEM7WUFDQSxJQUFJLENBQUMsbUJBQW1CLENBQUMsa0JBQWtCLENBQUMsQ0FBQztTQUM5QzthQUFNLElBQUksZUFBZSxLQUFLLENBQUMsRUFBRTtZQUNoQyxlQUFlLElBQUksQ0FBQyxDQUFDO1NBQ3RCO2FBQU07WUFDTCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztTQUN2QztJQUNILENBQUM7Q0FtcUJGO0FBRUQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsRUFBc0IsQ0FBQztBQUUxRCxTQUFTLGNBQWMsQ0FDckIsV0FBd0IsRUFDeEIsSUFBWSxFQUNaLElBQVksRUFDWixhQUFpQyxFQUFFO0lBRW5DLE1BQU0sR0FBRyxHQUFHLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRTVELElBQUksbUJBQW1CLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ2hDLE9BQU8sbUJBQW1CLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBRSxDQUFDO0tBQ3RDO0lBRUQsTUFBTSxVQUFVLEdBQWU7UUFDN0IsSUFBSSxFQUFFLFdBQVc7UUFDakIsSUFBSTtRQUNKLElBQUk7UUFDSixVQUFVO0tBQ1gsQ0FBQztJQUVGLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFFekMsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFjY0FkZHJlc3MsXG4gIENyZWF0ZVR4T3B0aW9ucyxcbiAgTENEQ2xpZW50LFxuICBQdWJsaWNLZXksXG4gIFNpbXBsZVB1YmxpY0tleSxcbiAgVHgsXG4gIFNpZ25Nb2RlLFxufSBmcm9tICdAeHBsYS94cGxhLmpzJztcbmltcG9ydCB7XG4gIENvbm5lY3RlZFdhbGxldCxcbiAgQ29ubmVjdGlvbixcbiAgQ29ubmVjdFR5cGUsXG4gIEluc3RhbGxhdGlvbixcbiAgTmV0d29ya0luZm8sXG4gIFNpZ25CeXRlc1Jlc3VsdCxcbiAgU2lnblJlc3VsdCxcbiAgVHhSZXN1bHQsXG4gIFdhbGxldEFwcCxcbiAgV2FsbGV0TENEQ2xpZW50Q29uZmlnLFxuICBXYWxsZXRTdGF0ZXMsXG4gIFdhbGxldFN0YXR1cyxcbn0gZnJvbSAnQGtzYW5na3VrMTAvd2FsbGV0LXR5cGVzJztcbmltcG9ydCB7XG4gIFhwbGFXZWJFeHRlbnNpb25GZWF0dXJlcyxcbiAgV2ViRXh0ZW5zaW9uVHhTdGF0dXMsXG59IGZyb20gJ0Brc2FuZ2t1azEwL3dlYi1leHRlbnNpb24taW50ZXJmYWNlJztcbmltcG9ydCBkZWVwRXF1YWwgZnJvbSAnZmFzdC1kZWVwLWVxdWFsJztcbmltcG9ydCB7XG4gIEJlaGF2aW9yU3ViamVjdCxcbiAgY29tYmluZUxhdGVzdCxcbiAgZmlyc3RWYWx1ZUZyb20sXG4gIE9ic2VydmFibGUsXG4gIFN1YnNjcmlwdGlvbixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIENIUk9NRV9FWFRFTlNJT05fSU5TVEFMTF9VUkwsXG4gIERFRkFVTFRfQ0hST01FX0VYVEVOU0lPTl9DT01QQVRJQkxFX0JST1dTRVJfQ0hFQ0ssXG59IGZyb20gJy4vZW52JztcbmltcG9ydCB7XG4gIG1hcEV4dGVuc2lvblNpZ25CeXRlc0Vycm9yLFxuICBtYXBFeHRlbnNpb25UeEVycm9yLFxufSBmcm9tICcuL2V4Y2VwdGlvbi9tYXBFeHRlbnNpb25UeEVycm9yJztcbmltcG9ydCB7IFxuICBtYXBXYWxsZXRDb25uZWN0RXJyb3IsXG4gIG1hcFdhbGxldENvbm5lY3RTaWduRXJyb3IsXG4gIG1hcFdhbGxldENvbm5lY3RTaWduQnl0ZXNFcnJvcixcbn0gZnJvbSAnLi9leGNlcHRpb24vbWFwV2FsbGV0Q29ubmVjdEVycm9yJztcbmltcG9ydCB7IHNlbGVjdENvbm5lY3Rpb24gfSBmcm9tICcuL21vZHVsZXMvY29ubmVjdC1tb2RhbCc7XG5pbXBvcnQge1xuICBFeHRlbnNpb25Sb3V0ZXIsXG4gIEV4dGVuc2lvblJvdXRlclN0YXR1cyxcbn0gZnJvbSAnLi9tb2R1bGVzL2V4dGVuc2lvbi1yb3V0ZXInO1xuaW1wb3J0IHtcbiAgRXh0ZW5zaW9uSW5mbyxcbiAgZ2V0WHBsYUV4dGVuc2lvbnMsXG59IGZyb20gJy4vbW9kdWxlcy9leHRlbnNpb24tcm91dGVyL211bHRpQ2hhbm5lbCc7XG5pbXBvcnQge1xuICBjb25uZWN0IGFzIHJlQ29ubmVjdCxcbiAgY29ubmVjdElmU2Vzc2lvbkV4aXN0cyBhcyByZUNvbm5lY3RJZlNlc3Npb25FeGlzdHMsXG4gIFJlYWRvbmx5V2FsbGV0Q29udHJvbGxlcixcbiAgcmVhZG9ubHlXYWxsZXRNb2RhbCxcbiAgUmVhZG9ubHlXYWxsZXRTZXNzaW9uLFxufSBmcm9tICcuL21vZHVsZXMvcmVhZG9ubHktd2FsbGV0JztcbmltcG9ydCB7XG4gIGNvbm5lY3QgYXMgd2NDb25uZWN0LFxuICBjb25uZWN0SWZTZXNzaW9uRXhpc3RzIGFzIHdjQ29ubmVjdElmU2Vzc2lvbkV4aXN0cyxcbiAgV2FsbGV0Q29ubmVjdENvbnRyb2xsZXIsXG4gIFdhbGxldENvbm5lY3RDb250cm9sbGVyT3B0aW9ucyxcbiAgV2FsbGV0Q29ubmVjdFNlc3Npb25TdGF0dXMsXG59IGZyb20gJy4vbW9kdWxlcy93YWxsZXRjb25uZWN0JztcbmltcG9ydCB7IGdldEV4dGVuc2lvbnMgfSBmcm9tICcuL29wZXJhdG9ycy9nZXRFeHRlbnNpb25zJztcbmltcG9ydCB7IHRvQ29ubmVjdGVkV2FsbGV0IH0gZnJvbSAnLi9vcGVyYXRvcnMvdG9Db25uZWN0ZWRXYWxsZXQnO1xuaW1wb3J0IHsgdG9MY2RDbGllbnQgfSBmcm9tICcuL29wZXJhdG9ycy90b0xjZENsaWVudCc7XG5pbXBvcnQgeyBpc0Rlc2t0b3BDaHJvbWUgfSBmcm9tICcuL3V0aWxzL2Jyb3dzZXItY2hlY2snO1xuaW1wb3J0IHsgY2hlY2tFeHRlbnNpb25SZWFkeSB9IGZyb20gJy4vdXRpbHMvY2hlY2tFeHRlbnNpb25SZWFkeSc7XG5pbXBvcnQgeyBzb3J0Q29ubmVjdGlvbnMgfSBmcm9tICcuL3V0aWxzL3NvcnRDb25uZWN0aW9ucyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2FsbGV0Q29udHJvbGxlck9wdGlvbnNcbiAgZXh0ZW5kcyBXYWxsZXRDb25uZWN0Q29udHJvbGxlck9wdGlvbnMge1xuICAvKipcbiAgICog4pqg77iPIERvbid0IGhhcmRjb2RpbmcgdGhpcywgdXNlIGdldENoYWluIE9wdGlvbnMoKVxuICAgKlxuICAgKiBmYWxsYmFjayBuZXR3b3JrIGlmIGNvbnRyb2xsZXIgaXMgbm90IGNvbm5lY3RlZFxuICAgKi9cbiAgZGVmYXVsdE5ldHdvcms6IE5ldHdvcmtJbmZvO1xuXG4gIC8qKlxuICAgKiDimqDvuI8gRG9uJ3QgaGFyZGNvZGluZyB0aGlzLCB1c2UgZ2V0Q2hhaW4gT3B0aW9ucygpXG4gICAqXG4gICAqIGZvciB3YWxsZXRjb25uZWN0XG4gICAqXG4gICAqIFRoZSBuZXR3b3JrIHJ1bGVzIHBhc3NlZCBieSB0aGUgWHBsYSBNb2JpbGUgYXJlIDAgaXMgdGVzdG5ldCwgMSBpcyBtYWlubmV0LlxuICAgKlxuICAgKiBBbHdheXMgc2V0IHRlc3RuZXQgZm9yIDAgYW5kIG1haW5uZXQgZm9yIDEuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYFxuICAgKiBjb25zdCBtYWlubmV0OiBOZXR3b3JrSW5mbyA9IHtcbiAgICogIG5hbWU6ICdtYWlubmV0JyxcbiAgICogIGNoYWluSUQ6ICdkaW1lbnNpb24tMScsXG4gICAqICBsY2Q6ICdodHRwczovL2xjZC54cGxhLm5ldCcsXG4gICAqIH1cbiAgICpcbiAgICogY29uc3QgdGVzdG5ldDogTmV0d29ya0luZm8gPSB7XG4gICAqICBuYW1lOiAndGVzdG5ldCcsXG4gICAqICBjaGFpbklEOiAnY3ViZS0xJyxcbiAgICogIGxjZDogJ2h0dHBzOi8vbGNkLnhwbGEubmV0JyxcbiAgICogfVxuICAgKlxuICAgKiBjb25zdCB3YWxsZXRDb25uZWN0Q2hhaW5JZHM6IFJlY29yZDxudW1iZXIsIE5ldHdvcmtJbmZvPiA9IHtcbiAgICogICAwOiB0ZXN0bmV0LFxuICAgKiAgIDE6IG1haW5uZXQsXG4gICAqIH1cbiAgICpcbiAgICogPFdhbGxldFByb3ZpZGVyIHdhbGxldENvbm5lY3RDaGFpbklkcz17d2FsbGV0Q29ubmVjdENoYWluSWRzfT5cbiAgICogYGBgXG4gICAqL1xuICB3YWxsZXRDb25uZWN0Q2hhaW5JZHM6IFJlY29yZDxudW1iZXIsIE5ldHdvcmtJbmZvPjtcblxuICAvKipcbiAgICogcnVuIGF0IGV4ZWN1dGluZyB0aGUgYGNvbm5lY3QoQ29ubmVjdFR5cGUuUkVBRE9OTFkpYFxuICAgKi9cbiAgY3JlYXRlUmVhZG9ubHlXYWxsZXRTZXNzaW9uPzogKFxuICAgIG5ldHdvcmtzOiBOZXR3b3JrSW5mb1tdLFxuICApID0+IFByb21pc2U8UmVhZG9ubHlXYWxsZXRTZXNzaW9uIHwgbnVsbD47XG5cbiAgLyoqXG4gICAqIHJ1biBhdCBleGVjdXRpbmcgdGhlIGBjb25uZWN0KClgIC0gb25seSB1c2VkIHdoZW4gZG9lcyBub3QgaW5wdXQgQ29ubmVjdFR5cGVcbiAgICovXG4gIHNlbGVjdENvbm5lY3Rpb24/OiAoXG4gICAgY29ubmVjdGlvbnM6IENvbm5lY3Rpb25bXSxcbiAgKSA9PiBQcm9taXNlPFt0eXBlOiBDb25uZWN0VHlwZSwgaWRlbnRpZmllcjogc3RyaW5nIHwgdW5kZWZpbmVkXSB8IG51bGw+O1xuXG4gIC8qKlxuICAgKiBydW4gYXQgZXhlY3V0aW5nIHRoZSBgY29ubmVjdChDb25uZWN0VHlwZS5FWFRFTlNJT04pYFxuICAgKiBpZiB1c2VyIGluc3RhbGxlZCBtdWx0aXBsZSB3YWxsZXRzXG4gICAqL1xuICBzZWxlY3RFeHRlbnNpb24/OiAoXG4gICAgZXh0ZW5zaW9uSW5mb3M6IEV4dGVuc2lvbkluZm9bXSxcbiAgKSA9PiBQcm9taXNlPEV4dGVuc2lvbkluZm8gfCBudWxsPjtcblxuICAvKipcbiAgICogbWlsbGlzZWNvbmRzIHRvIHdhaXQgY2hlY2tpbmcgY2hyb21lIGV4dGVuc2lvbiBpcyBpbnN0YWxsZWRcbiAgICpcbiAgICogQGRlZmF1bHQgMTAwMCAqIDMgbWlsaXNlY29uZHNcbiAgICovXG4gIHdhaXRpbmdDaHJvbWVFeHRlbnNpb25JbnN0YWxsQ2hlY2s/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIOKaoO+4jyBUaGlzIEFQSSBpcyBhbiBvcHRpb24gZm9yIHdhbGxldCBkZXZlbG9wZXJzLiBQbGVhc2UgZG9uJ3QgdXNlIGRBcHAgZGV2ZWxvcGVycy5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgXG4gICAqIDxXYWxsZXRQcm92aWRlciBkYW5nZXJvdXNseV9fY2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXJDaGVjaz17KHVzZXJBZ2VudDogc3RyaW5nKSA9PiB7XG4gICAqICAgcmV0dXJuIC9NeVdhbGxldFxcLy8udGVzdCh1c2VyQWdlbnQpO1xuICAgKiB9fT5cbiAgICogYGBgXG4gICAqL1xuICBkYW5nZXJvdXNseV9fY2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXJDaGVjaz86IChcbiAgICB1c2VyQWdlbnQ6IHN0cmluZyxcbiAgKSA9PiBib29sZWFuO1xufVxuXG5jb25zdCBDT05ORUNUSU9OUyA9IHtcbiAgW0Nvbm5lY3RUeXBlLlJFQURPTkxZXToge1xuICAgIHR5cGU6IENvbm5lY3RUeXBlLlJFQURPTkxZLFxuICAgIG5hbWU6ICdWaWV3IGFuIGFkZHJlc3MnLFxuICAgIGljb246ICdodHRwczovL2Fzc2V0cy54cGxhLmlvL2ljb24vd2FsbGV0LXByb3ZpZGVyL3JlYWRvbmx5LnN2ZycsXG4gIH0gYXMgQ29ubmVjdGlvbixcbiAgW0Nvbm5lY3RUeXBlLldBTExFVENPTk5FQ1RdOiB7XG4gICAgdHlwZTogQ29ubmVjdFR5cGUuV0FMTEVUQ09OTkVDVCxcbiAgICBuYW1lOiAnV2FsbGV0IENvbm5lY3QnLFxuICAgIGljb246ICdodHRwczovL2Fzc2V0cy54cGxhLmlvL2ljb24vd2FsbGV0LXByb3ZpZGVyL3dhbGxldGNvbm5lY3Quc3ZnJyxcbiAgfSBhcyBDb25uZWN0aW9uLFxufSBhcyBjb25zdDtcblxuY29uc3QgREVGQVVMVF9XQUlUSU5HX0NIUk9NRV9FWFRFTlNJT05fSU5TVEFMTF9DSEVDSyA9IDEwMDAgKiAzO1xuXG5jb25zdCBXQUxMRVRDT05ORUNUX1NVUFBPUlRfRkVBVFVSRVMgPSBuZXcgU2V0PFhwbGFXZWJFeHRlbnNpb25GZWF0dXJlcz4oW1xuICAncG9zdCcsICdzaWduJywgJ3NpZ24tYnl0ZXMnXG5dKTtcblxuY29uc3QgRU1QVFlfU1VQUE9SVF9GRUFUVVJFUyA9IG5ldyBTZXQ8WHBsYVdlYkV4dGVuc2lvbkZlYXR1cmVzPigpO1xuXG4vL25vaW5zcGVjdGlvbiBFUzZNaXNzaW5nQXdhaXRcbmV4cG9ydCBjbGFzcyBXYWxsZXRDb250cm9sbGVyIHtcbiAgcHJpdmF0ZSBleHRlbnNpb246IEV4dGVuc2lvblJvdXRlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHdhbGxldENvbm5lY3Q6IFdhbGxldENvbm5lY3RDb250cm9sbGVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHlXYWxsZXQ6IFJlYWRvbmx5V2FsbGV0Q29udHJvbGxlciB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgX2F2YWlsYWJsZUNvbm5lY3RUeXBlczogQmVoYXZpb3JTdWJqZWN0PENvbm5lY3RUeXBlW10+O1xuICBwcml2YXRlIF9hdmFpbGFibGVJbnN0YWxsVHlwZXM6IEJlaGF2aW9yU3ViamVjdDxDb25uZWN0VHlwZVtdPjtcbiAgcHJpdmF0ZSBfc3RhdGVzOiBCZWhhdmlvclN1YmplY3Q8V2FsbGV0U3RhdGVzPjtcblxuICBwcml2YXRlIGRpc2FibGVSZWFkb25seVdhbGxldDogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZGlzYWJsZUV4dGVuc2lvbjogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZGlzYWJsZVdhbGxldENvbm5lY3Q6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX25vdENvbm5lY3RlZDogV2FsbGV0U3RhdGVzO1xuICBwcml2YXRlIHJlYWRvbmx5IF9pbml0aWFsaXppbmc6IFdhbGxldFN0YXRlcztcblxuICBjb25zdHJ1Y3RvcihyZWFkb25seSBvcHRpb25zOiBXYWxsZXRDb250cm9sbGVyT3B0aW9ucykge1xuICAgIHRoaXMuX25vdENvbm5lY3RlZCA9IHtcbiAgICAgIHN0YXR1czogV2FsbGV0U3RhdHVzLldBTExFVF9OT1RfQ09OTkVDVEVELFxuICAgICAgbmV0d29yazogb3B0aW9ucy5kZWZhdWx0TmV0d29yayxcbiAgICB9O1xuXG4gICAgdGhpcy5faW5pdGlhbGl6aW5nID0ge1xuICAgICAgc3RhdHVzOiBXYWxsZXRTdGF0dXMuSU5JVElBTElaSU5HLFxuICAgICAgbmV0d29yazogb3B0aW9ucy5kZWZhdWx0TmV0d29yayxcbiAgICB9O1xuXG4gICAgdGhpcy5fYXZhaWxhYmxlQ29ubmVjdFR5cGVzID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDb25uZWN0VHlwZVtdPihbXG4gICAgICBDb25uZWN0VHlwZS5SRUFET05MWSxcbiAgICAgIENvbm5lY3RUeXBlLldBTExFVENPTk5FQ1QsXG4gICAgXSk7XG5cbiAgICB0aGlzLl9hdmFpbGFibGVJbnN0YWxsVHlwZXMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENvbm5lY3RUeXBlW10+KFtdKTtcblxuICAgIHRoaXMuX3N0YXRlcyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8V2FsbGV0U3RhdGVzPih0aGlzLl9pbml0aWFsaXppbmcpO1xuXG4gICAgbGV0IG51bVNlc3Npb25DaGVjazogbnVtYmVyID0gMDtcblxuICAgIC8vIHdhaXQgY2hlY2tpbmcgdGhlIGF2YWlsYWJpbGl0eSBvZiB0aGUgY2hyb21lIGV4dGVuc2lvblxuICAgIC8vIDAuIGNoZWNrIGlmIGV4dGVuc2lvbiB3YWxsZXQgc2Vzc2lvbiBpcyBleGlzdHNcbiAgICBjaGVja0V4dGVuc2lvblJlYWR5KFxuICAgICAgb3B0aW9ucy53YWl0aW5nQ2hyb21lRXh0ZW5zaW9uSW5zdGFsbENoZWNrID8/XG4gICAgICAgIERFRkFVTFRfV0FJVElOR19DSFJPTUVfRVhURU5TSU9OX0lOU1RBTExfQ0hFQ0ssXG4gICAgICB0aGlzLmlzQ2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXIoKSxcbiAgICApLnRoZW4oKHJlYWR5OiBib29sZWFuKSA9PiB7XG4gICAgICBpZiAocmVhZHkpIHtcbiAgICAgICAgdGhpcy5fYXZhaWxhYmxlQ29ubmVjdFR5cGVzLm5leHQoW1xuICAgICAgICAgIENvbm5lY3RUeXBlLkVYVEVOU0lPTixcbiAgICAgICAgICBDb25uZWN0VHlwZS5XQUxMRVRDT05ORUNULFxuICAgICAgICAgIENvbm5lY3RUeXBlLlJFQURPTkxZLFxuICAgICAgICBdKTtcblxuICAgICAgICB0aGlzLmV4dGVuc2lvbiA9IG5ldyBFeHRlbnNpb25Sb3V0ZXIoe1xuICAgICAgICAgIGhvc3RXaW5kb3c6IHdpbmRvdyxcbiAgICAgICAgICBzZWxlY3RFeHRlbnNpb246IG9wdGlvbnMuc2VsZWN0RXh0ZW5zaW9uLFxuICAgICAgICAgIGRhbmdlcm91c2x5X19jaHJvbWVFeHRlbnNpb25Db21wYXRpYmxlQnJvd3NlckNoZWNrOlxuICAgICAgICAgICAgb3B0aW9ucy5kYW5nZXJvdXNseV9fY2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXJDaGVjayA/P1xuICAgICAgICAgICAgREVGQVVMVF9DSFJPTUVfRVhURU5TSU9OX0NPTVBBVElCTEVfQlJPV1NFUl9DSEVDSyxcbiAgICAgICAgICBkZWZhdWx0TmV0d29yazogb3B0aW9ucy5kZWZhdWx0TmV0d29yayxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdGhpcy5leHRlbnNpb25cbiAgICAgICAgICAuc3RhdGVzKClcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIGZpbHRlcigoeyB0eXBlIH0pID0+IHR5cGUgIT09IEV4dGVuc2lvblJvdXRlclN0YXR1cy5JTklUSUFMSVpJTkcpLFxuICAgICAgICAgIClcbiAgICAgICAgICAuc3Vic2NyaWJlKChleHRlbnNpb25TdGF0ZXMpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgfSBjYXRjaCB7fVxuXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIGV4dGVuc2lvblN0YXRlcy50eXBlID09PSBFeHRlbnNpb25Sb3V0ZXJTdGF0dXMuV0FMTEVUX0NPTk5FQ1RFRCAmJlxuICAgICAgICAgICAgICAhdGhpcy5kaXNhYmxlV2FsbGV0Q29ubmVjdCAmJlxuICAgICAgICAgICAgICAhdGhpcy5kaXNhYmxlUmVhZG9ubHlXYWxsZXRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICB0aGlzLmVuYWJsZUV4dGVuc2lvbigpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1TZXNzaW9uQ2hlY2sgPT09IDApIHtcbiAgICAgICAgICAgICAgbnVtU2Vzc2lvbkNoZWNrICs9IDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlcyh0aGlzLl9ub3RDb25uZWN0ZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGlzRGVza3RvcENocm9tZSh0aGlzLmlzQ2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXIoKSkpIHtcbiAgICAgICAgICB0aGlzLl9hdmFpbGFibGVJbnN0YWxsVHlwZXMubmV4dChbQ29ubmVjdFR5cGUuRVhURU5TSU9OXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobnVtU2Vzc2lvbkNoZWNrID09PSAwKSB7XG4gICAgICAgICAgbnVtU2Vzc2lvbkNoZWNrICs9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVTdGF0ZXModGhpcy5fbm90Q29ubmVjdGVkKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gMS4gY2hlY2sgaWYgcmVhZG9ubHkgd2FsbGV0IHNlc3Npb24gaXMgZXhpc3RzXG4gICAgY29uc3QgZHJhZnRSZWFkb25seVdhbGxldCA9IHJlQ29ubmVjdElmU2Vzc2lvbkV4aXN0cygpO1xuXG4gICAgaWYgKGRyYWZ0UmVhZG9ubHlXYWxsZXQpIHtcbiAgICAgIHRoaXMuZW5hYmxlUmVhZG9ubHlXYWxsZXQoZHJhZnRSZWFkb25seVdhbGxldCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gMi4gY2hlY2sgaWYgd2FsbGV0Y29ubmVjdCBzZXNpc29uIGlzIGV4aXN0c1xuICAgIGNvbnN0IGRyYWZ0V2FsbGV0Q29ubmVjdCA9IHdjQ29ubmVjdElmU2Vzc2lvbkV4aXN0cyhvcHRpb25zKTtcblxuICAgIGlmIChcbiAgICAgIGRyYWZ0V2FsbGV0Q29ubmVjdCAmJlxuICAgICAgZHJhZnRXYWxsZXRDb25uZWN0LmdldExhdGVzdFNlc3Npb24oKS5zdGF0dXMgPT09XG4gICAgICAgIFdhbGxldENvbm5lY3RTZXNzaW9uU3RhdHVzLkNPTk5FQ1RFRFxuICAgICkge1xuICAgICAgdGhpcy5lbmFibGVXYWxsZXRDb25uZWN0KGRyYWZ0V2FsbGV0Q29ubmVjdCk7XG4gICAgfSBlbHNlIGlmIChudW1TZXNzaW9uQ2hlY2sgPT09IDApIHtcbiAgICAgIG51bVNlc3Npb25DaGVjayArPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVwZGF0ZVN0YXRlcyh0aGlzLl9ub3RDb25uZWN0ZWQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTb21lIG1vYmlsZSB3YWxsZXQgZW11bGF0ZXMgdGhlIGJlaGF2aW9yIG9mIGNocm9tZSBleHRlbnNpb24uXG4gICAqIEl0IGNvbmZpcm1zIHRoYXQgdGhlIGN1cnJlbnQgY29ubmVjdGlvbiBlbnZpcm9ubWVudCBpcyBzdWNoIGEgd2FsbGV0LlxuICAgKiAoSWYgeW91IGFyZSBydW5uaW5nIGNvbm5lY3QoKSBieSBjaGVja2luZyBhdmFpbGFibGVDb25uZWN0VHlwZSwgeW91IGRvIG5vdCBuZWVkIHRvIHVzZSB0aGlzIEFQSS4pXG4gICAqXG4gICAqIEBzZWUgV2FsbGV0I2lzQ2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXJcbiAgICovXG4gIGlzQ2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXIgPSAoKTogYm9vbGVhbiA9PiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMub3B0aW9ucy5kYW5nZXJvdXNseV9fY2hyb21lRXh0ZW5zaW9uQ29tcGF0aWJsZUJyb3dzZXJDaGVjayA/P1xuICAgICAgREVGQVVMVF9DSFJPTUVfRVhURU5TSU9OX0NPTVBBVElCTEVfQlJPV1NFUl9DSEVDS1xuICAgICkobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIGF2YWlsYWJsZSBjb25uZWN0IHR5cGVzIG9uIHRoZSBicm93c2VyXG4gICAqXG4gICAqIEBzZWUgV2FsbGV0I2F2YWlsYWJsZUNvbm5lY3RUeXBlc1xuICAgKi9cbiAgYXZhaWxhYmxlQ29ubmVjdFR5cGVzID0gKCk6IE9ic2VydmFibGU8Q29ubmVjdFR5cGVbXT4gPT4ge1xuICAgIHJldHVybiB0aGlzLl9hdmFpbGFibGVDb25uZWN0VHlwZXMuYXNPYnNlcnZhYmxlKCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIGF2YWlsYWJsZSBjb25uZWN0aW9ucyBpbmNsdWRlcyBpZGVudGlmaWVyLCBuYW1lLCBpY29uXG4gICAqXG4gICAqIEBzZWUgV2FsbGV0I2F2YWlsYWJsZUNvbm5lY3Rpb25zXG4gICAqL1xuICBhdmFpbGFibGVDb25uZWN0aW9ucyA9ICgpOiBPYnNlcnZhYmxlPENvbm5lY3Rpb25bXT4gPT4ge1xuICAgIHJldHVybiB0aGlzLl9hdmFpbGFibGVDb25uZWN0VHlwZXMucGlwZShcbiAgICAgIG1hcCgoY29ubmVjdFR5cGVzKSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25zOiBDb25uZWN0aW9uW10gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3RUeXBlIG9mIGNvbm5lY3RUeXBlcykge1xuICAgICAgICAgIGlmIChjb25uZWN0VHlwZSA9PT0gQ29ubmVjdFR5cGUuRVhURU5TSU9OKSB7XG4gICAgICAgICAgICBjb25zdCB4cGxhRXh0ZW5zaW9ucyA9IGdldFhwbGFFeHRlbnNpb25zKCk7XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgeHBsYUV4dGVuc2lvbiBvZiB4cGxhRXh0ZW5zaW9ucykge1xuICAgICAgICAgICAgICBjb25uZWN0aW9ucy5wdXNoKFxuICAgICAgICAgICAgICAgIG1lbW9Db25uZWN0aW9uKFxuICAgICAgICAgICAgICAgICAgQ29ubmVjdFR5cGUuRVhURU5TSU9OLFxuICAgICAgICAgICAgICAgICAgeHBsYUV4dGVuc2lvbi5uYW1lLFxuICAgICAgICAgICAgICAgICAgeHBsYUV4dGVuc2lvbi5pY29uLFxuICAgICAgICAgICAgICAgICAgeHBsYUV4dGVuc2lvbi5pZGVudGlmaWVyLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbm5lY3Rpb25zLnB1c2goQ09OTkVDVElPTlNbY29ubmVjdFR5cGVdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc29ydENvbm5lY3Rpb25zKGNvbm5lY3Rpb25zKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIGF2YWlsYWJsZSBpbnN0YWxsIHR5cGVzIG9uIHRoZSBicm93c2VyXG4gICAqXG4gICAqIGluIHRoaXMgdGltZSwgdGhpcyBvbmx5IGNvbnRhaW5zIFtDb25uZWN0VHlwZS5FWFRFTlNJT05dXG4gICAqXG4gICAqIEBzZWUgV2FsbGV0I2F2YWlsYWJsZUluc3RhbGxUeXBlc1xuICAgKi9cbiAgYXZhaWxhYmxlSW5zdGFsbFR5cGVzID0gKCk6IE9ic2VydmFibGU8Q29ubmVjdFR5cGVbXT4gPT4ge1xuICAgIHJldHVybiB0aGlzLl9hdmFpbGFibGVJbnN0YWxsVHlwZXMuYXNPYnNlcnZhYmxlKCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIGF2YWlsYWJsZSBpbnN0YWxsYXRpb25zIGluY2x1ZGVzIGlkZW50aWZpZXIsIG5hbWUsIGljb24sIHVybFxuICAgKlxuICAgKiBAc2VlIFdhbGxldCNhdmFpbGFibGVJbnN0YWxsYXRpb25zXG4gICAqL1xuICBhdmFpbGFibGVJbnN0YWxsYXRpb25zID0gKCk6IE9ic2VydmFibGU8SW5zdGFsbGF0aW9uW10+ID0+IHtcbiAgICByZXR1cm4gY29tYmluZUxhdGVzdChbdGhpcy5hdmFpbGFibGVDb25uZWN0aW9ucygpLCBnZXRFeHRlbnNpb25zKCldKS5waXBlKFxuICAgICAgbWFwKChbY29ubmVjdGlvbnMsIGV4dGVuc2lvbnNdKSA9PiB7XG4gICAgICAgIGNvbnN0IGluc3RhbGxlZElkZW50aWZpZXJzID0gbmV3IFNldDxzdHJpbmc+KFxuICAgICAgICAgIGNvbm5lY3Rpb25zXG4gICAgICAgICAgICAuZmlsdGVyKCh7IHR5cGUsIGlkZW50aWZpZXIgfSkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gdHlwZSA9PT0gQ29ubmVjdFR5cGUuRVhURU5TSU9OICYmICEhaWRlbnRpZmllcjtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAubWFwKCh7IGlkZW50aWZpZXIgfSkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gaWRlbnRpZmllciE7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gZXh0ZW5zaW9uc1xuICAgICAgICAgIC5maWx0ZXIoKHsgaWRlbnRpZmllciB9KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gIWluc3RhbGxlZElkZW50aWZpZXJzLmhhcyhpZGVudGlmaWVyKTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5tYXAoKHsgbmFtZSwgaWRlbnRpZmllciwgaWNvbiwgdXJsIH0pID0+IHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHR5cGU6IENvbm5lY3RUeXBlLkVYVEVOU0lPTixcbiAgICAgICAgICAgICAgaWRlbnRpZmllcixcbiAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgaWNvbixcbiAgICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBzZWUgV2FsbGV0I3N0YXR1c1xuICAgKiBAc2VlIFdhbGxldCNuZXR3b3JrXG4gICAqIEBzZWUgV2FsbGV0I3dhbGxldHNcbiAgICovXG4gIHN0YXRlcyA9ICgpOiBPYnNlcnZhYmxlPFdhbGxldFN0YXRlcz4gPT4ge1xuICAgIHJldHVybiB0aGlzLl9zdGF0ZXMuYXNPYnNlcnZhYmxlKCk7XG4gIH07XG5cbiAgLyoqIGdldCBjb25uZWN0ZWRXYWxsZXQgKi9cbiAgY29ubmVjdGVkV2FsbGV0ID0gKCk6IE9ic2VydmFibGU8Q29ubmVjdGVkV2FsbGV0IHwgdW5kZWZpbmVkPiA9PiB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRlcy5waXBlKHRvQ29ubmVjdGVkV2FsbGV0KHRoaXMpKTtcbiAgfTtcblxuICAvKiogZ2V0IGxjZENsaWVudCAqL1xuICBsY2RDbGllbnQgPSAoXG4gICAgbGNkQ2xpZW50Q29uZmlnPzogV2FsbGV0TENEQ2xpZW50Q29uZmlnLFxuICApOiBPYnNlcnZhYmxlPExDRENsaWVudD4gPT4ge1xuICAgIHJldHVybiB0aGlzLl9zdGF0ZXMucGlwZSh0b0xjZENsaWVudChsY2RDbGllbnRDb25maWcpKTtcbiAgfTtcblxuICAvKipcbiAgICogcmVsb2FkIHRoZSBjb25uZWN0ZWQgd2FsbGV0IHN0YXRlc1xuICAgKlxuICAgKiBpbiB0aGlzIHRpbWUsIHRoaXMgb25seSB3b3JrIG9uIHRoZSBDb25uZWN0VHlwZS5FWFRFTlNJT05cbiAgICpcbiAgICogQHNlZSBXYWxsZXQjcmVjaGVja1N0YXR1c1xuICAgKi9cbiAgcmVmZXRjaFN0YXRlcyA9ICgpID0+IHtcbiAgICBpZiAodGhpcy5kaXNhYmxlRXh0ZW5zaW9uKSB7XG4gICAgICB0aGlzLmV4dGVuc2lvbj8ucmVmZXRjaFN0YXRlcygpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBhdmFpbGFibGVJbnN0YWxsYXRpb25zXG4gICAqXG4gICAqIGluc3RhbGwgZm9yIHRoZSBjb25uZWN0IHR5cGVcbiAgICpcbiAgICogQHNlZSBXYWxsZXQjaW5zdGFsbFxuICAgKi9cbiAgaW5zdGFsbCA9ICh0eXBlOiBDb25uZWN0VHlwZSkgPT4ge1xuICAgIGlmICh0eXBlID09PSBDb25uZWN0VHlwZS5FWFRFTlNJT04pIHtcbiAgICAgIC8vIFRPRE8gc2VwYXJhdGUgaW5zdGFsbCBsaW5rcyBieSBicm93c2VyIHR5cGVzXG4gICAgICB3aW5kb3cub3BlbihDSFJPTUVfRVhURU5TSU9OX0lOU1RBTExfVVJMLCAnX2JsYW5rJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtXYWxsZXRDb250cm9sbGVyXSBDb25uZWN0VHlwZSBcIiR7dHlwZX1cIiBkb2VzIG5vdCBzdXBwb3J0IGluc3RhbGwoKSBmdW5jdGlvbmAsXG4gICAgICApO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogY29ubmVjdCB0byB3YWxsZXRcbiAgICpcbiAgICogQHNlZSBXYWxsZXQjY29ubmVjdFxuICAgKi9cbiAgY29ubmVjdCA9IGFzeW5jIChfdHlwZT86IENvbm5lY3RUeXBlLCBfaWRlbnRpZmllcj86IHN0cmluZywgX3dhbGxldEFwcD86IFdhbGxldEFwcCB8IGJvb2xlYW4pID0+IHtcbiAgICBsZXQgdHlwZTogQ29ubmVjdFR5cGU7XG4gICAgbGV0IGlkZW50aWZpZXI6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGlmICghIV90eXBlKSB7XG4gICAgICB0eXBlID0gX3R5cGU7XG4gICAgICBpZGVudGlmaWVyID0gX2lkZW50aWZpZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGNvbm5lY3Rpb25zID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy5hdmFpbGFibGVDb25uZWN0aW9ucygpKTtcbiAgICAgIGNvbnN0IHNlbGVjdG9yID0gdGhpcy5vcHRpb25zLnNlbGVjdENvbm5lY3Rpb24gPz8gc2VsZWN0Q29ubmVjdGlvbjtcbiAgICAgIGNvbnN0IHNlbGVjdGVkID0gYXdhaXQgc2VsZWN0b3IoY29ubmVjdGlvbnMpO1xuXG4gICAgICBpZiAoIXNlbGVjdGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdHlwZSA9IHNlbGVjdGVkWzBdO1xuICAgICAgaWRlbnRpZmllciA9IHNlbGVjdGVkWzFdO1xuICAgIH1cblxuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBDb25uZWN0VHlwZS5SRUFET05MWTpcbiAgICAgICAgY29uc3QgbmV0d29ya3M6IE5ldHdvcmtJbmZvW10gPSBPYmplY3Qua2V5cyhcbiAgICAgICAgICB0aGlzLm9wdGlvbnMud2FsbGV0Q29ubmVjdENoYWluSWRzLFxuICAgICAgICApLm1hcCgoY2hhaW5JZCkgPT4gdGhpcy5vcHRpb25zLndhbGxldENvbm5lY3RDaGFpbklkc1srY2hhaW5JZF0pO1xuXG4gICAgICAgIGNvbnN0IGNyZWF0ZVJlYWRvbmx5V2FsbGV0U2Vzc2lvbiA9XG4gICAgICAgICAgdGhpcy5vcHRpb25zLmNyZWF0ZVJlYWRvbmx5V2FsbGV0U2Vzc2lvbj8uKG5ldHdvcmtzKSA/P1xuICAgICAgICAgIHJlYWRvbmx5V2FsbGV0TW9kYWwoeyBuZXR3b3JrcyB9KTtcblxuICAgICAgICBjb25zdCByZWFkb25seVdhbGxldFNlc3Npb24gPSBhd2FpdCBjcmVhdGVSZWFkb25seVdhbGxldFNlc3Npb247XG5cbiAgICAgICAgaWYgKHJlYWRvbmx5V2FsbGV0U2Vzc2lvbikge1xuICAgICAgICAgIHRoaXMuZW5hYmxlUmVhZG9ubHlXYWxsZXQocmVDb25uZWN0KHJlYWRvbmx5V2FsbGV0U2Vzc2lvbikpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb25uZWN0VHlwZS5XQUxMRVRDT05ORUNUOlxuICAgICAgICB0aGlzLmVuYWJsZVdhbGxldENvbm5lY3Qod2NDb25uZWN0KHRoaXMub3B0aW9ucywgZmFsc2UsIF93YWxsZXRBcHApKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbm5lY3RUeXBlLkVYVEVOU0lPTjpcbiAgICAgICAgaWYgKCF0aGlzLmV4dGVuc2lvbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZXh0ZW5zaW9uIGluc3RhbmNlIGlzIG5vdCBjcmVhdGVkIWApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5leHRlbnNpb24uY29ubmVjdChpZGVudGlmaWVyKTtcbiAgICAgICAgdGhpcy5lbmFibGVFeHRlbnNpb24oKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gQ29ubmVjdFR5cGUhYCk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBtYW51YWwgY29ubmVjdCB0byByZWFkIG9ubHkgc2Vzc2lvblxuICAgKlxuICAgKiBAc2VlIFdhbGxldCNjb25uZWN0UmVhZG9ubHlcbiAgICovXG4gIGNvbm5lY3RSZWFkb25seSA9ICh4cGxhQWRkcmVzczogc3RyaW5nLCBuZXR3b3JrOiBOZXR3b3JrSW5mbykgPT4ge1xuICAgIHRoaXMuZW5hYmxlUmVhZG9ubHlXYWxsZXQoXG4gICAgICByZUNvbm5lY3Qoe1xuICAgICAgICB4cGxhQWRkcmVzcyxcbiAgICAgICAgbmV0d29yayxcbiAgICAgIH0pLFxuICAgICk7XG4gIH07XG5cbiAgLyoqIEBzZWUgV2FsbGV0I2Rpc2Nvbm5lY3QgKi9cbiAgZGlzY29ubmVjdCA9ICgpID0+IHtcbiAgICB0aGlzLmRpc2FibGVSZWFkb25seVdhbGxldD8uKCk7XG4gICAgdGhpcy5kaXNhYmxlUmVhZG9ubHlXYWxsZXQgPSBudWxsO1xuXG4gICAgdGhpcy5kaXNhYmxlRXh0ZW5zaW9uPy4oKTtcbiAgICB0aGlzLmRpc2FibGVFeHRlbnNpb24gPSBudWxsO1xuXG4gICAgdGhpcy5kaXNhYmxlV2FsbGV0Q29ubmVjdD8uKCk7XG4gICAgdGhpcy5kaXNhYmxlV2FsbGV0Q29ubmVjdCA9IG51bGw7XG5cbiAgICB0aGlzLnVwZGF0ZVN0YXRlcyh0aGlzLl9ub3RDb25uZWN0ZWQpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBAc2VlIFdhbGxldCNwb3N0XG4gICAqIEBwYXJhbSB0eFxuICAgKiBAcGFyYW0geHBsYUFkZHJlc3Mgb25seSBhdmFpbGFibGUgbmV3IGV4dGVuc2lvblxuICAgKi9cbiAgcG9zdCA9IGFzeW5jIChcbiAgICB0eDogQ3JlYXRlVHhPcHRpb25zLFxuICAgIHhwbGFBZGRyZXNzPzogc3RyaW5nLFxuICAgIHdhbGxldEFwcD86IFdhbGxldEFwcCB8IGJvb2xlYW4sXG4gICk6IFByb21pc2U8VHhSZXN1bHQ+ID0+IHtcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBleHRlbnNpb25cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBpZiAodGhpcy5kaXNhYmxlRXh0ZW5zaW9uKSB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2U8VHhSZXN1bHQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmV4dGVuc2lvbikge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYGV4dGVuc2lvbiBpbnN0YW5jZSBub3QgY3JlYXRlZCFgKSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdGhpcy5leHRlbnNpb24ucG9zdCh0eCwgeHBsYUFkZHJlc3MpLnN1YnNjcmliZSh7XG4gICAgICAgICAgbmV4dDogKHR4UmVzdWx0KSA9PiB7XG4gICAgICAgICAgICBpZiAodHhSZXN1bHQuc3RhdHVzID09PSBXZWJFeHRlbnNpb25UeFN0YXR1cy5TVUNDRUVEKSB7XG4gICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgIC4uLnR4LFxuICAgICAgICAgICAgICAgIHJlc3VsdDogdHhSZXN1bHQucGF5bG9hZCxcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSxcbiAgICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgICByZWplY3QobWFwRXh0ZW5zaW9uVHhFcnJvcih0eCwgZXJyb3IpKTtcbiAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIHdhbGxldCBjb25uZWN0XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgZWxzZSBpZiAodGhpcy53YWxsZXRDb25uZWN0KSB7XG4gICAgICByZXR1cm4gdGhpcy53YWxsZXRDb25uZWN0XG4gICAgICAgIC5wb3N0KHR4LCB3YWxsZXRBcHApXG4gICAgICAgIC50aGVuKFxuICAgICAgICAgIChyZXN1bHQpID0+XG4gICAgICAgICAgICAoe1xuICAgICAgICAgICAgICAuLi50eCxcbiAgICAgICAgICAgICAgcmVzdWx0LFxuICAgICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgfSBhcyBUeFJlc3VsdCksXG4gICAgICAgIClcbiAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgIHRocm93IG1hcFdhbGxldENvbm5lY3RFcnJvcih0eCwgZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGVyZSBhcmUgbm8gY29ubmVjdGlvbnMgdGhhdCBjYW4gYmUgcG9zdGluZyB0eCFgKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBzZWUgV2FsbGV0I3NpZ25cbiAgICogQHBhcmFtIHR4XG4gICAqIEBwYXJhbSB4cGxhQWRkcmVzcyBvbmx5IGF2YWlsYWJsZSBuZXcgZXh0ZW5zaW9uXG4gICAqL1xuICBzaWduID0gYXN5bmMgKFxuICAgIHR4OiBDcmVhdGVUeE9wdGlvbnMgJiB7XG4gICAgICBzZXF1ZW5jZT86IG51bWJlcjtcbiAgICAgIGFjY291bnROdW1iZXI/OiBudW1iZXI7XG4gICAgICBzaWduTW9kZT86IFNpZ25Nb2RlO1xuICAgIH0sXG4gICAgeHBsYUFkZHJlc3M/OiBzdHJpbmcsXG4gICAgd2FsbGV0QXBwPzogV2FsbGV0QXBwIHwgYm9vbGVhbixcbiAgKTogUHJvbWlzZTxTaWduUmVzdWx0PiA9PiB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZUV4dGVuc2lvbikge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPFNpZ25SZXN1bHQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmV4dGVuc2lvbikge1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYGV4dGVuc2lvbiBpbnN0YW5jZSBpcyBub3QgY3JlYXRlZCFgKSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdGhpcy5leHRlbnNpb24uc2lnbih0eCwgeHBsYUFkZHJlc3MpLnN1YnNjcmliZSh7XG4gICAgICAgICAgbmV4dDogKHR4UmVzdWx0KSA9PiB7XG4gICAgICAgICAgICBpZiAodHhSZXN1bHQuc3RhdHVzID09PSBXZWJFeHRlbnNpb25UeFN0YXR1cy5TVUNDRUVEKSB7XG4gICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgIC4uLnR4LFxuICAgICAgICAgICAgICAgIHJlc3VsdDogVHguZnJvbURhdGEodHhSZXN1bHQucGF5bG9hZCksXG4gICAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgZXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KG1hcEV4dGVuc2lvblR4RXJyb3IodHgsIGVycm9yKSk7XG4gICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyB3YWxsZXQgY29ubmVjdFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGVsc2UgaWYgKHRoaXMud2FsbGV0Q29ubmVjdCkge1xuICAgICAgaWYgKHdhbGxldEFwcCAmJiB3YWxsZXRBcHAgPT09IFdhbGxldEFwcC5YUExBX0dBTUVTKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlcmUgYXJlIG5vIGNvbm5lY3Rpb25zIHRoYXQgY2FuIGJlIHNpZ25pbmchYCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLndhbGxldENvbm5lY3RcbiAgICAgICAgLnNpZ24odHgsIHdhbGxldEFwcClcbiAgICAgICAgLnRoZW4oXG4gICAgICAgICAgKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAuLi50eCxcbiAgICAgICAgICAgICAgICByZXN1bHQ6IFR4LmZyb21EYXRhKHJlc3VsdCwgZmFsc2UpLFxuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICB0aHJvdyBtYXBXYWxsZXRDb25uZWN0U2lnbkVycm9yKHR4LCBlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGFyZSBubyBjb25uZWN0aW9ucyB0aGF0IGNhbiBiZSBzaWduaW5nIWApO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQHNlZSBXYWxsZXQjc2lnbkJ5dGVzXG4gICAqIEBwYXJhbSBieXRlc1xuICAgKiBAcGFyYW0geHBsYUFkZHJlc3Mgb25seSBhdmFpbGFibGUgbmV3IGV4dGVuc2lvblxuICAgKi9cbiAgc2lnbkJ5dGVzID0gYXN5bmMgKFxuICAgIGJ5dGVzOiBCdWZmZXIsXG4gICAgeHBsYUFkZHJlc3M/OiBzdHJpbmcsXG4gICAgd2FsbGV0QXBwPzogV2FsbGV0QXBwIHwgYm9vbGVhbixcbiAgKTogUHJvbWlzZTxTaWduQnl0ZXNSZXN1bHQ+ID0+IHtcbiAgICBpZiAodGhpcy5kaXNhYmxlRXh0ZW5zaW9uKSB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2U8U2lnbkJ5dGVzUmVzdWx0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5leHRlbnNpb24pIHtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBleHRlbnNpb24gaW5zdGFuY2UgaXMgbm90IGNyZWF0ZWQhYCkpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IHRoaXMuZXh0ZW5zaW9uXG4gICAgICAgICAgLnNpZ25CeXRlcyhieXRlcywgeHBsYUFkZHJlc3MpXG4gICAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgICBuZXh0OiAodHhSZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHR4UmVzdWx0LnN0YXR1cyA9PT0gV2ViRXh0ZW5zaW9uVHhTdGF0dXMuU1VDQ0VFRCkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgcmVzdWx0OiB7XG4gICAgICAgICAgICAgICAgICAgIHJlY2lkOiB0eFJlc3VsdC5wYXlsb2FkLnJlY2lkLFxuICAgICAgICAgICAgICAgICAgICBzaWduYXR1cmU6IFVpbnQ4QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICAgICAgICBCdWZmZXIuZnJvbSh0eFJlc3VsdC5wYXlsb2FkLnNpZ25hdHVyZSwgJ2Jhc2U2NCcpLFxuICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICBwdWJsaWNfa2V5OiB0eFJlc3VsdC5wYXlsb2FkLnB1YmxpY19rZXlcbiAgICAgICAgICAgICAgICAgICAgICA/IFB1YmxpY0tleS5mcm9tRGF0YSh0eFJlc3VsdC5wYXlsb2FkLnB1YmxpY19rZXkpXG4gICAgICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgcmVqZWN0KG1hcEV4dGVuc2lvblNpZ25CeXRlc0Vycm9yKGJ5dGVzLCBlcnJvcikpO1xuICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gd2FsbGV0IGNvbm5lY3RcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBlbHNlIGlmICh0aGlzLndhbGxldENvbm5lY3QpIHtcbiAgICAgIGlmICh3YWxsZXRBcHAgJiYgd2FsbGV0QXBwID09PSBXYWxsZXRBcHAuWFBMQV9HQU1FUykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGFyZSBubyBjb25uZWN0aW9ucyB0aGF0IGNhbiBiZSBzaWduaW5nIGJ5dGVzIWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy53YWxsZXRDb25uZWN0XG4gICAgICAgIC5zaWduQnl0ZXMoYnl0ZXMsIHdhbGxldEFwcClcbiAgICAgICAgLnRoZW4oXG4gICAgICAgICAgKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qga2V5ID0gbmV3IFNpbXBsZVB1YmxpY0tleShTdHJpbmcocmVzdWx0LnB1YmxpY19rZXkpKS50b0RhdGEoKVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgcmVzdWx0OiB7XG4gICAgICAgICAgICAgICAgcmVjaWQ6IHJlc3VsdC5yZWNpZCxcbiAgICAgICAgICAgICAgICBzaWduYXR1cmU6IFVpbnQ4QXJyYXkuZnJvbShcbiAgICAgICAgICAgICAgICAgIEJ1ZmZlci5mcm9tKHJlc3VsdC5zaWduYXR1cmUsICdiYXNlNjQnKSxcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIHB1YmxpY19rZXk6IGtleVxuICAgICAgICAgICAgICAgICAgPyBQdWJsaWNLZXkuZnJvbURhdGEoa2V5KVxuICAgICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICB0aHJvdyBtYXBXYWxsZXRDb25uZWN0U2lnbkJ5dGVzRXJyb3IoYnl0ZXMsIGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlcmUgYXJlIG5vIGNvbm5lY3Rpb25zIHRoYXQgY2FuIGJlIHNpZ25pbmcgYnl0ZXMhYCk7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAc2VlIFdhbGxldCNoYXNDVzIwVG9rZW5zXG4gICAqIEBwYXJhbSBjaGFpbklEXG4gICAqIEBwYXJhbSB0b2tlbkFkZHJzIFRva2VuIGFkZHJlc3Nlc1xuICAgKi9cbiAgaGFzQ1cyMFRva2VucyA9IGFzeW5jIChcbiAgICBjaGFpbklEOiBzdHJpbmcsXG4gICAgLi4udG9rZW5BZGRyczogc3RyaW5nW11cbiAgKTogUHJvbWlzZTx7IFt0b2tlbkFkZHI6IHN0cmluZ106IGJvb2xlYW4gfT4gPT4ge1xuICAgIGlmICh0aGlzLmF2YWlsYWJsZUV4dGVuc2lvbkZlYXR1cmUoJ2N3MjAtdG9rZW4nKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZXh0ZW5zaW9uIS5oYXNDVzIwVG9rZW5zKGNoYWluSUQsIC4uLnRva2VuQWRkcnMpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgRG9lcyBub3Qgc3VwcG9ydCBoYXNDVzIwVG9rZW5zKCkgb24gdGhpcyBjb25uZWN0aW9uYCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEBzZWUgV2FsbGV0I2FkZENXMjBUb2tlbnNcbiAgICogQHBhcmFtIGNoYWluSURcbiAgICogQHBhcmFtIHRva2VuQWRkcnMgVG9rZW4gYWRkcmVzc2VzXG4gICAqL1xuICBhZGRDVzIwVG9rZW5zID0gYXN5bmMgKFxuICAgIGNoYWluSUQ6IHN0cmluZyxcbiAgICAuLi50b2tlbkFkZHJzOiBzdHJpbmdbXVxuICApOiBQcm9taXNlPHsgW3Rva2VuQWRkcjogc3RyaW5nXTogYm9vbGVhbiB9PiA9PiB7XG4gICAgaWYgKHRoaXMuYXZhaWxhYmxlRXh0ZW5zaW9uRmVhdHVyZSgnY3cyMC10b2tlbicpKSB7XG4gICAgICByZXR1cm4gdGhpcy5leHRlbnNpb24hLmFkZENXMjBUb2tlbnMoY2hhaW5JRCwgLi4udG9rZW5BZGRycyk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBEb2VzIG5vdCBzdXBwb3J0IGFkZENXMjBUb2tlbnMoKSBvbiB0aGlzIGNvbm5lY3Rpb25gKTtcbiAgfTtcblxuICAvKipcbiAgICogQHNlZSBXYWxsZXQjaGFzTmV0d29ya1xuICAgKiBAcGFyYW0gbmV0d29ya1xuICAgKi9cbiAgaGFzTmV0d29yayA9IChuZXR3b3JrOiBPbWl0PE5ldHdvcmtJbmZvLCAnbmFtZSc+KTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgaWYgKHRoaXMuYXZhaWxhYmxlRXh0ZW5zaW9uRmVhdHVyZSgnbmV0d29yaycpKSB7XG4gICAgICByZXR1cm4gdGhpcy5leHRlbnNpb24hLmhhc05ldHdvcmsobmV0d29yayk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBEb2VzIG5vdCBzdXBwb3J0IGhhc05ldHdvcmsoKSBvbiB0aGlzIGNvbm5lY3Rpb25gKTtcbiAgfTtcblxuICAvKipcbiAgICogQHNlZSBXYWxsZXQjaGFzTmV0d29ya1xuICAgKiBAcGFyYW0gbmV0d29ya1xuICAgKi9cbiAgYWRkTmV0d29yayA9IChuZXR3b3JrOiBOZXR3b3JrSW5mbyk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgIGlmICh0aGlzLmF2YWlsYWJsZUV4dGVuc2lvbkZlYXR1cmUoJ25ldHdvcmsnKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZXh0ZW5zaW9uIS5hZGROZXR3b3JrKG5ldHdvcmspO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgRG9lcyBub3Qgc3VwcG9ydCBhZGROZXR3b3JrKCkgb24gdGhpcyBjb25uZWN0aW9uYCk7XG4gIH07XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBpbnRlcm5hbFxuICAvLyBjb25uZWN0IHR5cGUgY2hhbmdpbmdcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBwcml2YXRlIGF2YWlsYWJsZUV4dGVuc2lvbkZlYXR1cmUgPSAoZmVhdHVyZTogWHBsYVdlYkV4dGVuc2lvbkZlYXR1cmVzKSA9PiB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZUV4dGVuc2lvbiAmJiB0aGlzLmV4dGVuc2lvbikge1xuICAgICAgY29uc3Qgc3RhdGVzID0gdGhpcy5leHRlbnNpb24uZ2V0TGFzdFN0YXRlcygpO1xuXG4gICAgICByZXR1cm4gKFxuICAgICAgICBzdGF0ZXMudHlwZSA9PT0gRXh0ZW5zaW9uUm91dGVyU3RhdHVzLldBTExFVF9DT05ORUNURUQgJiZcbiAgICAgICAgc3RhdGVzLnN1cHBvcnRGZWF0dXJlcy5oYXMoZmVhdHVyZSlcbiAgICAgICk7XG4gICAgfVxuICB9O1xuXG4gIHByaXZhdGUgdXBkYXRlU3RhdGVzID0gKG5leHQ6IFdhbGxldFN0YXRlcykgPT4ge1xuICAgIGNvbnN0IHByZXYgPSB0aGlzLl9zdGF0ZXMuZ2V0VmFsdWUoKTtcblxuICAgIGlmIChcbiAgICAgIG5leHQuc3RhdHVzID09PSBXYWxsZXRTdGF0dXMuV0FMTEVUX0NPTk5FQ1RFRCAmJlxuICAgICAgbmV4dC53YWxsZXRzLmxlbmd0aCA9PT0gMFxuICAgICkge1xuICAgICAgbmV4dCA9IHtcbiAgICAgICAgc3RhdHVzOiBXYWxsZXRTdGF0dXMuV0FMTEVUX05PVF9DT05ORUNURUQsXG4gICAgICAgIG5ldHdvcms6IG5leHQubmV0d29yayxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHByZXYuc3RhdHVzICE9PSBuZXh0LnN0YXR1cyB8fCAhZGVlcEVxdWFsKHByZXYsIG5leHQpKSB7XG4gICAgICB0aGlzLl9zdGF0ZXMubmV4dChuZXh0KTtcbiAgICB9XG4gIH07XG5cbiAgcHJpdmF0ZSBlbmFibGVSZWFkb25seVdhbGxldCA9IChyZWFkb25seVdhbGxldDogUmVhZG9ubHlXYWxsZXRDb250cm9sbGVyKSA9PiB7XG4gICAgdGhpcy5kaXNhYmxlV2FsbGV0Q29ubmVjdD8uKCk7XG4gICAgdGhpcy5kaXNhYmxlRXh0ZW5zaW9uPy4oKTtcblxuICAgIGlmIChcbiAgICAgIHRoaXMucmVhZG9ubHlXYWxsZXQgPT09IHJlYWRvbmx5V2FsbGV0IHx8XG4gICAgICAodGhpcy5yZWFkb25seVdhbGxldD8ueHBsYUFkZHJlc3MgPT09IHJlYWRvbmx5V2FsbGV0LnhwbGFBZGRyZXNzICYmXG4gICAgICAgIHRoaXMucmVhZG9ubHlXYWxsZXQubmV0d29yayA9PT0gcmVhZG9ubHlXYWxsZXQubmV0d29yaylcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5yZWFkb25seVdhbGxldCkge1xuICAgICAgdGhpcy5yZWFkb25seVdhbGxldC5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWFkb25seVdhbGxldCA9IHJlYWRvbmx5V2FsbGV0O1xuXG4gICAgdGhpcy51cGRhdGVTdGF0ZXMoe1xuICAgICAgc3RhdHVzOiBXYWxsZXRTdGF0dXMuV0FMTEVUX0NPTk5FQ1RFRCxcbiAgICAgIG5ldHdvcms6IHJlYWRvbmx5V2FsbGV0Lm5ldHdvcmssXG4gICAgICB3YWxsZXRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBjb25uZWN0VHlwZTogQ29ubmVjdFR5cGUuUkVBRE9OTFksXG4gICAgICAgICAgeHBsYUFkZHJlc3M6IHJlYWRvbmx5V2FsbGV0LnhwbGFBZGRyZXNzLFxuICAgICAgICAgIGRlc2lnbjogJ3JlYWRvbmx5JyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBzdXBwb3J0RmVhdHVyZXM6IEVNUFRZX1NVUFBPUlRfRkVBVFVSRVMsXG4gICAgICBjb25uZWN0aW9uOiBDT05ORUNUSU9OUy5SRUFET05MWSxcbiAgICB9KTtcblxuICAgIHRoaXMuZGlzYWJsZVJlYWRvbmx5V2FsbGV0ID0gKCkgPT4ge1xuICAgICAgcmVhZG9ubHlXYWxsZXQuZGlzY29ubmVjdCgpO1xuICAgICAgdGhpcy5yZWFkb25seVdhbGxldCA9IG51bGw7XG4gICAgICB0aGlzLmRpc2FibGVSZWFkb25seVdhbGxldCA9IG51bGw7XG4gICAgfTtcbiAgfTtcblxuICBwcml2YXRlIGVuYWJsZUV4dGVuc2lvbiA9ICgpID0+IHtcbiAgICB0aGlzLmRpc2FibGVSZWFkb25seVdhbGxldD8uKCk7XG4gICAgdGhpcy5kaXNhYmxlV2FsbGV0Q29ubmVjdD8uKCk7XG5cbiAgICBpZiAodGhpcy5kaXNhYmxlRXh0ZW5zaW9uIHx8ICF0aGlzLmV4dGVuc2lvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGV4dGVuc2lvblN1YnNjcmlwdGlvbiA9IHRoaXMuZXh0ZW5zaW9uLnN0YXRlcygpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAoZXh0ZW5zaW9uU3RhdGVzKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBleHRlbnNpb25TdGF0ZXMudHlwZSA9PT0gRXh0ZW5zaW9uUm91dGVyU3RhdHVzLldBTExFVF9DT05ORUNURUQgJiZcbiAgICAgICAgICBBY2NBZGRyZXNzLnZhbGlkYXRlKGV4dGVuc2lvblN0YXRlcy53YWxsZXQueHBsYUFkZHJlc3MpXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGVzKHtcbiAgICAgICAgICAgIHN0YXR1czogV2FsbGV0U3RhdHVzLldBTExFVF9DT05ORUNURUQsXG4gICAgICAgICAgICBuZXR3b3JrOiBleHRlbnNpb25TdGF0ZXMubmV0d29yayxcbiAgICAgICAgICAgIHdhbGxldHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbm5lY3RUeXBlOiBDb25uZWN0VHlwZS5FWFRFTlNJT04sXG4gICAgICAgICAgICAgICAgeHBsYUFkZHJlc3M6IGV4dGVuc2lvblN0YXRlcy53YWxsZXQueHBsYUFkZHJlc3MsXG4gICAgICAgICAgICAgICAgZGVzaWduOiBleHRlbnNpb25TdGF0ZXMud2FsbGV0LmRlc2lnbixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBzdXBwb3J0RmVhdHVyZXM6IGV4dGVuc2lvblN0YXRlcy5zdXBwb3J0RmVhdHVyZXMsXG4gICAgICAgICAgICBjb25uZWN0aW9uOiBtZW1vQ29ubmVjdGlvbihcbiAgICAgICAgICAgICAgQ29ubmVjdFR5cGUuRVhURU5TSU9OLFxuICAgICAgICAgICAgICBleHRlbnNpb25TdGF0ZXMuZXh0ZW5zaW9uSW5mby5uYW1lLFxuICAgICAgICAgICAgICBleHRlbnNpb25TdGF0ZXMuZXh0ZW5zaW9uSW5mby5pY29uLFxuICAgICAgICAgICAgICBleHRlbnNpb25TdGF0ZXMuZXh0ZW5zaW9uSW5mby5pZGVudGlmaWVyLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVN0YXRlcyh0aGlzLl9ub3RDb25uZWN0ZWQpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy5kaXNhYmxlRXh0ZW5zaW9uID0gKCkgPT4ge1xuICAgICAgdGhpcy5leHRlbnNpb24/LmRpc2Nvbm5lY3QoKTtcbiAgICAgIGV4dGVuc2lvblN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5kaXNhYmxlRXh0ZW5zaW9uID0gbnVsbDtcbiAgICB9O1xuICB9O1xuXG4gIHByaXZhdGUgZW5hYmxlV2FsbGV0Q29ubmVjdCA9ICh3YWxsZXRDb25uZWN0OiBXYWxsZXRDb25uZWN0Q29udHJvbGxlcikgPT4ge1xuICAgIHRoaXMuZGlzYWJsZVJlYWRvbmx5V2FsbGV0Py4oKTtcbiAgICB0aGlzLmRpc2FibGVFeHRlbnNpb24/LigpO1xuXG4gICAgaWYgKHRoaXMud2FsbGV0Q29ubmVjdCA9PT0gd2FsbGV0Q29ubmVjdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLndhbGxldENvbm5lY3QpIHtcbiAgICAgIHRoaXMud2FsbGV0Q29ubmVjdC5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgdGhpcy53YWxsZXRDb25uZWN0ID0gd2FsbGV0Q29ubmVjdDtcblxuICAgIGNvbnN0IHN1YnNjcmliZVdhbGxldENvbm5lY3QgPSAoXG4gICAgICB3YzogV2FsbGV0Q29ubmVjdENvbnRyb2xsZXIsXG4gICAgKTogU3Vic2NyaXB0aW9uID0+IHtcbiAgICAgIHJldHVybiB3Yy5zZXNzaW9uKCkuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHN0YXR1cykgPT4ge1xuICAgICAgICAgIHN3aXRjaCAoc3RhdHVzLnN0YXR1cykge1xuICAgICAgICAgICAgY2FzZSBXYWxsZXRDb25uZWN0U2Vzc2lvblN0YXR1cy5DT05ORUNURUQ6XG4gICAgICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGVzKHtcbiAgICAgICAgICAgICAgICBzdGF0dXM6IFdhbGxldFN0YXR1cy5XQUxMRVRfQ09OTkVDVEVELFxuICAgICAgICAgICAgICAgIG5ldHdvcms6XG4gICAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMud2FsbGV0Q29ubmVjdENoYWluSWRzW3N0YXR1cy5jaGFpbklkXSA/P1xuICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLmRlZmF1bHROZXR3b3JrLFxuICAgICAgICAgICAgICAgIHdhbGxldHM6IFtcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgY29ubmVjdFR5cGU6IENvbm5lY3RUeXBlLldBTExFVENPTk5FQ1QsXG4gICAgICAgICAgICAgICAgICAgIHhwbGFBZGRyZXNzOiBzdGF0dXMueHBsYUFkZHJlc3MsXG4gICAgICAgICAgICAgICAgICAgIGRlc2lnbjogJ3dhbGxldGNvbm5lY3QnLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIHN1cHBvcnRGZWF0dXJlczogV0FMTEVUQ09OTkVDVF9TVVBQT1JUX0ZFQVRVUkVTLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb246IENPTk5FQ1RJT05TLldBTExFVENPTk5FQ1QsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHRoaXMudXBkYXRlU3RhdGVzKHRoaXMuX25vdENvbm5lY3RlZCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBjb25zdCB3YWxsZXRDb25uZWN0U2Vzc2lvblN1YnNjcmlwdGlvbiA9XG4gICAgICBzdWJzY3JpYmVXYWxsZXRDb25uZWN0KHdhbGxldENvbm5lY3QpO1xuXG4gICAgdGhpcy5kaXNhYmxlV2FsbGV0Q29ubmVjdCA9ICgpID0+IHtcbiAgICAgIHRoaXMud2FsbGV0Q29ubmVjdD8uZGlzY29ubmVjdCgpO1xuICAgICAgdGhpcy53YWxsZXRDb25uZWN0ID0gbnVsbDtcbiAgICAgIHdhbGxldENvbm5lY3RTZXNzaW9uU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLmRpc2FibGVXYWxsZXRDb25uZWN0ID0gbnVsbDtcbiAgICB9O1xuICB9O1xufVxuXG5jb25zdCBtZW1vaXplZENvbm5lY3Rpb25zID0gbmV3IE1hcDxzdHJpbmcsIENvbm5lY3Rpb24+KCk7XG5cbmZ1bmN0aW9uIG1lbW9Db25uZWN0aW9uKFxuICBjb25uZWN0VHlwZTogQ29ubmVjdFR5cGUsXG4gIG5hbWU6IHN0cmluZyxcbiAgaWNvbjogc3RyaW5nLFxuICBpZGVudGlmaWVyOiBzdHJpbmcgfCB1bmRlZmluZWQgPSAnJyxcbik6IENvbm5lY3Rpb24ge1xuICBjb25zdCBrZXkgPSBbY29ubmVjdFR5cGUsIG5hbWUsIGljb24sIGlkZW50aWZpZXJdLmpvaW4oJzsnKTtcblxuICBpZiAobWVtb2l6ZWRDb25uZWN0aW9ucy5oYXMoa2V5KSkge1xuICAgIHJldHVybiBtZW1vaXplZENvbm5lY3Rpb25zLmdldChrZXkpITtcbiAgfVxuXG4gIGNvbnN0IGNvbm5lY3Rpb246IENvbm5lY3Rpb24gPSB7XG4gICAgdHlwZTogY29ubmVjdFR5cGUsXG4gICAgbmFtZSxcbiAgICBpY29uLFxuICAgIGlkZW50aWZpZXIsXG4gIH07XG5cbiAgbWVtb2l6ZWRDb25uZWN0aW9ucy5zZXQoa2V5LCBjb25uZWN0aW9uKTtcblxuICByZXR1cm4gY29ubmVjdGlvbjtcbn1cbiJdfQ==