@bitgo-beta/abstract-utxo 1.6.1-alpha.23 → 1.6.1-alpha.230

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +853 -0
  2. package/dist/src/abstractUtxoCoin.d.ts +146 -34
  3. package/dist/src/abstractUtxoCoin.d.ts.map +1 -1
  4. package/dist/src/abstractUtxoCoin.js +350 -187
  5. package/dist/src/descriptor/NamedDescriptor.d.ts +7 -0
  6. package/dist/src/descriptor/NamedDescriptor.d.ts.map +1 -0
  7. package/dist/src/descriptor/NamedDescriptor.js +9 -0
  8. package/dist/src/descriptor/assertDescriptorWalletAddress.d.ts +4 -0
  9. package/dist/src/descriptor/assertDescriptorWalletAddress.d.ts.map +1 -0
  10. package/dist/src/descriptor/assertDescriptorWalletAddress.js +37 -0
  11. package/dist/src/descriptor/index.d.ts +4 -0
  12. package/dist/src/descriptor/index.d.ts.map +1 -0
  13. package/dist/src/descriptor/index.js +11 -0
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +8 -2
  17. package/dist/src/parseOutput.d.ts.map +1 -1
  18. package/dist/src/parseOutput.js +38 -1
  19. package/dist/src/recovery/RecoveryProvider.d.ts +1 -1
  20. package/dist/src/recovery/RecoveryProvider.d.ts.map +1 -1
  21. package/dist/src/recovery/RecoveryProvider.js +1 -2
  22. package/dist/src/recovery/backupKeyRecovery.d.ts +39 -11
  23. package/dist/src/recovery/backupKeyRecovery.d.ts.map +1 -1
  24. package/dist/src/recovery/backupKeyRecovery.js +124 -83
  25. package/dist/src/recovery/baseApi.d.ts +2 -2
  26. package/dist/src/recovery/baseApi.d.ts.map +1 -1
  27. package/dist/src/recovery/crossChainRecovery.d.ts +12 -3
  28. package/dist/src/recovery/crossChainRecovery.d.ts.map +1 -1
  29. package/dist/src/recovery/crossChainRecovery.js +50 -10
  30. package/dist/src/recovery/index.d.ts +0 -1
  31. package/dist/src/recovery/index.d.ts.map +1 -1
  32. package/dist/src/recovery/index.js +6 -3
  33. package/dist/src/recovery/mempoolApi.d.ts.map +1 -1
  34. package/dist/src/recovery/mempoolApi.js +6 -3
  35. package/dist/src/sign.d.ts +29 -5
  36. package/dist/src/sign.d.ts.map +1 -1
  37. package/dist/src/sign.js +73 -7
  38. package/dist/src/transaction.d.ts +36 -0
  39. package/dist/src/transaction.d.ts.map +1 -0
  40. package/dist/src/transaction.js +278 -0
  41. package/dist/tsconfig.tsbuildinfo +1 -7906
  42. package/package.json +12 -10
  43. package/dist/src/recovery/smartbitApi.d.ts +0 -11
  44. package/dist/src/recovery/smartbitApi.d.ts.map +0 -1
  45. package/dist/src/recovery/smartbitApi.js +0 -36
