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