@bitgo/sdk-coin-dot 4.3.13 → 4.3.15
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/CHANGELOG.md +8 -0
- package/package.json +6 -6
- package/LICENSE +0 -191
- package/dist/src/dot.d.ts +0 -154
- package/dist/src/dot.d.ts.map +0 -1
- package/dist/src/dot.js +0 -576
- package/dist/src/index.d.ts +0 -5
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -21
- package/dist/src/lib/addressInitializationBuilder.d.ts +0 -79
- package/dist/src/lib/addressInitializationBuilder.d.ts.map +0 -1
- package/dist/src/lib/addressInitializationBuilder.js +0 -182
- package/dist/src/lib/batchTransactionBuilder.d.ts +0 -62
- package/dist/src/lib/batchTransactionBuilder.d.ts.map +0 -1
- package/dist/src/lib/batchTransactionBuilder.js +0 -229
- package/dist/src/lib/claimBuilder.d.ts +0 -58
- package/dist/src/lib/claimBuilder.d.ts.map +0 -1
- package/dist/src/lib/claimBuilder.js +0 -117
- package/dist/src/lib/errors.d.ts +0 -8
- package/dist/src/lib/errors.d.ts.map +0 -1
- package/dist/src/lib/errors.js +0 -19
- package/dist/src/lib/iface.d.ts +0 -337
- package/dist/src/lib/iface.d.ts.map +0 -1
- package/dist/src/lib/iface.js +0 -128
- package/dist/src/lib/iface_utils.d.ts +0 -59
- package/dist/src/lib/iface_utils.d.ts.map +0 -1
- package/dist/src/lib/iface_utils.js +0 -92
- package/dist/src/lib/index.d.ts +0 -19
- package/dist/src/lib/index.d.ts.map +0 -1
- package/dist/src/lib/index.js +0 -71
- package/dist/src/lib/keyPair.d.ts +0 -38
- package/dist/src/lib/keyPair.d.ts.map +0 -1
- package/dist/src/lib/keyPair.js +0 -117
- package/dist/src/lib/nativeTransferBuilder.d.ts +0 -84
- package/dist/src/lib/nativeTransferBuilder.d.ts.map +0 -1
- package/dist/src/lib/nativeTransferBuilder.js +0 -219
- package/dist/src/lib/proxyBuilder.d.ts +0 -54
- package/dist/src/lib/proxyBuilder.d.ts.map +0 -1
- package/dist/src/lib/proxyBuilder.js +0 -116
- package/dist/src/lib/singletonRegistry.d.ts +0 -7
- package/dist/src/lib/singletonRegistry.d.ts.map +0 -1
- package/dist/src/lib/singletonRegistry.js +0 -20
- package/dist/src/lib/stakingBuilder.d.ts +0 -66
- package/dist/src/lib/stakingBuilder.d.ts.map +0 -1
- package/dist/src/lib/stakingBuilder.js +0 -167
- package/dist/src/lib/transaction.d.ts +0 -83
- package/dist/src/lib/transaction.d.ts.map +0 -1
- package/dist/src/lib/transaction.js +0 -610
- package/dist/src/lib/transactionBuilder.d.ts +0 -131
- package/dist/src/lib/transactionBuilder.d.ts.map +0 -1
- package/dist/src/lib/transactionBuilder.js +0 -351
- package/dist/src/lib/transactionBuilderFactory.d.ts +0 -28
- package/dist/src/lib/transactionBuilderFactory.d.ts.map +0 -1
- package/dist/src/lib/transactionBuilderFactory.js +0 -104
- package/dist/src/lib/transferBuilder.d.ts +0 -11
- package/dist/src/lib/transferBuilder.d.ts.map +0 -1
- package/dist/src/lib/transferBuilder.js +0 -11
- package/dist/src/lib/txnSchema.d.ts +0 -15
- package/dist/src/lib/txnSchema.d.ts.map +0 -1
- package/dist/src/lib/txnSchema.js +0 -117
- package/dist/src/lib/unnominateBuilder.d.ts +0 -24
- package/dist/src/lib/unnominateBuilder.d.ts.map +0 -1
- package/dist/src/lib/unnominateBuilder.js +0 -48
- package/dist/src/lib/unstakeBuilder.d.ts +0 -38
- package/dist/src/lib/unstakeBuilder.d.ts.map +0 -1
- package/dist/src/lib/unstakeBuilder.js +0 -87
- package/dist/src/lib/utils.d.ts +0 -261
- package/dist/src/lib/utils.d.ts.map +0 -1
- package/dist/src/lib/utils.js +0 -482
- package/dist/src/lib/withdrawUnstakedBuilder.d.ts +0 -38
- package/dist/src/lib/withdrawUnstakedBuilder.d.ts.map +0 -1
- package/dist/src/lib/withdrawUnstakedBuilder.js +0 -88
- package/dist/src/register.d.ts +0 -3
- package/dist/src/register.d.ts.map +0 -1
- package/dist/src/register.js +0 -11
- package/dist/src/resources/index.d.ts +0 -3
- package/dist/src/resources/index.d.ts.map +0 -1
- package/dist/src/resources/index.js +0 -19
- package/dist/src/resources/mainnet.d.ts +0 -2
- package/dist/src/resources/mainnet.d.ts.map +0 -1
- package/dist/src/resources/mainnet.js +0 -5
- package/dist/src/resources/westend.d.ts +0 -2
- package/dist/src/resources/westend.d.ts.map +0 -1
- package/dist/src/resources/westend.js +0 -5
- package/dist/src/tdot.d.ts +0 -12
- package/dist/src/tdot.d.ts.map +0 -1
- package/dist/src/tdot.js +0 -27
package/dist/src/dot.js
DELETED
|
@@ -1,576 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.Dot = exports.DEFAULT_SCAN_FACTOR = void 0;
|
|
40
|
-
const _ = __importStar(require("lodash"));
|
|
41
|
-
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
42
|
-
const statics_1 = require("@bitgo/statics");
|
|
43
|
-
const lib_1 = require("./lib");
|
|
44
|
-
require("@polkadot/api-augment");
|
|
45
|
-
const api_1 = require("@polkadot/api");
|
|
46
|
-
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
47
|
-
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
|
|
48
|
-
exports.DEFAULT_SCAN_FACTOR = 20; // default number of receive addresses to scan for funds
|
|
49
|
-
const dotUtils = lib_1.Utils.default;
|
|
50
|
-
class Dot extends sdk_core_1.BaseCoin {
|
|
51
|
-
constructor(bitgo, staticsCoin) {
|
|
52
|
-
super(bitgo);
|
|
53
|
-
this.MAX_VALIDITY_DURATION = 2400;
|
|
54
|
-
this.SWEEP_TXN_DURATION = 64;
|
|
55
|
-
if (!staticsCoin) {
|
|
56
|
-
throw new Error('missing required constructor parameter staticsCoin');
|
|
57
|
-
}
|
|
58
|
-
this._staticsCoin = staticsCoin;
|
|
59
|
-
}
|
|
60
|
-
static createInstance(bitgo, staticsCoin) {
|
|
61
|
-
return new Dot(bitgo, staticsCoin);
|
|
62
|
-
}
|
|
63
|
-
getChain() {
|
|
64
|
-
return 'dot';
|
|
65
|
-
}
|
|
66
|
-
getBaseChain() {
|
|
67
|
-
return 'dot';
|
|
68
|
-
}
|
|
69
|
-
getFamily() {
|
|
70
|
-
return 'dot';
|
|
71
|
-
}
|
|
72
|
-
getFullName() {
|
|
73
|
-
return 'Polkadot';
|
|
74
|
-
}
|
|
75
|
-
getBaseFactor() {
|
|
76
|
-
return Math.pow(10, this._staticsCoin.decimalPlaces);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Flag for sending value of 0
|
|
80
|
-
* @returns {boolean} True if okay to send 0 value, false otherwise
|
|
81
|
-
*/
|
|
82
|
-
valuelessTransferAllowed() {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
/** @inheritDoc */
|
|
86
|
-
supportsTss() {
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
/** inherited doc */
|
|
90
|
-
getDefaultMultisigType() {
|
|
91
|
-
return sdk_core_1.multisigTypes.tss;
|
|
92
|
-
}
|
|
93
|
-
getMPCAlgorithm() {
|
|
94
|
-
return 'eddsa';
|
|
95
|
-
}
|
|
96
|
-
allowsAccountConsolidations() {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Generate ed25519 key pair
|
|
101
|
-
*
|
|
102
|
-
* @param seed
|
|
103
|
-
* @returns {Object} object with generated pub, prv
|
|
104
|
-
*/
|
|
105
|
-
generateKeyPair(seed) {
|
|
106
|
-
const keyPair = seed ? dotUtils.keyPairFromSeed(new Uint8Array(seed)) : new lib_1.KeyPair();
|
|
107
|
-
const keys = keyPair.getKeys();
|
|
108
|
-
if (!keys.prv) {
|
|
109
|
-
throw new Error('Missing prv in key generation.');
|
|
110
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
pub: keys.pub,
|
|
113
|
-
prv: keys.prv,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Return boolean indicating whether input is valid public key for the coin.
|
|
118
|
-
*
|
|
119
|
-
* @param {String} pub the pub to be checked
|
|
120
|
-
* @returns {Boolean} is it valid?
|
|
121
|
-
*/
|
|
122
|
-
isValidPub(pub) {
|
|
123
|
-
return dotUtils.isValidPublicKey(pub);
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Return boolean indicating whether the supplied private key is a valid dot private key
|
|
127
|
-
*
|
|
128
|
-
* @param {String} prv the prv to be checked
|
|
129
|
-
* @returns {Boolean} is it valid?
|
|
130
|
-
*/
|
|
131
|
-
isValidPrv(prv) {
|
|
132
|
-
return dotUtils.isValidPrivateKey(prv);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Return boolean indicating whether input is valid public key for the coin
|
|
136
|
-
*
|
|
137
|
-
* @param {String} address the pub to be checked
|
|
138
|
-
* @returns {Boolean} is it valid?
|
|
139
|
-
*/
|
|
140
|
-
isValidAddress(address) {
|
|
141
|
-
return dotUtils.isValidAddress(address);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Sign message with private key
|
|
145
|
-
*
|
|
146
|
-
* @param key
|
|
147
|
-
* @param message
|
|
148
|
-
* @return {Buffer} A signature over the given message using the given key
|
|
149
|
-
*/
|
|
150
|
-
async signMessage(key, message) {
|
|
151
|
-
const msg = Buffer.isBuffer(message) ? message.toString('utf8') : message;
|
|
152
|
-
// reconstitute keys and sign
|
|
153
|
-
return Buffer.from(new lib_1.KeyPair({ prv: key.prv }).signMessage(msg));
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Explain/parse transaction
|
|
157
|
-
* @param unsignedTransaction
|
|
158
|
-
*/
|
|
159
|
-
async explainTransaction(unsignedTransaction) {
|
|
160
|
-
let outputAmount = 0;
|
|
161
|
-
unsignedTransaction.parsedTx.outputs.forEach((o) => {
|
|
162
|
-
outputAmount += parseInt(o.valueString, 10);
|
|
163
|
-
});
|
|
164
|
-
const explanationResult = {
|
|
165
|
-
displayOrder: [
|
|
166
|
-
'outputAmount',
|
|
167
|
-
'changeAmount',
|
|
168
|
-
'outputs',
|
|
169
|
-
'changeOutputs',
|
|
170
|
-
'fee',
|
|
171
|
-
'type',
|
|
172
|
-
'sequenceId',
|
|
173
|
-
'id',
|
|
174
|
-
'blockNumber',
|
|
175
|
-
],
|
|
176
|
-
sequenceId: unsignedTransaction.parsedTx.sequenceId,
|
|
177
|
-
fee: unsignedTransaction.feeInfo?.feeString,
|
|
178
|
-
id: unsignedTransaction.parsedTx.id,
|
|
179
|
-
type: unsignedTransaction.parsedTx.type,
|
|
180
|
-
outputs: unsignedTransaction.parsedTx.outputs,
|
|
181
|
-
blockNumber: unsignedTransaction.coinSpecific?.blockNumber,
|
|
182
|
-
outputAmount: outputAmount,
|
|
183
|
-
changeOutputs: [],
|
|
184
|
-
changeAmount: '0',
|
|
185
|
-
};
|
|
186
|
-
return explanationResult;
|
|
187
|
-
}
|
|
188
|
-
verifySignTransactionParams(params) {
|
|
189
|
-
const prv = params.prv;
|
|
190
|
-
const txHex = params.txPrebuild.txHex;
|
|
191
|
-
if (!txHex) {
|
|
192
|
-
throw new Error('missing txPrebuild parameter');
|
|
193
|
-
}
|
|
194
|
-
if (!_.isString(txHex)) {
|
|
195
|
-
throw new Error(`txPrebuild must be an object, got type ${typeof txHex}`);
|
|
196
|
-
}
|
|
197
|
-
if (!prv) {
|
|
198
|
-
throw new Error('missing prv parameter to sign transaction');
|
|
199
|
-
}
|
|
200
|
-
if (!_.isString(prv)) {
|
|
201
|
-
throw new Error(`prv must be a string, got type ${typeof prv}`);
|
|
202
|
-
}
|
|
203
|
-
if (!_.has(params, 'pubs')) {
|
|
204
|
-
throw new Error('missing public key parameter to sign transaction');
|
|
205
|
-
}
|
|
206
|
-
return { txHex, prv };
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Assemble keychain and half-sign prebuilt transaction
|
|
210
|
-
*
|
|
211
|
-
* @param params
|
|
212
|
-
* @param params.txPrebuild {TransactionPrebuild} prebuild object returned by platform
|
|
213
|
-
* @param params.prv {String} user prv
|
|
214
|
-
* @returns {Promise<SignedTransaction>}
|
|
215
|
-
*/
|
|
216
|
-
async signTransaction(params) {
|
|
217
|
-
const { txHex, prv } = this.verifySignTransactionParams(params);
|
|
218
|
-
const factory = this.getBuilder();
|
|
219
|
-
const txBuilder = factory.from(txHex);
|
|
220
|
-
const keyPair = new lib_1.KeyPair({ prv: prv });
|
|
221
|
-
const { referenceBlock, blockNumber, transactionVersion, sender } = params.txPrebuild.transaction;
|
|
222
|
-
txBuilder
|
|
223
|
-
.validity({ firstValid: blockNumber, maxDuration: this.MAX_VALIDITY_DURATION })
|
|
224
|
-
.referenceBlock(referenceBlock)
|
|
225
|
-
.version(transactionVersion)
|
|
226
|
-
.sender({ address: sender })
|
|
227
|
-
.sign({ key: keyPair.getKeys().prv });
|
|
228
|
-
const transaction = await txBuilder.build();
|
|
229
|
-
if (!transaction) {
|
|
230
|
-
throw new Error('Invalid transaction');
|
|
231
|
-
}
|
|
232
|
-
const signedTxHex = transaction.toBroadcastFormat();
|
|
233
|
-
return { txHex: signedTxHex };
|
|
234
|
-
}
|
|
235
|
-
async getInitializedNodeAPI() {
|
|
236
|
-
if (!Dot.nodeApiInitialized) {
|
|
237
|
-
const wsProvider = new api_1.WsProvider(sdk_core_1.Environments[this.bitgo.getEnv()].dotNodeUrls);
|
|
238
|
-
Dot.API = await api_1.ApiPromise.create({ provider: wsProvider });
|
|
239
|
-
Dot.nodeApiInitialized = true;
|
|
240
|
-
}
|
|
241
|
-
return Dot.API;
|
|
242
|
-
}
|
|
243
|
-
async getAccountInfo(walletAddr) {
|
|
244
|
-
const api = await this.getInitializedNodeAPI();
|
|
245
|
-
const { nonce, data: balance } = await api.query.system.account(walletAddr);
|
|
246
|
-
return { nonce: nonce.toNumber(), freeBalance: balance.free.toNumber() };
|
|
247
|
-
}
|
|
248
|
-
async getHeaderInfo() {
|
|
249
|
-
const api = await this.getInitializedNodeAPI();
|
|
250
|
-
const { number, hash } = await api.rpc.chain.getHeader();
|
|
251
|
-
return { headerNumber: number.toNumber(), headerHash: hash.toString() };
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
*
|
|
255
|
-
* Estimate the fee of the transaction
|
|
256
|
-
*
|
|
257
|
-
* @param {string} destAddr destination wallet address
|
|
258
|
-
* @param {string} srcAddr source wallet address
|
|
259
|
-
* @param {string} amount amount to transfer
|
|
260
|
-
* @returns {number} the estimated fee the transaction will cost
|
|
261
|
-
*
|
|
262
|
-
* @see https://polkadot.js.org/docs/api/cookbook/tx#how-do-i-estimate-the-transaction-fees
|
|
263
|
-
*/
|
|
264
|
-
async getFee(destAddr, srcAddr, amount) {
|
|
265
|
-
const api = await this.getInitializedNodeAPI();
|
|
266
|
-
const info = await api.tx.balances.transferAllowDeath(destAddr, amount).paymentInfo(srcAddr);
|
|
267
|
-
return info.partialFee.toNumber();
|
|
268
|
-
}
|
|
269
|
-
async getMaterial() {
|
|
270
|
-
const api = await this.getInitializedNodeAPI();
|
|
271
|
-
return {
|
|
272
|
-
genesisHash: api.genesisHash.toString(),
|
|
273
|
-
chainName: api.runtimeChain.toString(),
|
|
274
|
-
specName: api.runtimeVersion.specName.toString(),
|
|
275
|
-
specVersion: api.runtimeVersion.specVersion.toNumber(),
|
|
276
|
-
txVersion: api.runtimeVersion.transactionVersion.toNumber(),
|
|
277
|
-
metadata: api.runtimeMetadata.toHex(),
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Builds a funds recovery transaction without BitGo
|
|
282
|
-
* @param {MPCRecoveryOptions} params parameters needed to construct and
|
|
283
|
-
* (maybe) sign the transaction
|
|
284
|
-
*
|
|
285
|
-
* @returns {MPCTx} the serialized transaction hex string and index
|
|
286
|
-
* of the address being swept
|
|
287
|
-
*/
|
|
288
|
-
async recover(params) {
|
|
289
|
-
if (!params.bitgoKey) {
|
|
290
|
-
throw new Error('missing bitgoKey');
|
|
291
|
-
}
|
|
292
|
-
if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
|
|
293
|
-
throw new Error('invalid recoveryDestination');
|
|
294
|
-
}
|
|
295
|
-
const bitgoKey = params.bitgoKey.replace(/\s/g, '');
|
|
296
|
-
const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
|
|
297
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
298
|
-
const index = params.index || 0;
|
|
299
|
-
const currPath = params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${index}` : `m/${index}`;
|
|
300
|
-
const accountId = MPC.deriveUnhardened(bitgoKey, currPath).slice(0, 64);
|
|
301
|
-
const senderAddr = this.getAddressFromPublicKey(accountId);
|
|
302
|
-
const { nonce, freeBalance } = await this.getAccountInfo(senderAddr);
|
|
303
|
-
const destAddr = params.recoveryDestination;
|
|
304
|
-
const amount = freeBalance;
|
|
305
|
-
const partialFee = await this.getFee(destAddr, senderAddr, amount);
|
|
306
|
-
const value = new bignumber_js_1.default(freeBalance).minus(new bignumber_js_1.default(partialFee));
|
|
307
|
-
if (value.isLessThanOrEqualTo(0)) {
|
|
308
|
-
throw new Error('Did not find address with funds to recover');
|
|
309
|
-
}
|
|
310
|
-
// first build the unsigned txn
|
|
311
|
-
const { headerNumber, headerHash } = await this.getHeaderInfo();
|
|
312
|
-
const material = await this.getMaterial();
|
|
313
|
-
const validityWindow = { firstValid: headerNumber, maxDuration: this.MAX_VALIDITY_DURATION };
|
|
314
|
-
const txnBuilder = this.getBuilder().getTransferBuilder().material(material);
|
|
315
|
-
txnBuilder
|
|
316
|
-
.sweep(false)
|
|
317
|
-
.to({ address: params.recoveryDestination })
|
|
318
|
-
.sender({ address: senderAddr })
|
|
319
|
-
.validity(validityWindow)
|
|
320
|
-
.referenceBlock(headerHash)
|
|
321
|
-
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: nonce })
|
|
322
|
-
.fee({ amount: 0, type: 'tip' });
|
|
323
|
-
const unsignedTransaction = (await txnBuilder.build());
|
|
324
|
-
let serializedTx = unsignedTransaction.toBroadcastFormat();
|
|
325
|
-
if (!isUnsignedSweep) {
|
|
326
|
-
if (!params.userKey) {
|
|
327
|
-
throw new Error('missing userKey');
|
|
328
|
-
}
|
|
329
|
-
if (!params.backupKey) {
|
|
330
|
-
throw new Error('missing backupKey');
|
|
331
|
-
}
|
|
332
|
-
if (!params.walletPassphrase) {
|
|
333
|
-
throw new Error('missing wallet passphrase');
|
|
334
|
-
}
|
|
335
|
-
// Clean up whitespace from entered values
|
|
336
|
-
const userKey = params.userKey.replace(/\s/g, '');
|
|
337
|
-
const backupKey = params.backupKey.replace(/\s/g, '');
|
|
338
|
-
// Decrypt private keys from KeyCard values
|
|
339
|
-
let userPrv;
|
|
340
|
-
try {
|
|
341
|
-
userPrv = this.bitgo.decrypt({
|
|
342
|
-
input: userKey,
|
|
343
|
-
password: params.walletPassphrase,
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
catch (e) {
|
|
347
|
-
throw new Error(`Error decrypting user keychain: ${e.message}`);
|
|
348
|
-
}
|
|
349
|
-
/** TODO BG-52419 Implement Codec for parsing */
|
|
350
|
-
const userSigningMaterial = JSON.parse(userPrv);
|
|
351
|
-
let backupPrv;
|
|
352
|
-
try {
|
|
353
|
-
backupPrv = this.bitgo.decrypt({
|
|
354
|
-
input: backupKey,
|
|
355
|
-
password: params.walletPassphrase,
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
catch (e) {
|
|
359
|
-
throw new Error(`Error decrypting backup keychain: ${e.message}`);
|
|
360
|
-
}
|
|
361
|
-
const backupSigningMaterial = JSON.parse(backupPrv);
|
|
362
|
-
// add signature
|
|
363
|
-
const signatureHex = await sdk_core_1.EDDSAMethods.getTSSSignature(userSigningMaterial, backupSigningMaterial, currPath, unsignedTransaction);
|
|
364
|
-
const dotKeyPair = new lib_1.KeyPair({ pub: accountId });
|
|
365
|
-
txnBuilder.addSignature({ pub: dotKeyPair.getKeys().pub }, signatureHex);
|
|
366
|
-
const signedTransaction = await txnBuilder.build();
|
|
367
|
-
serializedTx = signedTransaction.toBroadcastFormat();
|
|
368
|
-
}
|
|
369
|
-
else {
|
|
370
|
-
const value = new bignumber_js_1.default(freeBalance);
|
|
371
|
-
const walletCoin = this.getChain();
|
|
372
|
-
const inputs = [
|
|
373
|
-
{
|
|
374
|
-
address: unsignedTransaction.inputs[0].address,
|
|
375
|
-
valueString: value.toString(),
|
|
376
|
-
value: value.toNumber(),
|
|
377
|
-
},
|
|
378
|
-
];
|
|
379
|
-
const outputs = [
|
|
380
|
-
{
|
|
381
|
-
address: unsignedTransaction.outputs[0].address,
|
|
382
|
-
valueString: value.toString(),
|
|
383
|
-
coinName: walletCoin,
|
|
384
|
-
},
|
|
385
|
-
];
|
|
386
|
-
const spendAmount = value.toString();
|
|
387
|
-
const parsedTx = { inputs: inputs, outputs: outputs, spendAmount: spendAmount, type: '' };
|
|
388
|
-
const feeInfo = { fee: 0, feeString: '0' };
|
|
389
|
-
const transaction = {
|
|
390
|
-
serializedTx: serializedTx,
|
|
391
|
-
scanIndex: index,
|
|
392
|
-
coin: walletCoin,
|
|
393
|
-
signableHex: unsignedTransaction.signablePayload.toString('hex'),
|
|
394
|
-
derivationPath: currPath,
|
|
395
|
-
parsedTx: parsedTx,
|
|
396
|
-
feeInfo: feeInfo,
|
|
397
|
-
coinSpecific: { ...validityWindow, commonKeychain: bitgoKey },
|
|
398
|
-
};
|
|
399
|
-
const unsignedTx = { unsignedTx: transaction, signatureShares: [] };
|
|
400
|
-
const transactions = [unsignedTx];
|
|
401
|
-
const txRequest = {
|
|
402
|
-
transactions: transactions,
|
|
403
|
-
walletCoin: walletCoin,
|
|
404
|
-
};
|
|
405
|
-
const txRequests = { txRequests: [txRequest] };
|
|
406
|
-
return txRequests;
|
|
407
|
-
}
|
|
408
|
-
const transaction = { serializedTx: serializedTx, scanIndex: index };
|
|
409
|
-
return transaction;
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Builds native DOT recoveries of receive addresses in batch without BitGo.
|
|
413
|
-
* Funds will be recovered to base address first. You need to initiate another sweep txn after that.
|
|
414
|
-
*
|
|
415
|
-
* @param {MPCConsolidationRecoveryOptions} params - options for consolidation recovery.
|
|
416
|
-
* @param {string} [params.startingScanIndex] - receive address index to start scanning from. default to 1 (inclusive).
|
|
417
|
-
* @param {string} [params.endingScanIndex] - receive address index to end scanning at. default to startingScanIndex + 20 (exclusive).
|
|
418
|
-
*/
|
|
419
|
-
async recoverConsolidations(params) {
|
|
420
|
-
const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
|
|
421
|
-
const startIdx = params.startingScanIndex || 1;
|
|
422
|
-
const endIdx = params.endingScanIndex || startIdx + exports.DEFAULT_SCAN_FACTOR;
|
|
423
|
-
if (startIdx < 1 || endIdx <= startIdx || endIdx - startIdx > 10 * exports.DEFAULT_SCAN_FACTOR) {
|
|
424
|
-
throw new Error(`Invalid starting or ending index to scan for addresses. startingScanIndex: ${startIdx}, endingScanIndex: ${endIdx}.`);
|
|
425
|
-
}
|
|
426
|
-
const bitgoKey = params.bitgoKey.replace(/\s/g, '');
|
|
427
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
428
|
-
const baseIndex = 0;
|
|
429
|
-
const basePath = params.seed ? (0, sdk_lib_mpc_1.getDerivationPath)(params.seed) + `/${baseIndex}` : `m/${baseIndex}`;
|
|
430
|
-
const accountId = MPC.deriveUnhardened(bitgoKey, basePath).slice(0, 64);
|
|
431
|
-
const baseAddress = this.getAddressFromPublicKey(accountId);
|
|
432
|
-
const consolidationTransactions = [];
|
|
433
|
-
let lastScanIndex = startIdx;
|
|
434
|
-
for (let i = startIdx; i < endIdx; i++) {
|
|
435
|
-
const recoverParams = {
|
|
436
|
-
userKey: params.userKey,
|
|
437
|
-
backupKey: params.backupKey,
|
|
438
|
-
bitgoKey: params.bitgoKey,
|
|
439
|
-
walletPassphrase: params.walletPassphrase,
|
|
440
|
-
recoveryDestination: baseAddress,
|
|
441
|
-
seed: params.seed,
|
|
442
|
-
index: i,
|
|
443
|
-
};
|
|
444
|
-
let recoveryTransaction;
|
|
445
|
-
try {
|
|
446
|
-
recoveryTransaction = await this.recover(recoverParams);
|
|
447
|
-
}
|
|
448
|
-
catch (e) {
|
|
449
|
-
if (e.message === 'Did not find address with funds to recover') {
|
|
450
|
-
lastScanIndex = i;
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
|
-
throw e;
|
|
454
|
-
}
|
|
455
|
-
if (isUnsignedSweep) {
|
|
456
|
-
consolidationTransactions.push(recoveryTransaction.txRequests[0]);
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
consolidationTransactions.push(recoveryTransaction);
|
|
460
|
-
}
|
|
461
|
-
lastScanIndex = i;
|
|
462
|
-
}
|
|
463
|
-
if (consolidationTransactions.length == 0) {
|
|
464
|
-
throw new Error('Did not find an address with funds to recover');
|
|
465
|
-
}
|
|
466
|
-
if (isUnsignedSweep) {
|
|
467
|
-
// lastScanIndex will be used to inform user the last address index scanned for available funds (so they can
|
|
468
|
-
// appropriately adjust the scan range on the next iteration of consolidation recoveries). In the case of unsigned
|
|
469
|
-
// sweep consolidations, this lastScanIndex will be provided in the coinSpecific of the last txn made.
|
|
470
|
-
const lastTransactionCoinSpecific = {
|
|
471
|
-
firstValid: consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific
|
|
472
|
-
.firstValid,
|
|
473
|
-
maxDuration: consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific
|
|
474
|
-
.maxDuration,
|
|
475
|
-
commonKeychain: consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific
|
|
476
|
-
.commonKeychain,
|
|
477
|
-
lastScanIndex: lastScanIndex,
|
|
478
|
-
};
|
|
479
|
-
consolidationTransactions[consolidationTransactions.length - 1].transactions[0].unsignedTx.coinSpecific =
|
|
480
|
-
lastTransactionCoinSpecific;
|
|
481
|
-
const consolidationSweepTransactions = { txRequests: consolidationTransactions };
|
|
482
|
-
return consolidationSweepTransactions;
|
|
483
|
-
}
|
|
484
|
-
return { transactions: consolidationTransactions, lastScanIndex };
|
|
485
|
-
}
|
|
486
|
-
/** inherited doc */
|
|
487
|
-
async createBroadcastableSweepTransaction(params) {
|
|
488
|
-
const req = params.signatureShares;
|
|
489
|
-
const broadcastableTransactions = [];
|
|
490
|
-
let lastScanIndex = 0;
|
|
491
|
-
for (let i = 0; i < req.length; i++) {
|
|
492
|
-
const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
|
|
493
|
-
const transaction = req[i].txRequest.transactions[0].unsignedTx;
|
|
494
|
-
if (!req[i].ovc || !req[i].ovc[0].eddsaSignature) {
|
|
495
|
-
throw new Error('Missing signature(s)');
|
|
496
|
-
}
|
|
497
|
-
const signature = req[i].ovc[0].eddsaSignature;
|
|
498
|
-
if (!transaction.signableHex) {
|
|
499
|
-
throw new Error('Missing signable hex');
|
|
500
|
-
}
|
|
501
|
-
const messageBuffer = Buffer.from(transaction.signableHex, 'hex');
|
|
502
|
-
const result = MPC.verify(messageBuffer, signature);
|
|
503
|
-
if (!result) {
|
|
504
|
-
throw new Error('Invalid signature');
|
|
505
|
-
}
|
|
506
|
-
const signatureHex = Buffer.concat([Buffer.from(signature.R, 'hex'), Buffer.from(signature.sigma, 'hex')]);
|
|
507
|
-
if (!transaction.coinSpecific ||
|
|
508
|
-
!transaction.coinSpecific?.firstValid ||
|
|
509
|
-
!transaction.coinSpecific?.maxDuration) {
|
|
510
|
-
throw new Error('missing validity window');
|
|
511
|
-
}
|
|
512
|
-
const validityWindow = {
|
|
513
|
-
firstValid: transaction.coinSpecific?.firstValid,
|
|
514
|
-
maxDuration: transaction.coinSpecific?.maxDuration,
|
|
515
|
-
};
|
|
516
|
-
const material = await this.getMaterial();
|
|
517
|
-
if (!transaction.coinSpecific?.commonKeychain) {
|
|
518
|
-
throw new Error('Missing common keychain');
|
|
519
|
-
}
|
|
520
|
-
const commonKeychain = transaction.coinSpecific.commonKeychain;
|
|
521
|
-
if (!transaction.derivationPath) {
|
|
522
|
-
throw new Error('Missing derivation path');
|
|
523
|
-
}
|
|
524
|
-
const derivationPath = transaction.derivationPath;
|
|
525
|
-
const accountId = MPC.deriveUnhardened(commonKeychain, derivationPath).slice(0, 64);
|
|
526
|
-
const senderAddr = this.getAddressFromPublicKey(accountId);
|
|
527
|
-
const txnBuilder = this.getBuilder()
|
|
528
|
-
.material(material)
|
|
529
|
-
.from(transaction.serializedTx)
|
|
530
|
-
.sender({ address: senderAddr })
|
|
531
|
-
.validity(validityWindow);
|
|
532
|
-
const dotKeyPair = new lib_1.KeyPair({ pub: accountId });
|
|
533
|
-
txnBuilder.addSignature({ pub: dotKeyPair.getKeys().pub }, signatureHex);
|
|
534
|
-
const signedTransaction = await txnBuilder.build();
|
|
535
|
-
const serializedTx = signedTransaction.toBroadcastFormat();
|
|
536
|
-
broadcastableTransactions.push({
|
|
537
|
-
serializedTx: serializedTx,
|
|
538
|
-
scanIndex: transaction.scanIndex,
|
|
539
|
-
});
|
|
540
|
-
if (i === req.length - 1 && transaction.coinSpecific.lastScanIndex) {
|
|
541
|
-
lastScanIndex = transaction.coinSpecific.lastScanIndex;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
return { transactions: broadcastableTransactions, lastScanIndex };
|
|
545
|
-
}
|
|
546
|
-
async parseTransaction(params) {
|
|
547
|
-
return {};
|
|
548
|
-
}
|
|
549
|
-
async isWalletAddress(params) {
|
|
550
|
-
throw new sdk_core_1.MethodNotImplementedError();
|
|
551
|
-
}
|
|
552
|
-
async verifyTransaction(params) {
|
|
553
|
-
const { txParams } = params;
|
|
554
|
-
if (Array.isArray(txParams.recipients) && txParams.recipients.length > 1) {
|
|
555
|
-
throw new Error(`${this.getChain()} doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
|
|
556
|
-
}
|
|
557
|
-
return true;
|
|
558
|
-
}
|
|
559
|
-
getAddressFromPublicKey(Pubkey) {
|
|
560
|
-
return new lib_1.KeyPair({ pub: Pubkey }).getAddress(lib_1.Utils.default.getAddressFormat(this.getChain()));
|
|
561
|
-
}
|
|
562
|
-
getBuilder() {
|
|
563
|
-
return new lib_1.TransactionBuilderFactory(statics_1.coins.get(this.getChain()));
|
|
564
|
-
}
|
|
565
|
-
/** @inheritDoc */
|
|
566
|
-
auditDecryptedKey({ publicKey, prv, multiSigType }) {
|
|
567
|
-
if (multiSigType !== 'tss') {
|
|
568
|
-
throw new Error('Unsupported multiSigType');
|
|
569
|
-
}
|
|
570
|
-
(0, sdk_lib_mpc_1.auditEddsaPrivateKey)(prv, publicKey ?? '');
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
exports.Dot = Dot;
|
|
574
|
-
Dot.initialized = false;
|
|
575
|
-
Dot.nodeApiInitialized = false;
|
|
576
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG90LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RvdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwwQ0FBNEI7QUFDNUIsOENBOEJ5QjtBQUN6Qiw0Q0FBMEY7QUFDMUYsK0JBQXdHO0FBQ3hHLGlDQUErQjtBQUMvQix1Q0FBdUQ7QUFFdkQsZ0VBQXFDO0FBQ3JDLG9EQUE2RTtBQUVoRSxRQUFBLG1CQUFtQixHQUFHLEVBQUUsQ0FBQyxDQUFDLHdEQUF3RDtBQXlCL0YsTUFBTSxRQUFRLEdBQUcsV0FBSyxDQUFDLE9BQU8sQ0FBQztBQUUvQixNQUFhLEdBQUksU0FBUSxtQkFBUTtJQUsvQixZQUFZLEtBQWdCLEVBQUUsV0FBdUM7UUFDbkUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBSk4sMEJBQXFCLEdBQUcsSUFBSSxDQUFDO1FBQzdCLHVCQUFrQixHQUFHLEVBQUUsQ0FBQztRQUsvQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztJQUNsQyxDQUFDO0lBT0QsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFnQixFQUFFLFdBQXVDO1FBQzdFLE9BQU8sSUFBSSxHQUFHLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRCxRQUFRO1FBQ04sT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsWUFBWTtRQUNWLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELFNBQVM7UUFDUCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxXQUFXO1FBQ1QsT0FBTyxVQUFVLENBQUM7SUFDcEIsQ0FBQztJQUVELGFBQWE7UUFDWCxPQUFPLElBQUksQ0FBQyxHQUFH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RUQsa0JBQWtCO0lBQ2xCLGlCQUFpQixDQUFDLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxZQUFZLEVBQTJCO1FBQ3pFLElBQUksWUFBWSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBQ0QsSUFBQSxrQ0FBb0IsRUFBQyxHQUFHLEVBQUUsU0FBUyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzdDLENBQUM7O0FBN2xCSCxrQkE4bEJDO0FBL2tCa0IsZUFBVyxHQUFHLEtBQUssQUFBUixDQUFTO0FBRXBCLHNCQUFrQixHQUFHLEtBQUssQUFBUixDQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHtcbiAgQmFzZUNvaW4sXG4gIEJpdEdvQmFzZSxcbiAgRG90QXNzZXRUeXBlcyxcbiAgRWRkc2EsXG4gIEVudmlyb25tZW50cyxcbiAgRXhwbGFuYXRpb25SZXN1bHQsXG4gIEtleVBhaXIsXG4gIE1ldGhvZE5vdEltcGxlbWVudGVkRXJyb3IsXG4gIE1QQ0FsZ29yaXRobSxcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyBhcyBCYXNlU2lnblRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgVW5zaWduZWRUcmFuc2FjdGlvbixcbiAgVmVyaWZ5QWRkcmVzc09wdGlvbnMsXG4gIFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgRUREU0FNZXRob2RzLFxuICBFRERTQU1ldGhvZFR5cGVzLFxuICBNUENUeCxcbiAgTVBDUmVjb3ZlcnlPcHRpb25zLFxuICBNUENDb25zb2xpZGF0aW9uUmVjb3ZlcnlPcHRpb25zLFxuICBNUENTd2VlcFR4cyxcbiAgUmVjb3ZlcnlUeFJlcXVlc3QsXG4gIE1QQ1Vuc2lnbmVkVHgsXG4gIE1QQ1N3ZWVwUmVjb3ZlcnlPcHRpb25zLFxuICBNUENUeHMsXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4sIGNvaW5zLCBQb2xrYWRvdFNwZWNOYW1lVHlwZSB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCB7IEludGVyZmFjZSwgS2V5UGFpciBhcyBEb3RLZXlQYWlyLCBUcmFuc2FjdGlvbiwgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSwgVXRpbHMgfSBmcm9tICcuL2xpYic7XG5pbXBvcnQgJ0Bwb2xrYWRvdC9hcGktYXVnbWVudCc7XG5pbXBvcnQgeyBBcGlQcm9taXNlLCBXc1Byb3ZpZGVyIH0gZnJvbSAnQHBvbGthZG90L2FwaSc7XG5pbXBvcnQgeyBNYXRlcmlhbCB9IGZyb20gJy4vbGliL2lmYWNlJztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IGF1ZGl0RWRkc2FQcml2YXRlS2V5LCBnZXREZXJpdmF0aW9uUGF0aCB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1NDQU5fRkFDVE9SID0gMjA7IC8vIGRlZmF1bHQgbnVtYmVyIG9mIHJlY2VpdmUgYWRkcmVzc2VzIHRvIHNjYW4gZm9yIGZ1bmRzXG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIEJhc2VTaWduVHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgdHhQcmVidWlsZDogVHJhbnNhY3Rpb25QcmVidWlsZDtcbiAgcHJ2OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNhY3Rpb25QcmVidWlsZCB7XG4gIHR4SGV4OiBzdHJpbmc7XG4gIHRyYW5zYWN0aW9uOiBJbnRlcmZhY2UuVHhEYXRhO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMge1xuICB0eFByZWJ1aWxkOiBUcmFuc2FjdGlvblByZWJ1aWxkO1xuICBwdWJsaWNLZXk6IHN0cmluZztcbiAgZmVlSW5mbzoge1xuICAgIGZlZTogc3RyaW5nO1xuICB9O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZlcmlmaWVkVHJhbnNhY3Rpb25QYXJhbWV0ZXJzIHtcbiAgdHhIZXg6IHN0cmluZztcbiAgcHJ2OiBzdHJpbmc7XG59XG5cbmNvbnN0IGRvdFV0aWxzID0gVXRpbHMuZGVmYXVsdDtcblxuZXhwb3J0IGNsYXNzIERvdCBleHRlbmRzIEJhc2VDb2luIHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IF9zdGF0aWNzQ29pbjogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPjtcbiAgcmVhZG9ubHkgTUFYX1ZBTElESVRZX0RVUkFUSU9OID0gMjQwMDtcbiAgcmVhZG9ubHkgU1dFRVBfVFhOX0RVUkFUSU9OID0gNjQ7XG5cbiAgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuXG4gICAgaWYgKCFzdGF0aWNzQ29pbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvbnN0cnVjdG9yIHBhcmFtZXRlciBzdGF0aWNzQ29pbicpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YXRpY3NDb2luID0gc3RhdGljc0NvaW47XG4gIH1cblxuICBwcm90ZWN0ZWQgc3RhdGljIGluaXRpYWxpemVkID0gZmFsc2U7XG4gIHByb3RlY3RlZCBzdGF0aWMgTVBDOiBFZGRzYTtcbiAgcHJvdGVjdGVkIHN0YXRpYyBub2RlQXBpSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIHN0YXRpYyBBUEk6IEFwaVByb21pc2U7XG5cbiAgc3RhdGljIGNyZWF0ZUluc3RhbmNlKGJpdGdvOiBCaXRHb0Jhc2UsIHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPik6IEJhc2VDb2luIHtcbiAgICByZXR1cm4gbmV3IERvdChiaXRnbywgc3RhdGljc0NvaW4pO1xuICB9XG5cbiAgZ2V0Q2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ2RvdCc7XG4gIH1cblxuICBnZXRCYXNlQ2hhaW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ2RvdCc7XG4gIH1cblxuICBnZXRGYW1pbHkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ2RvdCc7XG4gIH1cblxuICBnZXRGdWxsTmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiAnUG9sa2Fkb3QnO1xuICB9XG5cbiAgZ2V0QmFzZUZhY3RvcigpOiBudW1iZXIge1xuICAgIHJldHVybiBNYXRoLnBvdygxMCwgdGhpcy5fc3RhdGljc0NvaW4uZGVjaW1hbFBsYWNlcyk7XG4gIH1cblxuICAvKipcbiAgICogRmxhZyBmb3Igc2VuZGluZyB2YWx1ZSBvZiAwXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG9rYXkgdG8gc2VuZCAwIHZhbHVlLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHZhbHVlbGVzc1RyYW5zZmVyQWxsb3dlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBpbmhlcml0ZWQgZG9jICovXG4gIGdldERlZmF1bHRNdWx0aXNpZ1R5cGUoKTogTXVsdGlzaWdUeXBlIHtcbiAgICByZXR1cm4gbXVsdGlzaWdUeXBlcy50c3M7XG4gIH1cblxuICBnZXRNUENBbGdvcml0aG0oKTogTVBDQWxnb3JpdGhtIHtcbiAgICByZXR1cm4gJ2VkZHNhJztcbiAgfVxuXG4gIGFsbG93c0FjY291bnRDb25zb2xpZGF0aW9ucygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBlZDI1NTE5IGtleSBwYWlyXG4gICAqXG4gICAqIEBwYXJhbSBzZWVkXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IG9iamVjdCB3aXRoIGdlbmVyYXRlZCBwdWIsIHBydlxuICAgKi9cbiAgZ2VuZXJhdGVLZXlQYWlyKHNlZWQ/OiBCdWZmZXIpOiBLZXlQYWlyIHtcbiAgICBjb25zdCBrZXlQYWlyID0gc2VlZCA/IGRvdFV0aWxzLmtleVBhaXJGcm9tU2VlZChuZXcgVWludDhBcnJheShzZWVkKSkgOiBuZXcgRG90S2V5UGFpcigpO1xuICAgIGNvbnN0IGtleXMgPSBrZXlQYWlyLmdldEtleXMoKTtcbiAgICBpZiAoIWtleXMucHJ2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcHJ2IGluIGtleSBnZW5lcmF0aW9uLicpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgcHViOiBrZXlzLnB1YixcbiAgICAgIHBydjoga2V5cy5wcnYsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHVibGljIGtleSBmb3IgdGhlIGNvaW4uXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwdWIgdGhlIHB1YiB0byBiZSBjaGVja2VkXG4gICAqIEByZXR1cm5zIHtCb29sZWFufSBpcyBpdCB2YWxpZD9cbiAgICovXG4gIGlzVmFsaWRQdWIocHViOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZG90VXRpbHMuaXNWYWxpZFB1YmxpY0tleShwdWIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0aGUgc3VwcGxpZWQgcHJpdmF0ZSBrZXkgaXMgYSB2YWxpZCBkb3QgcHJpdmF0ZSBrZXlcbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBydiB0aGUgcHJ2IHRvIGJlIGNoZWNrZWRcbiAgICogQHJldHVybnMge0Jvb2xlYW59IGlzIGl0IHZhbGlkP1xuICAgKi9cbiAgaXNWYWxpZFBydihwcnY6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBkb3RVdGlscy5pc1ZhbGlkUHJpdmF0ZUtleShwcnYpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciBpbnB1dCBpcyB2YWxpZCBwdWJsaWMga2V5IGZvciB0aGUgY29pblxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gYWRkcmVzcyB0aGUgcHViIHRvIGJlIGNoZWNrZWRcbiAgICogQHJldHVybnMge0Jvb2xlYW59IGlzIGl0IHZhbGlkP1xuICAgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGRvdFV0aWxzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNpZ24gbWVzc2FnZSB3aXRoIHByaXZhdGUga2V5XG4gICAqXG4gICAqIEBwYXJhbSBrZXlcbiAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICogQHJldHVybiB7QnVmZmVyfSBBIHNpZ25hdHVyZSBvdmVyIHRoZSBnaXZlbiBtZXNzYWdlIHVzaW5nIHRoZSBnaXZlbiBrZXlcbiAgICovXG4gIGFzeW5jIHNpZ25NZXNzYWdlKGtleTogS2V5UGFpciwgbWVzc2FnZTogc3RyaW5nIHwgQnVmZmVyKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICBjb25zdCBtc2cgPSBCdWZmZXIuaXNCdWZmZXIobWVzc2FnZSkgPyBtZXNzYWdlLnRvU3RyaW5nKCd1dGY4JykgOiBtZXNzYWdlO1xuICAgIC8vIHJlY29uc3RpdHV0ZSBrZXlzIGFuZCBzaWduXG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKG5ldyBEb3RLZXlQYWlyKHsgcHJ2OiBrZXkucHJ2IH0pLnNpZ25NZXNzYWdlKG1zZykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4cGxhaW4vcGFyc2UgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHVuc2lnbmVkVHJhbnNhY3Rpb25cbiAgICovXG4gIGFzeW5jIGV4cGxhaW5UcmFuc2FjdGlvbih1bnNpZ25lZFRyYW5zYWN0aW9uOiBVbnNpZ25lZFRyYW5zYWN0aW9uKTogUHJvbWlzZTxFeHBsYW5hdGlvblJlc3VsdD4ge1xuICAgIGxldCBvdXRwdXRBbW91bnQgPSAwO1xuICAgIHVuc2lnbmVkVHJhbnNhY3Rpb24ucGFyc2VkVHgub3V0cHV0cy5mb3JFYWNoKChvKSA9PiB7XG4gICAgICBvdXRwdXRBbW91bnQgKz0gcGFyc2VJbnQoby52YWx1ZVN0cmluZywgMTApO1xuICAgIH0pO1xuICAgIGNvbnN0IGV4cGxhbmF0aW9uUmVzdWx0OiBFeHBsYW5hdGlvblJlc3VsdCA9IHtcbiAgICAgIGRpc3BsYXlPcmRlcjogW1xuICAgICAgICAnb3V0cHV0QW1vdW50JyxcbiAgICAgICAgJ2NoYW5nZUFtb3VudCcsXG4gICAgICAgICdvdXRwdXRzJyxcbiAgICAgICAgJ2NoYW5nZU91dHB1dHMnLFxuICAgICAgICAnZmVlJyxcbiAgICAgICAgJ3R5cGUnLFxuICAgICAgICAnc2VxdWVuY2VJZCcsXG4gICAgICAgICdpZCcsXG4gICAgICAgICdibG9ja051bWJlcicsXG4gICAgICBdLFxuICAgICAgc2VxdWVuY2VJZDogdW5zaWduZWRUcmFuc2FjdGlvbi5wYXJzZWRUeC5zZXF1ZW5jZUlkLFxuICAgICAgZmVlOiB1bnNpZ25lZFRyYW5zYWN0aW9uLmZlZUluZm8/LmZlZVN0cmluZyxcbiAgICAgIGlkOiB1bnNpZ25lZFRyYW5zYWN0aW9uLnBhcnNlZFR4LmlkLFxuICAgICAgdHlwZTogdW5zaWduZWRUcmFuc2FjdGlvbi5wYXJzZWRUeC50eXBlLFxuICAgICAgb3V0cHV0czogdW5zaWduZWRUcmFuc2FjdGlvbi5wYXJzZWRUeC5vdXRwdXRzLFxuICAgICAgYmxvY2tOdW1iZXI6IHVuc2lnbmVkVHJhbnNhY3Rpb24uY29pblNwZWNpZmljPy5ibG9ja051bWJlcixcbiAgICAgIG91dHB1dEFtb3VudDogb3V0cHV0QW1vdW50LFxuICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICB9O1xuXG4gICAgcmV0dXJuIGV4cGxhbmF0aW9uUmVzdWx0O1xuICB9XG5cbiAgdmVyaWZ5U2lnblRyYW5zYWN0aW9uUGFyYW1zKHBhcmFtczogU2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFZlcmlmaWVkVHJhbnNhY3Rpb25QYXJhbWV0ZXJzIHtcbiAgICBjb25zdCBwcnYgPSBwYXJhbXMucHJ2O1xuXG4gICAgY29uc3QgdHhIZXggPSBwYXJhbXMudHhQcmVidWlsZC50eEhleDtcblxuICAgIGlmICghdHhIZXgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB0eFByZWJ1aWxkIHBhcmFtZXRlcicpO1xuICAgIH1cblxuICAgIGlmICghXy5pc1N0cmluZyh0eEhleCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdHhQcmVidWlsZCBtdXN0IGJlIGFuIG9iamVjdCwgZ290IHR5cGUgJHt0eXBlb2YgdHhIZXh9YCk7XG4gICAgfVxuXG4gICAgaWYgKCFwcnYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBwcnYgcGFyYW1ldGVyIHRvIHNpZ24gdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBpZiAoIV8uaXNTdHJpbmcocHJ2KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBwcnYgbXVzdCBiZSBhIHN0cmluZywgZ290IHR5cGUgJHt0eXBlb2YgcHJ2fWApO1xuICAgIH1cblxuICAgIGlmICghXy5oYXMocGFyYW1zLCAncHVicycpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcHVibGljIGtleSBwYXJhbWV0ZXIgdG8gc2lnbiB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIHJldHVybiB7IHR4SGV4LCBwcnYgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NlbWJsZSBrZXljaGFpbiBhbmQgaGFsZi1zaWduIHByZWJ1aWx0IHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICogQHBhcmFtIHBhcmFtcy50eFByZWJ1aWxkIHtUcmFuc2FjdGlvblByZWJ1aWxkfSBwcmVidWlsZCBvYmplY3QgcmV0dXJuZWQgYnkgcGxhdGZvcm1cbiAgICogQHBhcmFtIHBhcmFtcy5wcnYge1N0cmluZ30gdXNlciBwcnZcbiAgICogQHJldHVybnMge1Byb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+fVxuICAgKi9cbiAgYXN5bmMgc2lnblRyYW5zYWN0aW9uKHBhcmFtczogU2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCB7IHR4SGV4LCBwcnYgfSA9IHRoaXMudmVyaWZ5U2lnblRyYW5zYWN0aW9uUGFyYW1zKHBhcmFtcyk7XG4gICAgY29uc3QgZmFjdG9yeSA9IHRoaXMuZ2V0QnVpbGRlcigpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZnJvbSh0eEhleCk7XG4gICAgY29uc3Qga2V5UGFpciA9IG5ldyBEb3RLZXlQYWlyKHsgcHJ2OiBwcnYgfSk7XG4gICAgY29uc3QgeyByZWZlcmVuY2VCbG9jaywgYmxvY2tOdW1iZXIsIHRyYW5zYWN0aW9uVmVyc2lvbiwgc2VuZGVyIH0gPSBwYXJhbXMudHhQcmVidWlsZC50cmFuc2FjdGlvbjtcblxuICAgIHR4QnVpbGRlclxuICAgICAgLnZhbGlkaXR5KHsgZmlyc3RWYWxpZDogYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiB0aGlzLk1BWF9WQUxJRElUWV9EVVJBVElPTiB9KVxuICAgICAgLnJlZmVyZW5jZUJsb2NrKHJlZmVyZW5jZUJsb2NrKVxuICAgICAgLnZlcnNpb24odHJhbnNhY3Rpb25WZXJzaW9uKVxuICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IHNlbmRlciB9KVxuICAgICAgLnNpZ24oeyBrZXk6IGtleVBhaXIuZ2V0S2V5cygpLnBydiB9KTtcbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGlmICghdHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICBjb25zdCBzaWduZWRUeEhleCA9IHRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgcmV0dXJuIHsgdHhIZXg6IHNpZ25lZFR4SGV4IH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0SW5pdGlhbGl6ZWROb2RlQVBJKCk6IFByb21pc2U8QXBpUHJvbWlzZT4ge1xuICAgIGlmICghRG90Lm5vZGVBcGlJbml0aWFsaXplZCkge1xuICAgICAgY29uc3Qgd3NQcm92aWRlciA9IG5ldyBXc1Byb3ZpZGVyKEVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS5kb3ROb2RlVXJscyk7XG4gICAgICBEb3QuQVBJID0gYXdhaXQgQXBpUHJvbWlzZS5jcmVhdGUoeyBwcm92aWRlcjogd3NQcm92aWRlciB9KTtcbiAgICAgIERvdC5ub2RlQXBpSW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gRG90LkFQSTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBnZXRBY2NvdW50SW5mbyh3YWxsZXRBZGRyOiBzdHJpbmcpOiBQcm9taXNlPHsgbm9uY2U6IG51bWJlcjsgZnJlZUJhbGFuY2U6IG51bWJlciB9PiB7XG4gICAgY29uc3QgYXBpID0gYXdhaXQgdGhpcy5nZXRJbml0aWFsaXplZE5vZGVBUEkoKTtcbiAgICBjb25zdCB7IG5vbmNlLCBkYXRhOiBiYWxhbmNlIH0gPSBhd2FpdCBhcGkucXVlcnkuc3lzdGVtLmFjY291bnQod2FsbGV0QWRkcik7XG4gICAgcmV0dXJuIHsgbm9uY2U6IG5vbmNlLnRvTnVtYmVyKCksIGZyZWVCYWxhbmNlOiBiYWxhbmNlLmZyZWUudG9OdW1iZXIoKSB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEhlYWRlckluZm8oKTogUHJvbWlzZTx7IGhlYWRlck51bWJlcjogbnVtYmVyOyBoZWFkZXJIYXNoOiBzdHJpbmcgfT4ge1xuICAgIGNvbnN0IGFwaSA9IGF3YWl0IHRoaXMuZ2V0SW5pdGlhbGl6ZWROb2RlQVBJKCk7XG4gICAgY29uc3QgeyBudW1iZXIsIGhhc2ggfSA9IGF3YWl0IGFwaS5ycGMuY2hhaW4uZ2V0SGVhZGVyKCk7XG4gICAgcmV0dXJuIHsgaGVhZGVyTnVtYmVyOiBudW1iZXIudG9OdW1iZXIoKSwgaGVhZGVySGFzaDogaGFzaC50b1N0cmluZygpIH07XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogRXN0aW1hdGUgdGhlIGZlZSBvZiB0aGUgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGRlc3RBZGRyIGRlc3RpbmF0aW9uIHdhbGxldCBhZGRyZXNzXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzcmNBZGRyIHNvdXJjZSB3YWxsZXQgYWRkcmVzc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gYW1vdW50IGFtb3VudCB0byB0cmFuc2ZlclxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSB0aGUgZXN0aW1hdGVkIGZlZSB0aGUgdHJhbnNhY3Rpb24gd2lsbCBjb3N0XG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9wb2xrYWRvdC5qcy5vcmcvZG9jcy9hcGkvY29va2Jvb2svdHgjaG93LWRvLWktZXN0aW1hdGUtdGhlLXRyYW5zYWN0aW9uLWZlZXNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBnZXRGZWUoZGVzdEFkZHI6IHN0cmluZywgc3JjQWRkcjogc3RyaW5nLCBhbW91bnQ6IG51bWJlcik6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgYXBpID0gYXdhaXQgdGhpcy5nZXRJbml0aWFsaXplZE5vZGVBUEkoKTtcbiAgICBjb25zdCBpbmZvID0gYXdhaXQgYXBpLnR4LmJhbGFuY2VzLnRyYW5zZmVyQWxsb3dEZWF0aChkZXN0QWRkciwgYW1vdW50KS5wYXltZW50SW5mbyhzcmNBZGRyKTtcbiAgICByZXR1cm4gaW5mby5wYXJ0aWFsRmVlLnRvTnVtYmVyKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZ2V0TWF0ZXJpYWwoKTogUHJvbWlzZTxNYXRlcmlhbD4ge1xuICAgIGNvbnN0IGFwaSA9IGF3YWl0IHRoaXMuZ2V0SW5pdGlhbGl6ZWROb2RlQVBJKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGdlbmVzaXNIYXNoOiBhcGkuZ2VuZXNpc0hhc2gudG9TdHJpbmcoKSxcbiAgICAgIGNoYWluTmFtZTogYXBpLnJ1bnRpbWVDaGFpbi50b1N0cmluZygpLFxuICAgICAgc3BlY05hbWU6IGFwaS5ydW50aW1lVmVyc2lvbi5zcGVjTmFtZS50b1N0cmluZygpIGFzIFBvbGthZG90U3BlY05hbWVUeXBlLFxuICAgICAgc3BlY1ZlcnNpb246IGFwaS5ydW50aW1lVmVyc2lvbi5zcGVjVmVyc2lvbi50b051bWJlcigpLFxuICAgICAgdHhWZXJzaW9uOiBhcGkucnVudGltZVZlcnNpb24udHJhbnNhY3Rpb25WZXJzaW9uLnRvTnVtYmVyKCksXG4gICAgICBtZXRhZGF0YTogYXBpLnJ1bnRpbWVNZXRhZGF0YS50b0hleCgpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgZnVuZHMgcmVjb3ZlcnkgdHJhbnNhY3Rpb24gd2l0aG91dCBCaXRHb1xuICAgKiBAcGFyYW0ge01QQ1JlY292ZXJ5T3B0aW9uc30gcGFyYW1zIHBhcmFtZXRlcnMgbmVlZGVkIHRvIGNvbnN0cnVjdCBhbmRcbiAgICogKG1heWJlKSBzaWduIHRoZSB0cmFuc2FjdGlvblxuICAgKlxuICAgKiBAcmV0dXJucyB7TVBDVHh9IHRoZSBzZXJpYWxpemVkIHRyYW5zYWN0aW9uIGhleCBzdHJpbmcgYW5kIGluZGV4XG4gICAqIG9mIHRoZSBhZGRyZXNzIGJlaW5nIHN3ZXB0XG4gICAqL1xuICBhc3luYyByZWNvdmVyKHBhcmFtczogTVBDUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxNUENUeCB8IE1QQ1N3ZWVwVHhzPiB7XG4gICAgaWYgKCFwYXJhbXMuYml0Z29LZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiaXRnb0tleScpO1xuICAgIH1cbiAgICBpZiAoIXBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24nKTtcbiAgICB9XG5cbiAgICBjb25zdCBiaXRnb0tleSA9IHBhcmFtcy5iaXRnb0tleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9ICFwYXJhbXMudXNlcktleSAmJiAhcGFyYW1zLmJhY2t1cEtleSAmJiAhcGFyYW1zLndhbGxldFBhc3NwaHJhc2U7XG5cbiAgICBjb25zdCBNUEMgPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpO1xuXG4gICAgY29uc3QgaW5kZXggPSBwYXJhbXMuaW5kZXggfHwgMDtcbiAgICBjb25zdCBjdXJyUGF0aCA9IHBhcmFtcy5zZWVkID8gZ2V0RGVyaXZhdGlvblBhdGgocGFyYW1zLnNlZWQpICsgYC8ke2luZGV4fWAgOiBgbS8ke2luZGV4fWA7XG4gICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoYml0Z29LZXksIGN1cnJQYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgY29uc3Qgc2VuZGVyQWRkciA9IHRoaXMuZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkoYWNjb3VudElkKTtcblxuICAgIGNvbnN0IHsgbm9uY2UsIGZyZWVCYWxhbmNlIH0gPSBhd2FpdCB0aGlzLmdldEFjY291bnRJbmZvKHNlbmRlckFkZHIpO1xuICAgIGNvbnN0IGRlc3RBZGRyID0gcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb247XG4gICAgY29uc3QgYW1vdW50ID0gZnJlZUJhbGFuY2U7XG4gICAgY29uc3QgcGFydGlhbEZlZSA9IGF3YWl0IHRoaXMuZ2V0RmVlKGRlc3RBZGRyLCBzZW5kZXJBZGRyLCBhbW91bnQpO1xuXG4gICAgY29uc3QgdmFsdWUgPSBuZXcgQmlnTnVtYmVyKGZyZWVCYWxhbmNlKS5taW51cyhuZXcgQmlnTnVtYmVyKHBhcnRpYWxGZWUpKTtcbiAgICBpZiAodmFsdWUuaXNMZXNzVGhhbk9yRXF1YWxUbygwKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWQgbm90IGZpbmQgYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICB9XG5cbiAgICAvLyBmaXJzdCBidWlsZCB0aGUgdW5zaWduZWQgdHhuXG4gICAgY29uc3QgeyBoZWFkZXJOdW1iZXIsIGhlYWRlckhhc2ggfSA9IGF3YWl0IHRoaXMuZ2V0SGVhZGVySW5mbygpO1xuICAgIGNvbnN0IG1hdGVyaWFsID0gYXdhaXQgdGhpcy5nZXRNYXRlcmlhbCgpO1xuICAgIGNvbnN0IHZhbGlkaXR5V2luZG93ID0geyBmaXJzdFZhbGlkOiBoZWFkZXJOdW1iZXIsIG1heER1cmF0aW9uOiB0aGlzLk1BWF9WQUxJRElUWV9EVVJBVElPTiB9O1xuXG4gICAgY29uc3QgdHhuQnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpLmdldFRyYW5zZmVyQnVpbGRlcigpLm1hdGVyaWFsKG1hdGVyaWFsKTtcbiAgICB0eG5CdWlsZGVyXG4gICAgICAuc3dlZXAoZmFsc2UpXG4gICAgICAudG8oeyBhZGRyZXNzOiBwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB9KVxuICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IHNlbmRlckFkZHIgfSlcbiAgICAgIC52YWxpZGl0eSh2YWxpZGl0eVdpbmRvdylcbiAgICAgIC5yZWZlcmVuY2VCbG9jayhoZWFkZXJIYXNoKVxuICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogbm9uY2UgfSlcbiAgICAgIC5mZWUoeyBhbW91bnQ6IDAsIHR5cGU6ICd0aXAnIH0pO1xuICAgIGNvbnN0IHVuc2lnbmVkVHJhbnNhY3Rpb24gPSAoYXdhaXQgdHhuQnVpbGRlci5idWlsZCgpKSBhcyBUcmFuc2FjdGlvbjtcblxuICAgIGxldCBzZXJpYWxpemVkVHggPSB1bnNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgaWYgKCFpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIGlmICghcGFyYW1zLnVzZXJLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHVzZXJLZXknKTtcbiAgICAgIH1cbiAgICAgIGlmICghcGFyYW1zLmJhY2t1cEtleSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgYmFja3VwS2V5Jyk7XG4gICAgICB9XG4gICAgICBpZiAoIXBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB3YWxsZXQgcGFzc3BocmFzZScpO1xuICAgICAgfVxuXG4gICAgICAvLyBDbGVhbiB1cCB3aGl0ZXNwYWNlIGZyb20gZW50ZXJlZCB2YWx1ZXNcbiAgICAgIGNvbnN0IHVzZXJLZXkgPSBwYXJhbXMudXNlcktleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgICAgY29uc3QgYmFja3VwS2V5ID0gcGFyYW1zLmJhY2t1cEtleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuXG4gICAgICAvLyBEZWNyeXB0IHByaXZhdGUga2V5cyBmcm9tIEtleUNhcmQgdmFsdWVzXG4gICAgICBsZXQgdXNlclBydjtcbiAgICAgIHRyeSB7XG4gICAgICAgIHVzZXJQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIGlucHV0OiB1c2VyS2V5LFxuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICAgIC8qKiBUT0RPIEJHLTUyNDE5IEltcGxlbWVudCBDb2RlYyBmb3IgcGFyc2luZyAqL1xuICAgICAgY29uc3QgdXNlclNpZ25pbmdNYXRlcmlhbCA9IEpTT04ucGFyc2UodXNlclBydikgYXMgRUREU0FNZXRob2RUeXBlcy5Vc2VyU2lnbmluZ01hdGVyaWFsO1xuXG4gICAgICBsZXQgYmFja3VwUHJ2O1xuICAgICAgdHJ5IHtcbiAgICAgICAgYmFja3VwUHJ2ID0gdGhpcy5iaXRnby5kZWNyeXB0KHtcbiAgICAgICAgICBpbnB1dDogYmFja3VwS2V5LFxuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyBiYWNrdXAga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgYmFja3VwU2lnbmluZ01hdGVyaWFsID0gSlNPTi5wYXJzZShiYWNrdXBQcnYpIGFzIEVERFNBTWV0aG9kVHlwZXMuQmFja3VwU2lnbmluZ01hdGVyaWFsO1xuXG4gICAgICAvLyBhZGQgc2lnbmF0dXJlXG4gICAgICBjb25zdCBzaWduYXR1cmVIZXggPSBhd2FpdCBFRERTQU1ldGhvZHMuZ2V0VFNTU2lnbmF0dXJlKFxuICAgICAgICB1c2VyU2lnbmluZ01hdGVyaWFsLFxuICAgICAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwsXG4gICAgICAgIGN1cnJQYXRoLFxuICAgICAgICB1bnNpZ25lZFRyYW5zYWN0aW9uXG4gICAgICApO1xuICAgICAgY29uc3QgZG90S2V5UGFpciA9IG5ldyBEb3RLZXlQYWlyKHsgcHViOiBhY2NvdW50SWQgfSk7XG4gICAgICB0eG5CdWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogZG90S2V5UGFpci5nZXRLZXlzKCkucHViIH0sIHNpZ25hdHVyZUhleCk7XG4gICAgICBjb25zdCBzaWduZWRUcmFuc2FjdGlvbiA9IGF3YWl0IHR4bkJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNlcmlhbGl6ZWRUeCA9IHNpZ25lZFRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gbmV3IEJpZ051bWJlcihmcmVlQmFsYW5jZSk7XG4gICAgICBjb25zdCB3YWxsZXRDb2luID0gdGhpcy5nZXRDaGFpbigpO1xuICAgICAgY29uc3QgaW5wdXRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogdW5zaWduZWRUcmFuc2FjdGlvbi5pbnB1dHNbMF0uYWRkcmVzcyxcbiAgICAgICAgICB2YWx1ZVN0cmluZzogdmFsdWUudG9TdHJpbmcoKSxcbiAgICAgICAgICB2YWx1ZTogdmFsdWUudG9OdW1iZXIoKSxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCBvdXRwdXRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogdW5zaWduZWRUcmFuc2FjdGlvbi5vdXRwdXRzWzBdLmFkZHJlc3MsXG4gICAgICAgICAgdmFsdWVTdHJpbmc6IHZhbHVlLnRvU3RyaW5nKCksXG4gICAgICAgICAgY29pbk5hbWU6IHdhbGxldENvaW4sXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgY29uc3Qgc3BlbmRBbW91bnQgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgY29uc3QgcGFyc2VkVHggPSB7IGlucHV0czogaW5wdXRzLCBvdXRwdXRzOiBvdXRwdXRzLCBzcGVuZEFtb3VudDogc3BlbmRBbW91bnQsIHR5cGU6ICcnIH07XG4gICAgICBjb25zdCBmZWVJbmZvID0geyBmZWU6IDAsIGZlZVN0cmluZzogJzAnIH07XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbjogTVBDVHggPSB7XG4gICAgICAgIHNlcmlhbGl6ZWRUeDogc2VyaWFsaXplZFR4LFxuICAgICAgICBzY2FuSW5kZXg6IGluZGV4LFxuICAgICAgICBjb2luOiB3YWxsZXRDb2luLFxuICAgICAgICBzaWduYWJsZUhleDogdW5zaWduZWRUcmFuc2FjdGlvbi5zaWduYWJsZVBheWxvYWQudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBkZXJpdmF0aW9uUGF0aDogY3VyclBhdGgsXG4gICAgICAgIHBhcnNlZFR4OiBwYXJzZWRUeCxcbiAgICAgICAgZmVlSW5mbzogZmVlSW5mbyxcbiAgICAgICAgY29pblNwZWNpZmljOiB7IC4uLnZhbGlkaXR5V2luZG93LCBjb21tb25LZXljaGFpbjogYml0Z29LZXkgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHVuc2lnbmVkVHg6IE1QQ1Vuc2lnbmVkVHggPSB7IHVuc2lnbmVkVHg6IHRyYW5zYWN0aW9uLCBzaWduYXR1cmVTaGFyZXM6IFtdIH07XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbnM6IE1QQ1Vuc2lnbmVkVHhbXSA9IFt1bnNpZ25lZFR4XTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdDogUmVjb3ZlcnlUeFJlcXVlc3QgPSB7XG4gICAgICAgIHRyYW5zYWN0aW9uczogdHJhbnNhY3Rpb25zLFxuICAgICAgICB3YWxsZXRDb2luOiB3YWxsZXRDb2luLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdHM6IE1QQ1N3ZWVwVHhzID0geyB0eFJlcXVlc3RzOiBbdHhSZXF1ZXN0XSB9O1xuICAgICAgcmV0dXJuIHR4UmVxdWVzdHM7XG4gICAgfVxuICAgIGNvbnN0IHRyYW5zYWN0aW9uOiBNUENUeCA9IHsgc2VyaWFsaXplZFR4OiBzZXJpYWxpemVkVHgsIHNjYW5JbmRleDogaW5kZXggfTtcbiAgICByZXR1cm4gdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIG5hdGl2ZSBET1QgcmVjb3ZlcmllcyBvZiByZWNlaXZlIGFkZHJlc3NlcyBpbiBiYXRjaCB3aXRob3V0IEJpdEdvLlxuICAgKiBGdW5kcyB3aWxsIGJlIHJlY292ZXJlZCB0byBiYXNlIGFkZHJlc3MgZmlyc3QuIFlvdSBuZWVkIHRvIGluaXRpYXRlIGFub3RoZXIgc3dlZXAgdHhuIGFmdGVyIHRoYXQuXG4gICAqXG4gICAqIEBwYXJhbSB7TVBDQ29uc29saWRhdGlvblJlY292ZXJ5T3B0aW9uc30gcGFyYW1zIC0gb3B0aW9ucyBmb3IgY29uc29saWRhdGlvbiByZWNvdmVyeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXJhbXMuc3RhcnRpbmdTY2FuSW5kZXhdIC0gcmVjZWl2ZSBhZGRyZXNzIGluZGV4IHRvIHN0YXJ0IHNjYW5uaW5nIGZyb20uIGRlZmF1bHQgdG8gMSAoaW5jbHVzaXZlKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtwYXJhbXMuZW5kaW5nU2NhbkluZGV4XSAtIHJlY2VpdmUgYWRkcmVzcyBpbmRleCB0byBlbmQgc2Nhbm5pbmcgYXQuIGRlZmF1bHQgdG8gc3RhcnRpbmdTY2FuSW5kZXggKyAyMCAoZXhjbHVzaXZlKS5cbiAgICovXG4gIGFzeW5jIHJlY292ZXJDb25zb2xpZGF0aW9ucyhwYXJhbXM6IE1QQ0NvbnNvbGlkYXRpb25SZWNvdmVyeU9wdGlvbnMpOiBQcm9taXNlPE1QQ1R4cyB8IE1QQ1N3ZWVwVHhzPiB7XG4gICAgY29uc3QgaXNVbnNpZ25lZFN3ZWVwID0gIXBhcmFtcy51c2VyS2V5ICYmICFwYXJhbXMuYmFja3VwS2V5ICYmICFwYXJhbXMud2FsbGV0UGFzc3BocmFzZTtcbiAgICBjb25zdCBzdGFydElkeCA9IHBhcmFtcy5zdGFydGluZ1NjYW5JbmRleCB8fCAxO1xuICAgIGNvbnN0IGVuZElkeCA9IHBhcmFtcy5lbmRpbmdTY2FuSW5kZXggfHwgc3RhcnRJZHggKyBERUZBVUxUX1NDQU5fRkFDVE9SO1xuXG4gICAgaWYgKHN0YXJ0SWR4IDwgMSB8fCBlbmRJZHggPD0gc3RhcnRJZHggfHwgZW5kSWR4IC0gc3RhcnRJZHggPiAxMCAqIERFRkFVTFRfU0NBTl9GQUNUT1IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEludmFsaWQgc3RhcnRpbmcgb3IgZW5kaW5nIGluZGV4IHRvIHNjYW4gZm9yIGFkZHJlc3Nlcy4gc3RhcnRpbmdTY2FuSW5kZXg6ICR7c3RhcnRJZHh9LCBlbmRpbmdTY2FuSW5kZXg6ICR7ZW5kSWR4fS5gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGJpdGdvS2V5ID0gcGFyYW1zLmJpdGdvS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgY29uc3QgTVBDID0gYXdhaXQgRUREU0FNZXRob2RzLmdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICBjb25zdCBiYXNlSW5kZXggPSAwO1xuICAgIGNvbnN0IGJhc2VQYXRoID0gcGFyYW1zLnNlZWQgPyBnZXREZXJpdmF0aW9uUGF0aChwYXJhbXMuc2VlZCkgKyBgLyR7YmFzZUluZGV4fWAgOiBgbS8ke2Jhc2VJbmRleH1gO1xuICAgIGNvbnN0IGFjY291bnRJZCA9IE1QQy5kZXJpdmVVbmhhcmRlbmVkKGJpdGdvS2V5LCBiYXNlUGF0aCkuc2xpY2UoMCwgNjQpO1xuICAgIGNvbnN0IGJhc2VBZGRyZXNzID0gdGhpcy5nZXRBZGRyZXNzRnJvbVB1YmxpY0tleShhY2NvdW50SWQpO1xuXG4gICAgY29uc3QgY29uc29saWRhdGlvblRyYW5zYWN0aW9uczogYW55W10gPSBbXTtcbiAgICBsZXQgbGFzdFNjYW5JbmRleCA9IHN0YXJ0SWR4O1xuICAgIGZvciAobGV0IGkgPSBzdGFydElkeDsgaSA8IGVuZElkeDsgaSsrKSB7XG4gICAgICBjb25zdCByZWNvdmVyUGFyYW1zID0ge1xuICAgICAgICB1c2VyS2V5OiBwYXJhbXMudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBwYXJhbXMuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogcGFyYW1zLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogYmFzZUFkZHJlc3MsXG4gICAgICAgIHNlZWQ6IHBhcmFtcy5zZWVkLFxuICAgICAgICBpbmRleDogaSxcbiAgICAgIH07XG5cbiAgICAgIGxldCByZWNvdmVyeVRyYW5zYWN0aW9uO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVjb3ZlcnlUcmFuc2FjdGlvbiA9IGF3YWl0IHRoaXMucmVjb3ZlcihyZWNvdmVyUGFyYW1zKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGUubWVzc2FnZSA9PT0gJ0RpZCBub3QgZmluZCBhZGRyZXNzIHdpdGggZnVuZHMgdG8gcmVjb3ZlcicpIHtcbiAgICAgICAgICBsYXN0U2NhbkluZGV4ID0gaTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICAgIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnMucHVzaCgocmVjb3ZlcnlUcmFuc2FjdGlvbiBhcyBNUENTd2VlcFR4cykudHhSZXF1ZXN0c1swXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLnB1c2gocmVjb3ZlcnlUcmFuc2FjdGlvbik7XG4gICAgICB9XG4gICAgICBsYXN0U2NhbkluZGV4ID0gaTtcbiAgICB9XG5cbiAgICBpZiAoY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXInKTtcbiAgICB9XG5cbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICAvLyBsYXN0U2NhbkluZGV4IHdpbGwgYmUgdXNlZCB0byBpbmZvcm0gdXNlciB0aGUgbGFzdCBhZGRyZXNzIGluZGV4IHNjYW5uZWQgZm9yIGF2YWlsYWJsZSBmdW5kcyAoc28gdGhleSBjYW5cbiAgICAgIC8vIGFwcHJvcHJpYXRlbHkgYWRqdXN0IHRoZSBzY2FuIHJhbmdlIG9uIHRoZSBuZXh0IGl0ZXJhdGlvbiBvZiBjb25zb2xpZGF0aW9uIHJlY292ZXJpZXMpLiBJbiB0aGUgY2FzZSBvZiB1bnNpZ25lZFxuICAgICAgLy8gc3dlZXAgY29uc29saWRhdGlvbnMsIHRoaXMgbGFzdFNjYW5JbmRleCB3aWxsIGJlIHByb3ZpZGVkIGluIHRoZSBjb2luU3BlY2lmaWMgb2YgdGhlIGxhc3QgdHhuIG1hZGUuXG4gICAgICBjb25zdCBsYXN0VHJhbnNhY3Rpb25Db2luU3BlY2lmaWMgPSB7XG4gICAgICAgIGZpcnN0VmFsaWQ6XG4gICAgICAgICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9uc1tjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLmxlbmd0aCAtIDFdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmNvaW5TcGVjaWZpY1xuICAgICAgICAgICAgLmZpcnN0VmFsaWQsXG4gICAgICAgIG1heER1cmF0aW9uOlxuICAgICAgICAgIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnNbY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5sZW5ndGggLSAxXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWNcbiAgICAgICAgICAgIC5tYXhEdXJhdGlvbixcbiAgICAgICAgY29tbW9uS2V5Y2hhaW46XG4gICAgICAgICAgY29uc29saWRhdGlvblRyYW5zYWN0aW9uc1tjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zLmxlbmd0aCAtIDFdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LmNvaW5TcGVjaWZpY1xuICAgICAgICAgICAgLmNvbW1vbktleWNoYWluLFxuICAgICAgICBsYXN0U2NhbkluZGV4OiBsYXN0U2NhbkluZGV4LFxuICAgICAgfTtcbiAgICAgIGNvbnNvbGlkYXRpb25UcmFuc2FjdGlvbnNbY29uc29saWRhdGlvblRyYW5zYWN0aW9ucy5sZW5ndGggLSAxXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5jb2luU3BlY2lmaWMgPVxuICAgICAgICBsYXN0VHJhbnNhY3Rpb25Db2luU3BlY2lmaWM7XG4gICAgICBjb25zdCBjb25zb2xpZGF0aW9uU3dlZXBUcmFuc2FjdGlvbnM6IE1QQ1N3ZWVwVHhzID0geyB0eFJlcXVlc3RzOiBjb25zb2xpZGF0aW9uVHJhbnNhY3Rpb25zIH07XG4gICAgICByZXR1cm4gY29uc29saWRhdGlvblN3ZWVwVHJhbnNhY3Rpb25zO1xuICAgIH1cblxuICAgIHJldHVybiB7IHRyYW5zYWN0aW9uczogY29uc29saWRhdGlvblRyYW5zYWN0aW9ucywgbGFzdFNjYW5JbmRleCB9O1xuICB9XG5cbiAgLyoqIGluaGVyaXRlZCBkb2MgKi9cbiAgYXN5bmMgY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24ocGFyYW1zOiBNUENTd2VlcFJlY292ZXJ5T3B0aW9ucyk6IFByb21pc2U8TVBDVHhzPiB7XG4gICAgY29uc3QgcmVxID0gcGFyYW1zLnNpZ25hdHVyZVNoYXJlcztcbiAgICBjb25zdCBicm9hZGNhc3RhYmxlVHJhbnNhY3Rpb25zOiBNUENUeFtdID0gW107XG4gICAgbGV0IGxhc3RTY2FuSW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IE1QQyA9IGF3YWl0IEVERFNBTWV0aG9kcy5nZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHJlcVtpXS50eFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICBpZiAoIXJlcVtpXS5vdmMgfHwgIXJlcVtpXS5vdmNbMF0uZWRkc2FTaWduYXR1cmUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHNpZ25hdHVyZShzKScpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gcmVxW2ldLm92Y1swXS5lZGRzYVNpZ25hdHVyZTtcbiAgICAgIGlmICghdHJhbnNhY3Rpb24uc2lnbmFibGVIZXgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHNpZ25hYmxlIGhleCcpO1xuICAgICAgfVxuICAgICAgY29uc3QgbWVzc2FnZUJ1ZmZlciA9IEJ1ZmZlci5mcm9tKHRyYW5zYWN0aW9uLnNpZ25hYmxlSGV4ISwgJ2hleCcpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gTVBDLnZlcmlmeShtZXNzYWdlQnVmZmVyLCBzaWduYXR1cmUpO1xuICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpZ25hdHVyZScpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2lnbmF0dXJlSGV4ID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oc2lnbmF0dXJlLlIsICdoZXgnKSwgQnVmZmVyLmZyb20oc2lnbmF0dXJlLnNpZ21hLCAnaGV4JyldKTtcbiAgICAgIGlmIChcbiAgICAgICAgIXRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYyB8fFxuICAgICAgICAhdHJhbnNhY3Rpb24uY29pblNwZWNpZmljPy5maXJzdFZhbGlkIHx8XG4gICAgICAgICF0cmFuc2FjdGlvbi5jb2luU3BlY2lmaWM/Lm1heER1cmF0aW9uXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHZhbGlkaXR5IHdpbmRvdycpO1xuICAgICAgfVxuICAgICAgY29uc3QgdmFsaWRpdHlXaW5kb3cgPSB7XG4gICAgICAgIGZpcnN0VmFsaWQ6IHRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYz8uZmlyc3RWYWxpZCxcbiAgICAgICAgbWF4RHVyYXRpb246IHRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYz8ubWF4RHVyYXRpb24sXG4gICAgICB9O1xuICAgICAgY29uc3QgbWF0ZXJpYWwgPSBhd2FpdCB0aGlzLmdldE1hdGVyaWFsKCk7XG4gICAgICBpZiAoIXRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYz8uY29tbW9uS2V5Y2hhaW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGNvbW1vbiBrZXljaGFpbicpO1xuICAgICAgfVxuICAgICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPSB0cmFuc2FjdGlvbi5jb2luU3BlY2lmaWMhLmNvbW1vbktleWNoYWluISBhcyBzdHJpbmc7XG4gICAgICBpZiAoIXRyYW5zYWN0aW9uLmRlcml2YXRpb25QYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBkZXJpdmF0aW9uIHBhdGgnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gdHJhbnNhY3Rpb24uZGVyaXZhdGlvblBhdGggYXMgc3RyaW5nO1xuICAgICAgY29uc3QgYWNjb3VudElkID0gTVBDLmRlcml2ZVVuaGFyZGVuZWQoY29tbW9uS2V5Y2hhaW4sIGRlcml2YXRpb25QYXRoKS5zbGljZSgwLCA2NCk7XG4gICAgICBjb25zdCBzZW5kZXJBZGRyID0gdGhpcy5nZXRBZGRyZXNzRnJvbVB1YmxpY0tleShhY2NvdW50SWQpO1xuICAgICAgY29uc3QgdHhuQnVpbGRlciA9IHRoaXMuZ2V0QnVpbGRlcigpXG4gICAgICAgIC5tYXRlcmlhbChtYXRlcmlhbClcbiAgICAgICAgLmZyb20odHJhbnNhY3Rpb24uc2VyaWFsaXplZFR4IGFzIHN0cmluZylcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IHNlbmRlckFkZHIgfSlcbiAgICAgICAgLnZhbGlkaXR5KHZhbGlkaXR5V2luZG93KTtcbiAgICAgIGNvbnN0IGRvdEtleVBhaXIgPSBuZXcgRG90S2V5UGFpcih7IHB1YjogYWNjb3VudElkIH0pO1xuICAgICAgdHhuQnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IGRvdEtleVBhaXIuZ2V0S2V5cygpLnB1YiB9LCBzaWduYXR1cmVIZXgpO1xuICAgICAgY29uc3Qgc2lnbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCB0eG5CdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBzZXJpYWxpemVkVHggPSBzaWduZWRUcmFuc2FjdGlvbi50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBicm9hZGNhc3RhYmxlVHJhbnNhY3Rpb25zLnB1c2goe1xuICAgICAgICBzZXJpYWxpemVkVHg6IHNlcmlhbGl6ZWRUeCxcbiAgICAgICAgc2NhbkluZGV4OiB0cmFuc2FjdGlvbi5zY2FuSW5kZXgsXG4gICAgICB9KTtcblxuICAgICAgaWYgKGkgPT09IHJlcS5sZW5ndGggLSAxICYmIHRyYW5zYWN0aW9uLmNvaW5TcGVjaWZpYyEubGFzdFNjYW5JbmRleCkge1xuICAgICAgICBsYXN0U2NhbkluZGV4ID0gdHJhbnNhY3Rpb24uY29pblNwZWNpZmljIS5sYXN0U2NhbkluZGV4IGFzIG51bWJlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHsgdHJhbnNhY3Rpb25zOiBicm9hZGNhc3RhYmxlVHJhbnNhY3Rpb25zLCBsYXN0U2NhbkluZGV4IH07XG4gIH1cblxuICBhc3luYyBwYXJzZVRyYW5zYWN0aW9uKHBhcmFtczogUGFyc2VUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFBhcnNlZFRyYW5zYWN0aW9uPiB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgYXN5bmMgaXNXYWxsZXRBZGRyZXNzKHBhcmFtczogVmVyaWZ5QWRkcmVzc09wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0aHJvdyBuZXcgTWV0aG9kTm90SW1wbGVtZW50ZWRFcnJvcigpO1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IHR4UGFyYW1zIH0gPSBwYXJhbXM7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodHhQYXJhbXMucmVjaXBpZW50cykgJiYgdHhQYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke3RoaXMuZ2V0Q2hhaW4oKX0gZG9lc24ndCBzdXBwb3J0IHNlbmRpbmcgdG8gbW9yZSB0aGFuIDEgZGVzdGluYXRpb24gYWRkcmVzcyB3aXRoaW4gYSBzaW5nbGUgdHJhbnNhY3Rpb24uIFRyeSBhZ2FpbiwgdXNpbmcgb25seSBhIHNpbmdsZSByZWNpcGllbnQuYFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBnZXRBZGRyZXNzRnJvbVB1YmxpY0tleShQdWJrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIG5ldyBEb3RLZXlQYWlyKHsgcHViOiBQdWJrZXkgfSkuZ2V0QWRkcmVzcyhVdGlscy5kZWZhdWx0LmdldEFkZHJlc3NGb3JtYXQodGhpcy5nZXRDaGFpbigpIGFzIERvdEFzc2V0VHlwZXMpKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QnVpbGRlcigpOiBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5IHtcbiAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KHRoaXMuZ2V0Q2hhaW4oKSkpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGF1ZGl0RGVjcnlwdGVkS2V5KHsgcHVibGljS2V5LCBwcnYsIG11bHRpU2lnVHlwZSB9OiBBdWRpdERlY3J5cHRlZEtleVBhcmFtcykge1xuICAgIGlmIChtdWx0aVNpZ1R5cGUgIT09ICd0c3MnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIG11bHRpU2lnVHlwZScpO1xuICAgIH1cbiAgICBhdWRpdEVkZHNhUHJpdmF0ZUtleShwcnYsIHB1YmxpY0tleSA/PyAnJyk7XG4gIH1cbn1cbiJdfQ==
|