@@ -0,0 +1,36 @@
1
+ import * as utxolib from '@bitgo-beta/utxo-lib';
2
+ import { BitGoBase, IRequestTracer } from '@bitgo-beta/sdk-core';
3
+ import { AbstractUtxoCoin, ExplainTransactionOptions, TransactionExplanation, TransactionPrebuild } from './abstractUtxoCoin';
4
+ /**
5
+ * Get the inputs for a psbt from a prebuild.
6
+ */
7
+ export declare function getPsbtTxInputs(psbtArg: string | utxolib.bitgo.UtxoPsbt, network: utxolib.Network): {
8
+ address: string;
9
+ value: bigint;
10
+ valueString: string;
11
+ }[];
12
+ /**
13
+ * Get the inputs for a transaction from a prebuild.
14
+ */
15
+ export declare function getTxInputs<TNumber extends number | bigint>(params: {
16
+ txPrebuild: TransactionPrebuild<TNumber>;
17
+ bitgo: BitGoBase;
18
+ coin: AbstractUtxoCoin;
19
+ disableNetworking: boolean;
20
+ reqId?: IRequestTracer;
21
+ }): Promise<{
22
+ address: string;
23
+ value: TNumber;
24
+ valueString: string;
25
+ }[]>;
26
+ /**
27
+ * Decompose a raw psbt into useful information, such as the total amounts,
28
+ * change amounts, and transaction outputs.
29
+ */
30
+ export declare function explainPsbt<TNumber extends number | bigint>(params: ExplainTransactionOptions<TNumber>, network: utxolib.Network): TransactionExplanation;
31
+ /**
32
+ * Decompose a raw transaction into useful information, such as the total amounts,
33
+ * change amounts, and transaction outputs.
34
+ */
35
+ export declare function explainTx<TNumber extends number | bigint>(params: ExplainTransactionOptions<TNumber>, coin: AbstractUtxoCoin): TransactionExplanation;
36
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAU,MAAM,sBAAsB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAGhB,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EAEpB,MAAM,oBAAoB,CAAC;AAG5B;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,EACxC,OAAO,EAAE,OAAO,CAAC,OAAO,GACvB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,CAyB3D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE;IACzE,UAAU,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAoCtE;AAuHD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EACzD,MAAM,EAAE,yBAAyB,CAAC,OAAO,CAAC,EAC1C,OAAO,EAAE,OAAO,CAAC,OAAO,GACvB,sBAAsB,CA8ExB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EACvD,MAAM,EAAE,yBAAyB,CAAC,OAAO,CAAC,EAC1C,IAAI,EAAE,gBAAgB,GACrB,sBAAsB,CAexB"}
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.explainTx = exports.explainPsbt = exports.getTxInputs = exports.getPsbtTxInputs = void 0;
4
+ const utxolib = require("@bitgo-beta/utxo-lib");
5
+ const utxo_lib_1 = require("@bitgo-beta/utxo-lib");
6
+ /**
7
+ * Get the inputs for a psbt from a prebuild.
8
+ */
9
+ function getPsbtTxInputs(psbtArg, network) {
10
+ const psbt = psbtArg instanceof utxolib.bitgo.UtxoPsbt ? psbtArg : utxolib.bitgo.createPsbtFromHex(psbtArg, network);
11
+ const txInputs = psbt.txInputs;
12
+ return psbt.data.inputs.map((input, index) => {
13
+ let address;
14
+ let value;
15
+ if (input.witnessUtxo) {
16
+ address = utxolib.address.fromOutputScript(input.witnessUtxo.script, network);
17
+ value = input.witnessUtxo.value;
18
+ }
19
+ else if (input.nonWitnessUtxo) {
20
+ const tx = utxolib.bitgo.createTransactionFromBuffer(input.nonWitnessUtxo, network, {
21
+ amountType: 'bigint',
22
+ });
23
+ const txId = Buffer.from(txInputs[index].hash).reverse().toString('hex');
24
+ if (tx.getId() !== txId) {
25
+ throw new Error('input transaction hex does not match id');
26
+ }
27
+ const prevTxOutputIndex = txInputs[index].index;
28
+ address = utxolib.address.fromOutputScript(tx.outs[prevTxOutputIndex].script, network);
29
+ value = tx.outs[prevTxOutputIndex].value;
30
+ }
31
+ else {
32
+ throw new Error('psbt input is missing both witnessUtxo and nonWitnessUtxo');
33
+ }
34
+ return { address, value, valueString: value.toString() };
35
+ });
36
+ }
37
+ exports.getPsbtTxInputs = getPsbtTxInputs;
38
+ /**
39
+ * Get the inputs for a transaction from a prebuild.
40
+ */
41
+ async function getTxInputs(params) {
42
+ const { txPrebuild, bitgo, coin, disableNetworking, reqId } = params;
43
+ if (!txPrebuild.txHex) {
44
+ throw new Error(`txPrebuild.txHex not set`);
45
+ }
46
+ const transaction = coin.createTransactionFromHex(txPrebuild.txHex);
47
+ const transactionCache = {};
48
+ return await Promise.all(transaction.ins.map(async (currentInput) => {
49
+ var _a, _b;
50
+ const transactionId = Buffer.from(currentInput.hash).reverse().toString('hex');
51
+ const txHex = (_b = (_a = txPrebuild.txInfo) === null || _a === void 0 ? void 0 : _a.txHexes) === null || _b === void 0 ? void 0 : _b[transactionId];
52
+ if (txHex) {
53
+ const localTx = coin.createTransactionFromHex(txHex);
54
+ if (localTx.getId() !== transactionId) {
55
+ throw new Error('input transaction hex does not match id');
56
+ }
57
+ const currentOutput = localTx.outs[currentInput.index];
58
+ const address = utxolib.address.fromOutputScript(currentOutput.script, coin.network);
59
+ return {
60
+ address,
61
+ value: currentOutput.value,
62
+ valueString: currentOutput.value.toString(),
63
+ };
64
+ }
65
+ else if (!transactionCache[transactionId]) {
66
+ if (disableNetworking) {
67
+ throw new Error('attempting to retrieve transaction details externally with networking disabled');
68
+ }
69
+ if (reqId) {
70
+ bitgo.setRequestTracer(reqId);
71
+ }
72
+ transactionCache[transactionId] = await bitgo.get(coin.url(`/public/tx/${transactionId}`)).result();
73
+ }
74
+ const transactionDetails = transactionCache[transactionId];
75
+ return transactionDetails.outputs[currentInput.index];
76
+ }));
77
+ }
78
+ exports.getTxInputs = getTxInputs;
79
+ function explainCommon(tx, params, network) {
80
+ var _a;
81
+ const displayOrder = ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs'];
82
+ let spendAmount = BigInt(0);
83
+ let changeAmount = BigInt(0);
84
+ const changeOutputs = [];
85
+ const outputs = [];
86
+ const { changeInfo } = params;
87
+ const changeAddresses = (_a = changeInfo === null || changeInfo === void 0 ? void 0 : changeInfo.map((info) => info.address)) !== null && _a !== void 0 ? _a : [];
88
+ tx.outs.forEach((currentOutput) => {
89
+ const currentAddress = utxolib.address.fromOutputScript(currentOutput.script, network);
90
+ const currentAmount = BigInt(currentOutput.value);
91
+ if (changeAddresses.includes(currentAddress)) {
92
+ // this is change
93
+ changeAmount += currentAmount;
94
+ const change = changeInfo === null || changeInfo === void 0 ? void 0 : changeInfo.find((change) => change.address === currentAddress);
95
+ if (!change) {
96
+ throw new Error('changeInfo must have change information for all change outputs');
97
+ }
98
+ changeOutputs.push({
99
+ address: currentAddress,
100
+ amount: currentAmount.toString(),
101
+ chain: change.chain,
102
+ index: change.index,
103
+ external: false,
104
+ });
105
+ return;
106
+ }
107
+ spendAmount += currentAmount;
108
+ outputs.push({
109
+ address: currentAddress,
110
+ amount: currentAmount.toString(),
111
+ // If changeInfo has a length greater than or equal to zero, it means that the change information
112
+ // was provided to the function but the output was not identified as change. In this case,
113
+ // the output is external, and we can set it as so. If changeInfo is undefined, it means we were
114
+ // given no information about change outputs, so we can't determine anything about the output,
115
+ // so we leave it undefined.
116
+ external: changeInfo ? true : undefined,
117
+ });
118
+ });
119
+ const outputDetails = {
120
+ outputAmount: spendAmount.toString(),
121
+ changeAmount: changeAmount.toString(),
122
+ outputs,
123
+ changeOutputs,
124
+ };
125
+ let fee;
126
+ let locktime;
127
+ if (params.feeInfo) {
128
+ displayOrder.push('fee');
129
+ fee = params.feeInfo;
130
+ }
131
+ if (Number.isInteger(tx.locktime) && tx.locktime > 0) {
132
+ displayOrder.push('locktime');
133
+ locktime = tx.locktime;
134
+ }
135
+ return { displayOrder, id: tx.getId(), ...outputDetails, fee, locktime };
136
+ }
137
+ function getRootWalletKeys(params) {
138
+ var _a;
139
+ const keys = (_a = params.pubs) === null || _a === void 0 ? void 0 : _a.map((xpub) => utxo_lib_1.bip32.fromBase58(xpub));
140
+ return keys && keys.length === 3 ? new utxo_lib_1.bitgo.RootWalletKeys(keys) : undefined;
141
+ }
142
+ function getPsbtInputSignaturesCount(psbt, params) {
143
+ const rootWalletKeys = getRootWalletKeys(params);
144
+ return rootWalletKeys
145
+ ? utxo_lib_1.bitgo.getSignatureValidationArrayPsbt(psbt, rootWalletKeys).map((sv) => sv[1].filter((v) => v).length)
146
+ : Array(psbt.data.inputs.length).fill(0);
147
+ }
148
+ function getTxInputSignaturesCount(tx, params, network) {
149
+ var _a, _b, _c;
150
+ const prevOutputs = (_b = (_a = params.txInfo) === null || _a === void 0 ? void 0 : _a.unspents) === null || _b === void 0 ? void 0 : _b.map((u) => utxo_lib_1.bitgo.toOutput(u, network));
151
+ const rootWalletKeys = getRootWalletKeys(params);
152
+ const { unspents = [] } = (_c = params.txInfo) !== null && _c !== void 0 ? _c : {};
153
+ // get the number of signatures per input
154
+ return tx.ins.map((input, idx) => {
155
+ if (unspents.length !== tx.ins.length) {
156
+ return 0;
157
+ }
158
+ if (!prevOutputs) {
159
+ throw new Error(`invalid state`);
160
+ }
161
+ if (!rootWalletKeys) {
162
+ // no pub keys or incorrect number of pub keys
163
+ return 0;
164
+ }
165
+ try {
166
+ return utxo_lib_1.bitgo.verifySignatureWithUnspent(tx, idx, unspents, rootWalletKeys).filter((v) => v).length;
167
+ }
168
+ catch (e) {
169
+ // some other error occurred and we can't validate the signatures
170
+ return 0;
171
+ }
172
+ });
173
+ }
174
+ /**
175
+ * Decompose a raw psbt into useful information, such as the total amounts,
176
+ * change amounts, and transaction outputs.
177
+ */
178
+ function explainPsbt(params, network) {
179
+ const { txHex } = params;
180
+ let psbt;
181
+ try {
182
+ psbt = utxo_lib_1.bitgo.createPsbtFromHex(txHex, network);
183
+ }
184
+ catch (e) {
185
+ throw new Error('failed to parse psbt hex');
186
+ }
187
+ const txOutputs = psbt.txOutputs;
188
+ function getChainAndIndexFromBip32Derivations(output) {
189
+ var _a, _b;
190
+ const derivations = (_b = (_a = output.bip32Derivation) !== null && _a !== void 0 ? _a : output.tapBip32Derivation) !== null && _b !== void 0 ? _b : undefined;
191
+ if (!derivations) {
192
+ return undefined;
193
+ }
194
+ const paths = derivations.map((d) => d.path);
195
+ if (!paths || paths.length !== 3) {
196
+ throw new Error('expected 3 paths in bip32Derivation or tapBip32Derivation');
197
+ }
198
+ if (!paths.every((p) => paths[0] === p)) {
199
+ throw new Error('expected all paths to be the same');
200
+ }
201
+ paths.forEach((path) => {
202
+ if (paths[0] !== path) {
203
+ throw new Error('Unable to get a single chain and index on the output because there are different paths for different keys');
204
+ }
205
+ });
206
+ return utxolib.bitgo.getChainAndIndexFromPath(paths[0]);
207
+ }
208
+ function getChangeInfo() {
209
+ try {
210
+ return utxolib.bitgo.findInternalOutputIndices(psbt).map((i) => {
211
+ const derivationInformation = getChainAndIndexFromBip32Derivations(psbt.data.outputs[i]);
212
+ if (!derivationInformation) {
213
+ throw new Error('could not find derivation information on bip32Derivation or tapBip32Derivation');
214
+ }
215
+ return {
216
+ address: utxolib.address.fromOutputScript(txOutputs[i].script, network),
217
+ external: false,
218
+ ...derivationInformation,
219
+ };
220
+ });
221
+ }
222
+ catch (e) {
223
+ if (e instanceof utxolib.bitgo.ErrorNoMultiSigInputFound) {
224
+ return undefined;
225
+ }
226
+ throw e;
227
+ }
228
+ }
229
+ const changeInfo = getChangeInfo();
230
+ const tx = psbt.getUnsignedTx();
231
+ const common = explainCommon(tx, { ...params, txInfo: params.txInfo, changeInfo }, network);
232
+ const inputSignaturesCount = getPsbtInputSignaturesCount(psbt, params);
233
+ // Set fee from subtracting inputs from outputs
234
+ const outputAmount = txOutputs.reduce((cumulative, curr) => cumulative + BigInt(curr.value), BigInt(0));
235
+ const inputAmount = psbt.txInputs.reduce((cumulative, txInput, i) => {
236
+ const data = psbt.data.inputs[i];
237
+ if (data.witnessUtxo) {
238
+ return cumulative + BigInt(data.witnessUtxo.value);
239
+ }
240
+ else if (data.nonWitnessUtxo) {
241
+ const tx = utxo_lib_1.bitgo.createTransactionFromBuffer(data.nonWitnessUtxo, network, { amountType: 'bigint' });
242
+ return cumulative + BigInt(tx.outs[txInput.index].value);
243
+ }
244
+ else {
245
+ throw new Error('could not find value on input');
246
+ }
247
+ }, BigInt(0));
248
+ return {
249
+ ...common,
250
+ fee: (inputAmount - outputAmount).toString(),
251
+ inputSignatures: inputSignaturesCount,
252
+ signatures: inputSignaturesCount.reduce((prev, curr) => (curr > prev ? curr : prev), 0),
253
+ };
254
+ }
255
+ exports.explainPsbt = explainPsbt;
256
+ /**
257
+ * Decompose a raw transaction into useful information, such as the total amounts,
258
+ * change amounts, and transaction outputs.
259
+ */
260
+ function explainTx(params, coin) {
261
+ const { txHex } = params;
262
+ let tx;
263
+ try {
264
+ tx = coin.createTransactionFromHex(txHex);
265
+ }
266
+ catch (e) {
267
+ throw new Error('failed to parse transaction hex');
268
+ }
269
+ const common = explainCommon(tx, params, coin.network);
270
+ const inputSignaturesCount = getTxInputSignaturesCount(tx, params, coin.network);
271
+ return {
272
+ ...common,
273
+ inputSignatures: inputSignaturesCount,
274
+ signatures: inputSignaturesCount.reduce((prev, curr) => (curr > prev ? curr : prev), 0),
275
+ };
276
+ }
277
+ exports.explainTx = explainTx;
278
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZ0RBQWdEO0FBV2hELG1EQUFvRTtBQUVwRTs7R0FFRztBQUNILFNBQWdCLGVBQWUsQ0FDN0IsT0FBd0MsRUFDeEMsT0FBd0I7SUFFeEIsTUFBTSxJQUFJLEdBQUcsT0FBTyxZQUFZLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDL0IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDM0MsSUFBSSxPQUFlLENBQUM7UUFDcEIsSUFBSSxLQUFhLENBQUM7UUFDbEIsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFO1lBQ3JCLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzlFLEtBQUssR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztTQUNqQzthQUFNLElBQUksS0FBSyxDQUFDLGNBQWMsRUFBRTtZQUMvQixNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLDJCQUEyQixDQUFTLEtBQUssQ0FBQyxjQUFjLEVBQUUsT0FBTyxFQUFFO2dCQUMxRixVQUFVLEVBQUUsUUFBUTthQUNyQixDQUFDLENBQUM7WUFDSCxNQUFNLElBQUksR0FBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJ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ZSxFQUFFLG9CQUFvQjtRQUNyQyxVQUFVLEVBQUUsb0JBQW9CLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztLQUM5RCxDQUFDO0FBQzlCLENBQUM7QUFsQkQsOEJBa0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgdXR4b2xpYiBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5pbXBvcnQgeyBCaXRHb0Jhc2UsIElSZXF1ZXN0VHJhY2VyLCBUcmlwbGUgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQge1xuICBBYnN0cmFjdFV0eG9Db2luLFxuICBEZWNvcmF0ZWRFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zLFxuICBXYWxsZXRPdXRwdXQsXG4gIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFRyYW5zYWN0aW9uRXhwbGFuYXRpb24sXG4gIFRyYW5zYWN0aW9uUHJlYnVpbGQsXG4gIE91dHB1dCxcbn0gZnJvbSAnLi9hYnN0cmFjdFV0eG9Db2luJztcbmltcG9ydCB7IGJpcDMyLCBCSVAzMkludGVyZmFjZSwgYml0Z28gfSBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5cbi8qKlxuICogR2V0IHRoZSBpbnB1dHMgZm9yIGEgcHNidCBmcm9tIGEgcHJlYnVpbGQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQc2J0VHhJbnB1dHMoXG4gIHBzYnRBcmc6IHN0cmluZyB8IHV0eG9saWIuYml0Z28uVXR4b1BzYnQsXG4gIG5ldHdvcms6IHV0eG9saWIuTmV0d29ya1xuKTogeyBhZGRyZXNzOiBzdHJpbmc7IHZhbHVlOiBiaWdpbnQ7IHZhbHVlU3RyaW5nOiBzdHJpbmcgfVtdIHtcbiAgY29uc3QgcHNidCA9IHBzYnRBcmcgaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0ID8gcHNidEFyZyA6IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgocHNidEFyZywgbmV0d29yayk7XG4gIGNvbnN0IHR4SW5wdXRzID0gcHNidC50eElucHV0cztcbiAgcmV0dXJuIHBzYnQuZGF0YS5pbnB1dHMubWFwKChpbnB1dCwgaW5kZXgpID0+IHtcbiAgICBsZXQgYWRkcmVzczogc3RyaW5nO1xuICAgIGxldCB2YWx1ZTogYmlnaW50O1xuICAgIGlmIChpbnB1dC53aXRuZXNzVXR4bykge1xuICAgICAgYWRkcmVzcyA9IHV0eG9saWIuYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KGlucHV0LndpdG5lc3NVdHhvLnNjcmlwdCwgbmV0d29yayk7XG4gICAgICB2YWx1ZSA9IGlucHV0LndpdG5lc3NVdHhvLnZhbHVlO1xuICAgIH0gZWxzZSBpZiAoaW5wdXQubm9uV2l0bmVzc1V0eG8pIHtcbiAgICAgIGNvbnN0IHR4ID0gdXR4b2xpYi5iaXRnby5jcmVhdGVUcmFuc2FjdGlvbkZyb21CdWZmZXI8YmlnaW50PihpbnB1dC5ub25XaXRuZXNzVXR4bywgbmV0d29yaywge1xuICAgICAgICBhbW91bnRUeXBlOiAnYmlnaW50JyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdHhJZCA9IChCdWZmZXIuZnJvbSh0eElucHV0c1tpbmRleF0uaGFzaCkucmV2ZXJzZSgpIGFzIEJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgaWYgKHR4LmdldElkKCkgIT09IHR4SWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0cmFuc2FjdGlvbiBoZXggZG9lcyBub3QgbWF0Y2ggaWQnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHByZXZUeE91dHB1dEluZGV4ID0gdHhJbnB1dHNbaW5kZXhdLmluZGV4O1xuICAgICAgYWRkcmVzcyA9IHV0eG9saWIuYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KHR4Lm91dHNbcHJldlR4T3V0cHV0SW5kZXhdLnNjcmlwdCwgbmV0d29yayk7XG4gICAgICB2YWx1ZSA9IHR4Lm91dHNbcHJldlR4T3V0cHV0SW5kZXhdLnZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BzYnQgaW5wdXQgaXMgbWlzc2luZyBib3RoIHdpdG5lc3NVdHhvIGFuZCBub25XaXRuZXNzVXR4bycpO1xuICAgIH1cbiAgICByZXR1cm4geyBhZGRyZXNzLCB2YWx1ZSwgdmFsdWVTdHJpbmc6IHZhbHVlLnRvU3RyaW5nKCkgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBpbnB1dHMgZm9yIGEgdHJhbnNhY3Rpb24gZnJvbSBhIHByZWJ1aWxkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VHhJbnB1dHM8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4ocGFyYW1zOiB7XG4gIHR4UHJlYnVpbGQ6IFRyYW5zYWN0aW9uUHJlYnVpbGQ8VE51bWJlcj47XG4gIGJpdGdvOiBCaXRHb0Jhc2U7XG4gIGNvaW46IEFic3RyYWN0VXR4b0NvaW47XG4gIGRpc2FibGVOZXR3b3JraW5nOiBib29sZWFuO1xuICByZXFJZD86IElSZXF1ZXN0VHJhY2VyO1xufSk6IFByb21pc2U8eyBhZGRyZXNzOiBzdHJpbmc7IHZhbHVlOiBUTnVtYmVyOyB2YWx1ZVN0cmluZzogc3RyaW5nIH1bXT4ge1xuICBjb25zdCB7IHR4UHJlYnVpbGQsIGJpdGdvLCBjb2luLCBkaXNhYmxlTmV0d29ya2luZywgcmVxSWQgfSA9IHBhcmFtcztcbiAgaWYgKCF0eFByZWJ1aWxkLnR4SGV4KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGB0eFByZWJ1aWxkLnR4SGV4IG5vdCBzZXRgKTtcbiAgfVxuICBjb25zdCB0cmFuc2FjdGlvbiA9IGNvaW4uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4PFROdW1iZXI+KHR4UHJlYnVpbGQudHhIZXgpO1xuICBjb25zdCB0cmFuc2FjdGlvbkNhY2hlID0ge307XG4gIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChcbiAgICB0cmFuc2FjdGlvbi5pbnMubWFwKGFzeW5jIChjdXJyZW50SW5wdXQpOiBQcm9taXNlPHsgYWRkcmVzczogc3RyaW5nOyB2YWx1ZTogVE51bWJlcjsgdmFsdWVTdHJpbmc6IHN0cmluZyB9PiA9PiB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbklkID0gKEJ1ZmZlci5mcm9tKGN1cnJlbnRJbnB1dC5oYXNoKS5yZXZlcnNlKCkgYXMgQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCB0eEhleCA9IHR4UHJlYnVpbGQudHhJbmZvPy50eEhleGVzPy5bdHJhbnNhY3Rpb25JZF07XG4gICAgICBpZiAodHhIZXgpIHtcbiAgICAgICAgY29uc3QgbG9jYWxUeCA9IGNvaW4uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4PFROdW1iZXI+KHR4SGV4KTtcbiAgICAgICAgaWYgKGxvY2FsVHguZ2V0SWQoKSAhPT0gdHJhbnNhY3Rpb25JZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgdHJhbnNhY3Rpb24gaGV4IGRvZXMgbm90IG1hdGNoIGlkJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY3VycmVudE91dHB1dCA9IGxvY2FsVHgub3V0c1tjdXJyZW50SW5wdXQuaW5kZXhdO1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gdXR4b2xpYi5hZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoY3VycmVudE91dHB1dC5zY3JpcHQsIGNvaW4ubmV0d29yayk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgICB2YWx1ZTogY3VycmVudE91dHB1dC52YWx1ZSxcbiAgICAgICAgICB2YWx1ZVN0cmluZzogY3VycmVudE91dHB1dC52YWx1ZS50b1N0cmluZygpLFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmICghdHJhbnNhY3Rpb25DYWNoZVt0cmFuc2FjdGlvbklkXSkge1xuICAgICAgICBpZiAoZGlzYWJsZU5ldHdvcmtpbmcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F0dGVtcHRpbmcgdG8gcmV0cmlldmUgdHJhbnNhY3Rpb24gZGV0YWlscyBleHRlcm5hbGx5IHdpdGggbmV0d29ya2luZyBkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXFJZCkge1xuICAgICAgICAgIGJpdGdvLnNldFJlcXVlc3RUcmFjZXIocmVxSWQpO1xuICAgICAgICB9XG4gICAgICAgIHRyYW5zYWN0aW9uQ2FjaGVbdHJhbnNhY3Rpb25JZF0gPSBhd2FpdCBiaXRnby5nZXQoY29pbi51cmwoYC9wdWJsaWMvdHgvJHt0cmFuc2FjdGlvbklkfWApKS5yZXN1bHQoKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uRGV0YWlscyA9IHRyYW5zYWN0aW9uQ2FjaGVbdHJhbnNhY3Rpb25JZF07XG4gICAgICByZXR1cm4gdHJhbnNhY3Rpb25EZXRhaWxzLm91dHB1dHNbY3VycmVudElucHV0LmluZGV4XTtcbiAgICB9KVxuICApO1xufVxuXG5mdW5jdGlvbiBleHBsYWluQ29tbW9uPFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KFxuICB0eDogYml0Z28uVXR4b1RyYW5zYWN0aW9uPFROdW1iZXI+LFxuICBwYXJhbXM6IERlY29yYXRlZEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnM8VE51bWJlcj4sXG4gIG5ldHdvcms6IHV0eG9saWIuTmV0d29ya1xuKSB7XG4gIGNvbnN0IGRpc3BsYXlPcmRlciA9IFsnaWQnLCAnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnXTtcbiAgbGV0IHNwZW5kQW1vdW50ID0gQmlnSW50KDApO1xuICBsZXQgY2hhbmdlQW1vdW50ID0gQmlnSW50KDApO1xuICBjb25zdCBjaGFuZ2VPdXRwdXRzOiBXYWxsZXRPdXRwdXRbXSA9IFtdO1xuICBjb25zdCBvdXRwdXRzOiBPdXRwdXRbXSA9IFtdO1xuXG4gIGNvbnN0IHsgY2hhbmdlSW5mbyB9ID0gcGFyYW1zO1xuICBjb25zdCBjaGFuZ2VBZGRyZXNzZXMgPSBjaGFuZ2VJbmZvPy5tYXAoKGluZm8pID0+IGluZm8uYWRkcmVzcykgPz8gW107XG5cbiAgdHgub3V0cy5mb3JFYWNoKChjdXJyZW50T3V0cHV0KSA9PiB7XG4gICAgY29uc3QgY3VycmVudEFkZHJlc3MgPSB1dHhvbGliLmFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChjdXJyZW50T3V0cHV0LnNjcmlwdCwgbmV0d29yayk7XG4gICAgY29uc3QgY3VycmVudEFtb3VudCA9IEJpZ0ludChjdXJyZW50T3V0cHV0LnZhbHVlKTtcblxuICAgIGlmIChjaGFuZ2VBZGRyZXNzZXMuaW5jbHVkZXMoY3VycmVudEFkZHJlc3MpKSB7XG4gICAgICAvLyB0aGlzIGlzIGNoYW5nZVxuICAgICAgY2hhbmdlQW1vdW50ICs9IGN1cnJlbnRBbW91bnQ7XG4gICAgICBjb25zdCBjaGFuZ2UgPSBjaGFuZ2VJbmZvPy5maW5kKChjaGFuZ2UpID0+IGNoYW5nZS5hZGRyZXNzID09PSBjdXJyZW50QWRkcmVzcyk7XG5cbiAgICAgIGlmICghY2hhbmdlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2hhbmdlSW5mbyBtdXN0IGhhdmUgY2hhbmdlIGluZm9ybWF0aW9uIGZvciBhbGwgY2hhbmdlIG91dHB1dHMnKTtcbiAgICAgIH1cbiAgICAgIGNoYW5nZU91dHB1dHMucHVzaCh7XG4gICAgICAgIGFkZHJlc3M6IGN1cnJlbnRBZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IGN1cnJlbnRBbW91bnQudG9TdHJpbmcoKSxcbiAgICAgICAgY2hhaW46IGNoYW5nZS5jaGFpbixcbiAgICAgICAgaW5kZXg6IGNoYW5nZS5pbmRleCxcbiAgICAgICAgZXh0ZXJuYWw6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc3BlbmRBbW91bnQgKz0gY3VycmVudEFtb3VudDtcbiAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgYWRkcmVzczogY3VycmVudEFkZHJlc3MsXG4gICAgICBhbW91bnQ6IGN1cnJlbnRBbW91bnQudG9TdHJpbmcoKSxcbiAgICAgIC8vIElmIGNoYW5nZUluZm8gaGFzIGEgbGVuZ3RoIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB6ZXJvLCBpdCBtZWFucyB0aGF0IHRoZSBjaGFuZ2UgaW5mb3JtYXRpb25cbiAgICAgIC8vIHdhcyBwcm92aWRlZCB0byB0aGUgZnVuY3Rpb24gYnV0IHRoZSBvdXRwdXQgd2FzIG5vdCBpZGVudGlmaWVkIGFzIGNoYW5nZS4gSW4gdGhpcyBjYXNlLFxuICAgICAgLy8gdGhlIG91dHB1dCBpcyBleHRlcm5hbCwgYW5kIHdlIGNhbiBzZXQgaXQgYXMgc28uIElmIGNoYW5nZUluZm8gaXMgdW5kZWZpbmVkLCBpdCBtZWFucyB3ZSB3ZXJlXG4gICAgICAvLyBnaXZlbiBubyBpbmZvcm1hdGlvbiBhYm91dCBjaGFuZ2Ugb3V0cHV0cywgc28gd2UgY2FuJ3QgZGV0ZXJtaW5lIGFueXRoaW5nIGFib3V0IHRoZSBvdXRwdXQsXG4gICAgICAvLyBzbyB3ZSBsZWF2ZSBpdCB1bmRlZmluZWQuXG4gICAgICBleHRlcm5hbDogY2hhbmdlSW5mbyA/IHRydWUgOiB1bmRlZmluZWQsXG4gICAgfSk7XG4gIH0pO1xuXG4gIGNvbnN0IG91dHB1dERldGFpbHMgPSB7XG4gICAgb3V0cHV0QW1vdW50OiBzcGVuZEFtb3VudC50b1N0cmluZygpLFxuICAgIGNoYW5nZUFtb3VudDogY2hhbmdlQW1vdW50LnRvU3RyaW5nKCksXG4gICAgb3V0cHV0cyxcbiAgICBjaGFuZ2VPdXRwdXRzLFxuICB9O1xuXG4gIGxldCBmZWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbGV0IGxvY2t0aW1lOiBudW1iZXIgfCB1bmRlZmluZWQ7XG5cbiAgaWYgKHBhcmFtcy5mZWVJbmZvKSB7XG4gICAgZGlzcGxheU9yZGVyLnB1c2goJ2ZlZScpO1xuICAgIGZlZSA9IHBhcmFtcy5mZWVJbmZvO1xuICB9XG5cbiAgaWYgKE51bWJlci5pc0ludGVnZXIodHgubG9ja3RpbWUpICYmIHR4LmxvY2t0aW1lID4gMCkge1xuICAgIGRpc3BsYXlPcmRlci5wdXNoKCdsb2NrdGltZScpO1xuICAgIGxvY2t0aW1lID0gdHgubG9ja3RpbWU7XG4gIH1cblxuICByZXR1cm4geyBkaXNwbGF5T3JkZXIsIGlkOiB0eC5nZXRJZCgpLCAuLi5vdXRwdXREZXRhaWxzLCBmZWUsIGxvY2t0aW1lIH07XG59XG5cbmZ1bmN0aW9uIGdldFJvb3RXYWxsZXRLZXlzPFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9uczxUTnVtYmVyPikge1xuICBjb25zdCBrZXlzID0gcGFyYW1zLnB1YnM/Lm1hcCgoeHB1YikgPT4gYmlwMzIuZnJvbUJhc2U1OCh4cHViKSk7XG4gIHJldHVybiBrZXlzICYmIGtleXMubGVuZ3RoID09PSAzID8gbmV3IGJpdGdvLlJvb3RXYWxsZXRLZXlzKGtleXMgYXMgVHJpcGxlPEJJUDMySW50ZXJmYWNlPikgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGdldFBzYnRJbnB1dFNpZ25hdHVyZXNDb3VudDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgcHNidDogYml0Z28uVXR4b1BzYnQsXG4gIHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9uczxUTnVtYmVyPlxuKSB7XG4gIGNvbnN0IHJvb3RXYWxsZXRLZXlzID0gZ2V0Um9vdFdhbGxldEtleXMocGFyYW1zKTtcbiAgcmV0dXJuIHJvb3RXYWxsZXRLZXlzXG4gICAgPyBiaXRnby5nZXRTaWduYXR1cmVWYWxpZGF0aW9uQXJyYXlQc2J0KHBzYnQsIHJvb3RXYWxsZXRLZXlzKS5tYXAoKHN2KSA9PiBzdlsxXS5maWx0ZXIoKHYpID0+IHYpLmxlbmd0aClcbiAgICA6IChBcnJheShwc2J0LmRhdGEuaW5wdXRzLmxlbmd0aCkgYXMgbnVtYmVyW10pLmZpbGwoMCk7XG59XG5cbmZ1bmN0aW9uIGdldFR4SW5wdXRTaWduYXR1cmVzQ291bnQ8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oXG4gIHR4OiBiaXRnby5VdHhvVHJhbnNhY3Rpb248VE51bWJlcj4sXG4gIHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9uczxUTnVtYmVyPixcbiAgbmV0d29yazogdXR4b2xpYi5OZXR3b3JrXG4pIHtcbiAgY29uc3QgcHJldk91dHB1dHMgPSBwYXJhbXMudHhJbmZvPy51bnNwZW50cz8ubWFwKCh1KSA9PiBiaXRnby50b091dHB1dDxUTnVtYmVyPih1LCBuZXR3b3JrKSk7XG4gIGNvbnN0IHJvb3RXYWxsZXRLZXlzID0gZ2V0Um9vdFdhbGxldEtleXMocGFyYW1zKTtcbiAgY29uc3QgeyB1bnNwZW50cyA9IFtdIH0gPSBwYXJhbXMudHhJbmZvID8/IHt9O1xuXG4gIC8vIGdldCB0aGUgbnVtYmVyIG9mIHNpZ25hdHVyZXMgcGVyIGlucHV0XG4gIHJldHVybiB0eC5pbnMubWFwKChpbnB1dCwgaWR4KTogbnVtYmVyID0+IHtcbiAgICBpZiAodW5zcGVudHMubGVuZ3RoICE9PSB0eC5pbnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgaWYgKCFwcmV2T3V0cHV0cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIHN0YXRlYCk7XG4gICAgfVxuICAgIGlmICghcm9vdFdhbGxldEtleXMpIHtcbiAgICAgIC8vIG5vIHB1YiBrZXlzIG9yIGluY29ycmVjdCBudW1iZXIgb2YgcHViIGtleXNcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGJpdGdvLnZlcmlmeVNpZ25hdHVyZVdpdGhVbnNwZW50PFROdW1iZXI+KHR4LCBpZHgsIHVuc3BlbnRzLCByb290V2FsbGV0S2V5cykuZmlsdGVyKCh2KSA9PiB2KS5sZW5ndGg7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gc29tZSBvdGhlciBlcnJvciBvY2N1cnJlZCBhbmQgd2UgY2FuJ3QgdmFsaWRhdGUgdGhlIHNpZ25hdHVyZXNcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogRGVjb21wb3NlIGEgcmF3IHBzYnQgaW50byB1c2VmdWwgaW5mb3JtYXRpb24sIHN1Y2ggYXMgdGhlIHRvdGFsIGFtb3VudHMsXG4gKiBjaGFuZ2UgYW1vdW50cywgYW5kIHRyYW5zYWN0aW9uIG91dHB1dHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHBsYWluUHNidDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgcGFyYW1zOiBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zPFROdW1iZXI+LFxuICBuZXR3b3JrOiB1dHhvbGliLk5ldHdvcmtcbik6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24ge1xuICBjb25zdCB7IHR4SGV4IH0gPSBwYXJhbXM7XG4gIGxldCBwc2J0OiBiaXRnby5VdHhvUHNidDtcbiAgdHJ5IHtcbiAgICBwc2J0ID0gYml0Z28uY3JlYXRlUHNidEZyb21IZXgodHhIZXgsIG5ldHdvcmspO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdmYWlsZWQgdG8gcGFyc2UgcHNidCBoZXgnKTtcbiAgfVxuICBjb25zdCB0eE91dHB1dHMgPSBwc2J0LnR4T3V0cHV0cztcblxuICBmdW5jdGlvbiBnZXRDaGFpbkFuZEluZGV4RnJvbUJpcDMyRGVyaXZhdGlvbnMob3V0cHV0OiBiaXRnby5Qc2J0T3V0cHV0KSB7XG4gICAgY29uc3QgZGVyaXZhdGlvbnMgPSBvdXRwdXQuYmlwMzJEZXJpdmF0aW9uID8/IG91dHB1dC50YXBCaXAzMkRlcml2YXRpb24gPz8gdW5kZWZpbmVkO1xuICAgIGlmICghZGVyaXZhdGlvbnMpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IHBhdGhzID0gZGVyaXZhdGlvbnMubWFwKChkKSA9PiBkLnBhdGgpO1xuICAgIGlmICghcGF0aHMgfHwgcGF0aHMubGVuZ3RoICE9PSAzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGVkIDMgcGF0aHMgaW4gYmlwMzJEZXJpdmF0aW9uIG9yIHRhcEJpcDMyRGVyaXZhdGlvbicpO1xuICAgIH1cbiAgICBpZiAoIXBhdGhzLmV2ZXJ5KChwKSA9PiBwYXRoc1swXSA9PT0gcCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0ZWQgYWxsIHBhdGhzIHRvIGJlIHRoZSBzYW1lJyk7XG4gICAgfVxuXG4gICAgcGF0aHMuZm9yRWFjaCgocGF0aCkgPT4ge1xuICAgICAgaWYgKHBhdGhzWzBdICE9PSBwYXRoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnVW5hYmxlIHRvIGdldCBhIHNpbmdsZSBjaGFpbiBhbmQgaW5kZXggb24gdGhlIG91dHB1dCBiZWNhdXNlIHRoZXJlIGFyZSBkaWZmZXJlbnQgcGF0aHMgZm9yIGRpZmZlcmVudCBrZXlzJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB1dHhvbGliLmJpdGdvLmdldENoYWluQW5kSW5kZXhGcm9tUGF0aChwYXRoc1swXSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRDaGFuZ2VJbmZvKCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdXR4b2xpYi5iaXRnby5maW5kSW50ZXJuYWxPdXRwdXRJbmRpY2VzKHBzYnQpLm1hcCgoaSkgPT4ge1xuICAgICAgICBjb25zdCBkZXJpdmF0aW9uSW5mb3JtYXRpb24gPSBnZXRDaGFpbkFuZEluZGV4RnJvbUJpcDMyRGVyaXZhdGlvbnMocHNidC5kYXRhLm91dHB1dHNbaV0pO1xuICAgICAgICBpZiAoIWRlcml2YXRpb25JbmZvcm1hdGlvbikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IGZpbmQgZGVyaXZhdGlvbiBpbmZvcm1hdGlvbiBvbiBiaXAzMkRlcml2YXRpb24gb3IgdGFwQmlwMzJEZXJpdmF0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBhZGRyZXNzOiB1dHhvbGliLmFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdCh0eE91dHB1dHNbaV0uc2NyaXB0LCBuZXR3b3JrKSxcbiAgICAgICAgICBleHRlcm5hbDogZmFsc2UsXG4gICAgICAgICAgLi4uZGVyaXZhdGlvbkluZm9ybWF0aW9uLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUgaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLkVycm9yTm9NdWx0aVNpZ0lucHV0Rm91bmQpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG4gIGNvbnN0IGNoYW5nZUluZm8gPSBnZXRDaGFuZ2VJbmZvKCk7XG4gIGNvbnN0IHR4ID0gcHNidC5nZXRVbnNpZ25lZFR4KCkgYXMgYml0Z28uVXR4b1RyYW5zYWN0aW9uPFROdW1iZXI+O1xuICBjb25zdCBjb21tb24gPSBleHBsYWluQ29tbW9uKHR4LCB7IC4uLnBhcmFtcywgdHhJbmZvOiBwYXJhbXMudHhJbmZvLCBjaGFuZ2VJbmZvIH0sIG5ldHdvcmspO1xuICBjb25zdCBpbnB1dFNpZ25hdHVyZXNDb3VudCA9IGdldFBzYnRJbnB1dFNpZ25hdHVyZXNDb3VudChwc2J0LCBwYXJhbXMpO1xuXG4gIC8vIFNldCBmZWUgZnJvbSBzdWJ0cmFjdGluZyBpbnB1dHMgZnJvbSBvdXRwdXRzXG4gIGNvbnN0IG91dHB1dEFtb3VudCA9IHR4T3V0cHV0cy5yZWR1Y2UoKGN1bXVsYXRpdmUsIGN1cnIpID0+IGN1bXVsYXRpdmUgKyBCaWdJbnQoY3Vyci52YWx1ZSksIEJpZ0ludCgwKSk7XG4gIGNvbnN0IGlucHV0QW1vdW50ID0gcHNidC50eElucHV0cy5yZWR1Y2UoKGN1bXVsYXRpdmUsIHR4SW5wdXQsIGkpID0+IHtcbiAgICBjb25zdCBkYXRhID0gcHNidC5kYXRhLmlucHV0c1tpXTtcbiAgICBpZiAoZGF0YS53aXRuZXNzVXR4bykge1xuICAgICAgcmV0dXJuIGN1bXVsYXRpdmUgKyBCaWdJbnQoZGF0YS53aXRuZXNzVXR4by52YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChkYXRhLm5vbldpdG5lc3NVdHhvKSB7XG4gICAgICBjb25zdCB0eCA9IGJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUJ1ZmZlcjxiaWdpbnQ+KGRhdGEubm9uV2l0bmVzc1V0eG8sIG5ldHdvcmssIHsgYW1vdW50VHlwZTogJ2JpZ2ludCcgfSk7XG4gICAgICByZXR1cm4gY3VtdWxhdGl2ZSArIEJpZ0ludCh0eC5vdXRzW3R4SW5wdXQuaW5kZXhdLnZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgZmluZCB2YWx1ZSBvbiBpbnB1dCcpO1xuICAgIH1cbiAgfSwgQmlnSW50KDApKTtcblxuICByZXR1cm4ge1xuICAgIC4uLmNvbW1vbixcbiAgICBmZWU6IChpbnB1dEFtb3VudCAtIG91dHB1dEFtb3VudCkudG9TdHJpbmcoKSxcbiAgICBpbnB1dFNpZ25hdHVyZXM6IGlucHV0U2lnbmF0dXJlc0NvdW50LFxuICAgIHNpZ25hdHVyZXM6IGlucHV0U2lnbmF0dXJlc0NvdW50LnJlZHVjZSgocHJldiwgY3VycikgPT4gKGN1cnIgPiBwcmV2ID8gY3VyciA6IHByZXYpLCAwKSxcbiAgfSBhcyBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uO1xufVxuXG4vKipcbiAqIERlY29tcG9zZSBhIHJhdyB0cmFuc2FjdGlvbiBpbnRvIHVzZWZ1bCBpbmZvcm1hdGlvbiwgc3VjaCBhcyB0aGUgdG90YWwgYW1vdW50cyxcbiAqIGNoYW5nZSBhbW91bnRzLCBhbmQgdHJhbnNhY3Rpb24gb3V0cHV0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4cGxhaW5UeDxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgcGFyYW1zOiBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zPFROdW1iZXI+LFxuICBjb2luOiBBYnN0cmFjdFV0eG9Db2luXG4pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgY29uc3QgeyB0eEhleCB9ID0gcGFyYW1zO1xuICBsZXQgdHg7XG4gIHRyeSB7XG4gICAgdHggPSBjb2luLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleCh0eEhleCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZhaWxlZCB0byBwYXJzZSB0cmFuc2FjdGlvbiBoZXgnKTtcbiAgfVxuICBjb25zdCBjb21tb24gPSBleHBsYWluQ29tbW9uKHR4LCBwYXJhbXMsIGNvaW4ubmV0d29yayk7XG4gIGNvbnN0IGlucHV0U2lnbmF0dXJlc0NvdW50ID0gZ2V0VHhJbnB1dFNpZ25hdHVyZXNDb3VudCh0eCwgcGFyYW1zLCBjb2luLm5ldHdvcmspO1xuICByZXR1cm4ge1xuICAgIC4uLmNvbW1vbixcbiAgICBpbnB1dFNpZ25hdHVyZXM6IGlucHV0U2lnbmF0dXJlc0NvdW50LFxuICAgIHNpZ25hdHVyZXM6IGlucHV0U2lnbmF0dXJlc0NvdW50LnJlZHVjZSgocHJldiwgY3VycikgPT4gKGN1cnIgPiBwcmV2ID8gY3VyciA6IHByZXYpLCAwKSxcbiAgfSBhcyBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uO1xufVxuIl19