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