@bitgo-beta/abstract-utxo 1.6.1-alpha.13 → 1.6.1-alpha.131

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.
@@ -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,EAChB,yBAAyB,EAEzB,sBAAsB,EACtB,mBAAmB,EACpB,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;AAwGD;;;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,CA8CxB;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,236 @@
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 { changeAddresses = [] } = (_a = params.txInfo) !== null && _a !== void 0 ? _a : {};
87
+ tx.outs.forEach((currentOutput) => {
88
+ const currentAddress = utxolib.address.fromOutputScript(currentOutput.script, network);
89
+ const currentAmount = BigInt(currentOutput.value);
90
+ if (changeAddresses.includes(currentAddress)) {
91
+ // this is change
92
+ changeAmount += currentAmount;
93
+ changeOutputs.push({
94
+ address: currentAddress,
95
+ amount: currentAmount.toString(),
96
+ });
97
+ return;
98
+ }
99
+ spendAmount += currentAmount;
100
+ outputs.push({
101
+ address: currentAddress,
102
+ amount: currentAmount.toString(),
103
+ });
104
+ });
105
+ const outputDetails = {
106
+ outputAmount: spendAmount.toString(),
107
+ changeAmount: changeAmount.toString(),
108
+ outputs,
109
+ changeOutputs,
110
+ };
111
+ let fee;
112
+ let locktime;
113
+ if (params.feeInfo) {
114
+ displayOrder.push('fee');
115
+ fee = params.feeInfo;
116
+ }
117
+ if (Number.isInteger(tx.locktime) && tx.locktime > 0) {
118
+ displayOrder.push('locktime');
119
+ locktime = tx.locktime;
120
+ }
121
+ return { displayOrder, id: tx.getId(), ...outputDetails, fee, locktime };
122
+ }
123
+ function getRootWalletKeys(params) {
124
+ var _a;
125
+ const keys = (_a = params.pubs) === null || _a === void 0 ? void 0 : _a.map((xpub) => utxo_lib_1.bip32.fromBase58(xpub));
126
+ return keys && keys.length === 3 ? new utxo_lib_1.bitgo.RootWalletKeys(keys) : undefined;
127
+ }
128
+ function getPsbtInputSignaturesCount(psbt, params) {
129
+ const rootWalletKeys = getRootWalletKeys(params);
130
+ return rootWalletKeys
131
+ ? utxo_lib_1.bitgo.getSignatureValidationArrayPsbt(psbt, rootWalletKeys).map((sv) => sv[1].filter((v) => v).length)
132
+ : Array(psbt.data.inputs.length).fill(0);
133
+ }
134
+ function getTxInputSignaturesCount(tx, params, network) {
135
+ var _a, _b, _c;
136
+ 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));
137
+ const rootWalletKeys = getRootWalletKeys(params);
138
+ const { unspents = [] } = (_c = params.txInfo) !== null && _c !== void 0 ? _c : {};
139
+ // get the number of signatures per input
140
+ return tx.ins.map((input, idx) => {
141
+ if (unspents.length !== tx.ins.length) {
142
+ return 0;
143
+ }
144
+ if (!prevOutputs) {
145
+ throw new Error(`invalid state`);
146
+ }
147
+ if (!rootWalletKeys) {
148
+ // no pub keys or incorrect number of pub keys
149
+ return 0;
150
+ }
151
+ try {
152
+ return utxo_lib_1.bitgo.verifySignatureWithUnspent(tx, idx, unspents, rootWalletKeys).filter((v) => v).length;
153
+ }
154
+ catch (e) {
155
+ // some other error occurred and we can't validate the signatures
156
+ return 0;
157
+ }
158
+ });
159
+ }
160
+ /**
161
+ * Decompose a raw psbt into useful information, such as the total amounts,
162
+ * change amounts, and transaction outputs.
163
+ */
164
+ function explainPsbt(params, network) {
165
+ const { txHex } = params;
166
+ let psbt;
167
+ try {
168
+ psbt = utxo_lib_1.bitgo.createPsbtFromHex(txHex, network);
169
+ }
170
+ catch (e) {
171
+ throw new Error('failed to parse psbt hex');
172
+ }
173
+ const txOutputs = psbt.txOutputs;
174
+ function getChangeAddresses() {
175
+ try {
176
+ return utxolib.bitgo
177
+ .findInternalOutputIndices(psbt)
178
+ .map((i) => utxolib.address.fromOutputScript(txOutputs[i].script, network));
179
+ }
180
+ catch (e) {
181
+ if (e instanceof utxolib.bitgo.ErrorNoMultiSigInputFound) {
182
+ return [];
183
+ }
184
+ throw e;
185
+ }
186
+ }
187
+ const changeAddresses = getChangeAddresses();
188
+ const tx = psbt.getUnsignedTx();
189
+ const common = explainCommon(tx, { ...params, txInfo: { ...params.txInfo, changeAddresses } }, network);
190
+ const inputSignaturesCount = getPsbtInputSignaturesCount(psbt, params);
191
+ // Set fee from subtracting inputs from outputs
192
+ const outputAmount = txOutputs.reduce((cumulative, curr) => cumulative + BigInt(curr.value), BigInt(0));
193
+ const inputAmount = psbt.txInputs.reduce((cumulative, txInput, i) => {
194
+ const data = psbt.data.inputs[i];
195
+ if (data.witnessUtxo) {
196
+ return cumulative + BigInt(data.witnessUtxo.value);
197
+ }
198
+ else if (data.nonWitnessUtxo) {
199
+ const tx = utxo_lib_1.bitgo.createTransactionFromBuffer(data.nonWitnessUtxo, network, { amountType: 'bigint' });
200
+ return cumulative + BigInt(tx.outs[txInput.index].value);
201
+ }
202
+ else {
203
+ throw new Error('could not find value on input');
204
+ }
205
+ }, BigInt(0));
206
+ return {
207
+ ...common,
208
+ fee: (inputAmount - outputAmount).toString(),
209
+ inputSignatures: inputSignaturesCount,
210
+ signatures: inputSignaturesCount.reduce((prev, curr) => (curr > prev ? curr : prev), 0),
211
+ };
212
+ }
213
+ exports.explainPsbt = explainPsbt;
214
+ /**
215
+ * Decompose a raw transaction into useful information, such as the total amounts,
216
+ * change amounts, and transaction outputs.
217
+ */
218
+ function explainTx(params, coin) {
219
+ const { txHex } = params;
220
+ let tx;
221
+ try {
222
+ tx = coin.createTransactionFromHex(txHex);
223
+ }
224
+ catch (e) {
225
+ throw new Error('failed to parse transaction hex');
226
+ }
227
+ const common = explainCommon(tx, params, coin.network);
228
+ const inputSignaturesCount = getTxInputSignaturesCount(tx, params, coin.network);
229
+ return {
230
+ ...common,
231
+ inputSignatures: inputSignaturesCount,
232
+ signatures: inputSignaturesCount.reduce((prev, curr) => (curr > prev ? curr : prev), 0),
233
+ };
234
+ }
235
+ exports.explainTx = explainTx;
236
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZ0RBQWdEO0FBU2hELG1EQUFvRTtBQUVwRTs7R0FFRztBQUNILFNBQWdCLGVBQWUsQ0FDN0IsT0FBd0MsRUFDeEMsT0FBd0I7SUFFeEIsTUFBTSxJQUFJLEdBQUcsT0FBTyxZQUFZLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3JILE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDL0IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDM0MsSUFBSSxPQUFlLENBQUM7UUFDcEIsSUFBSSxLQUFhLENBQUM7UUFDbEIsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFO1lBQ3JCLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzlFLEtBQUssR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQztTQUNqQzthQUFNLElBQUksS0FBSyxDQUFDLGNBQWMsRUFBRTtZQUMvQixNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLDJCQUEyQixDQUFTLEtBQUssQ0FBQyxjQUFjLEVBQUUsT0FBTyxFQUFFO2dCQUMxRixVQUFVLEVBQUUsUUFBUTthQUNyQixDQUFDLENBQUM7WUFDSCxNQUFNLElBQUksR0FBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJ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STtRQUNGLEVBQUUsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDM0M7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztLQUNwRDtJQUNELE1BQU0sTUFBTSxHQUFHLGFBQWEsQ0FBQyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2RCxNQUFNLG9CQUFvQixHQUFHLHlCQUF5QixDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pGLE9BQU87UUFDTCxHQUFHLE1BQU07UUFDVCxlQUFlLEVBQUUsb0JBQW9CO1FBQ3JDLFVBQVUsRUFBRSxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQzlELENBQUM7QUFDOUIsQ0FBQztBQWxCRCw4QkFrQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tbGliJztcbmltcG9ydCB7IEJpdEdvQmFzZSwgSVJlcXVlc3RUcmFjZXIsIFRyaXBsZSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7XG4gIEFic3RyYWN0VXR4b0NvaW4sXG4gIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMsXG4gIE91dHB1dCxcbiAgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbixcbiAgVHJhbnNhY3Rpb25QcmVidWlsZCxcbn0gZnJvbSAnLi9hYnN0cmFjdFV0eG9Db2luJztcbmltcG9ydCB7IGJpcDMyLCBCSVAzMkludGVyZmFjZSwgYml0Z28gfSBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5cbi8qKlxuICogR2V0IHRoZSBpbnB1dHMgZm9yIGEgcHNidCBmcm9tIGEgcHJlYnVpbGQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQc2J0VHhJbnB1dHMoXG4gIHBzYnRBcmc6IHN0cmluZyB8IHV0eG9saWIuYml0Z28uVXR4b1BzYnQsXG4gIG5ldHdvcms6IHV0eG9saWIuTmV0d29ya1xuKTogeyBhZGRyZXNzOiBzdHJpbmc7IHZhbHVlOiBiaWdpbnQ7IHZhbHVlU3RyaW5nOiBzdHJpbmcgfVtdIHtcbiAgY29uc3QgcHNidCA9IHBzYnRBcmcgaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0ID8gcHNidEFyZyA6IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgocHNidEFyZywgbmV0d29yayk7XG4gIGNvbnN0IHR4SW5wdXRzID0gcHNidC50eElucHV0cztcbiAgcmV0dXJuIHBzYnQuZGF0YS5pbnB1dHMubWFwKChpbnB1dCwgaW5kZXgpID0+IHtcbiAgICBsZXQgYWRkcmVzczogc3RyaW5nO1xuICAgIGxldCB2YWx1ZTogYmlnaW50O1xuICAgIGlmIChpbnB1dC53aXRuZXNzVXR4bykge1xuICAgICAgYWRkcmVzcyA9IHV0eG9saWIuYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KGlucHV0LndpdG5lc3NVdHhvLnNjcmlwdCwgbmV0d29yayk7XG4gICAgICB2YWx1ZSA9IGlucHV0LndpdG5lc3NVdHhvLnZhbHVlO1xuICAgIH0gZWxzZSBpZiAoaW5wdXQubm9uV2l0bmVzc1V0eG8pIHtcbiAgICAgIGNvbnN0IHR4ID0gdXR4b2xpYi5iaXRnby5jcmVhdGVUcmFuc2FjdGlvbkZyb21CdWZmZXI8YmlnaW50PihpbnB1dC5ub25XaXRuZXNzVXR4bywgbmV0d29yaywge1xuICAgICAgICBhbW91bnRUeXBlOiAnYmlnaW50JyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdHhJZCA9IChCdWZmZXIuZnJvbSh0eElucHV0c1tpbmRleF0uaGFzaCkucmV2ZXJzZSgpIGFzIEJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgaWYgKHR4LmdldElkKCkgIT09IHR4SWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0cmFuc2FjdGlvbiBoZXggZG9lcyBub3QgbWF0Y2ggaWQnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHByZXZUeE91dHB1dEluZGV4ID0gdHhJbnB1dHNbaW5kZXhdLmluZGV4O1xuICAgICAgYWRkcmVzcyA9IHV0eG9saWIuYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KHR4Lm91dHNbcHJldlR4T3V0cHV0SW5kZXhdLnNjcmlwdCwgbmV0d29yayk7XG4gICAgICB2YWx1ZSA9IHR4Lm91dHNbcHJldlR4T3V0cHV0SW5kZXhdLnZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BzYnQgaW5wdXQgaXMgbWlzc2luZyBib3RoIHdpdG5lc3NVdHhvIGFuZCBub25XaXRuZXNzVXR4bycpO1xuICAgIH1cbiAgICByZXR1cm4geyBhZGRyZXNzLCB2YWx1ZSwgdmFsdWVTdHJpbmc6IHZhbHVlLnRvU3RyaW5nKCkgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBpbnB1dHMgZm9yIGEgdHJhbnNhY3Rpb24gZnJvbSBhIHByZWJ1aWxkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VHhJbnB1dHM8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4ocGFyYW1zOiB7XG4gIHR4UHJlYnVpbGQ6IFRyYW5zYWN0aW9uUHJlYnVpbGQ8VE51bWJlcj47XG4gIGJpdGdvOiBCaXRHb0Jhc2U7XG4gIGNvaW46IEFic3RyYWN0VXR4b0NvaW47XG4gIGRpc2FibGVOZXR3b3JraW5nOiBib29sZWFuO1xuICByZXFJZD86IElSZXF1ZXN0VHJhY2VyO1xufSk6IFByb21pc2U8eyBhZGRyZXNzOiBzdHJpbmc7IHZhbHVlOiBUTnVtYmVyOyB2YWx1ZVN0cmluZzogc3RyaW5nIH1bXT4ge1xuICBjb25zdCB7IHR4UHJlYnVpbGQsIGJpdGdvLCBjb2luLCBkaXNhYmxlTmV0d29ya2luZywgcmVxSWQgfSA9IHBhcmFtcztcbiAgaWYgKCF0eFByZWJ1aWxkLnR4SGV4KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGB0eFByZWJ1aWxkLnR4SGV4IG5vdCBzZXRgKTtcbiAgfVxuICBjb25zdCB0cmFuc2FjdGlvbiA9IGNvaW4uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4PFROdW1iZXI+KHR4UHJlYnVpbGQudHhIZXgpO1xuICBjb25zdCB0cmFuc2FjdGlvbkNhY2hlID0ge307XG4gIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChcbiAgICB0cmFuc2FjdGlvbi5pbnMubWFwKGFzeW5jIChjdXJyZW50SW5wdXQpOiBQcm9taXNlPHsgYWRkcmVzczogc3RyaW5nOyB2YWx1ZTogVE51bWJlcjsgdmFsdWVTdHJpbmc6IHN0cmluZyB9PiA9PiB7XG4gICAgICBjb25zdCB0cmFuc2FjdGlvbklkID0gKEJ1ZmZlci5mcm9tKGN1cnJlbnRJbnB1dC5oYXNoKS5yZXZlcnNlKCkgYXMgQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCB0eEhleCA9IHR4UHJlYnVpbGQudHhJbmZvPy50eEhleGVzPy5bdHJhbnNhY3Rpb25JZF07XG4gICAgICBpZiAodHhIZXgpIHtcbiAgICAgICAgY29uc3QgbG9jYWxUeCA9IGNvaW4uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4PFROdW1iZXI+KHR4SGV4KTtcbiAgICAgICAgaWYgKGxvY2FsVHguZ2V0SWQoKSAhPT0gdHJhbnNhY3Rpb25JZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgdHJhbnNhY3Rpb24gaGV4IGRvZXMgbm90IG1hdGNoIGlkJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY3VycmVudE91dHB1dCA9IGxvY2FsVHgub3V0c1tjdXJyZW50SW5wdXQuaW5kZXhdO1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gdXR4b2xpYi5hZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoY3VycmVudE91dHB1dC5zY3JpcHQsIGNvaW4ubmV0d29yayk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgICB2YWx1ZTogY3VycmVudE91dHB1dC52YWx1ZSxcbiAgICAgICAgICB2YWx1ZVN0cmluZzogY3VycmVudE91dHB1dC52YWx1ZS50b1N0cmluZygpLFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmICghdHJhbnNhY3Rpb25DYWNoZVt0cmFuc2FjdGlvbklkXSkge1xuICAgICAgICBpZiAoZGlzYWJsZU5ldHdvcmtpbmcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F0dGVtcHRpbmcgdG8gcmV0cmlldmUgdHJhbnNhY3Rpb24gZGV0YWlscyBleHRlcm5hbGx5IHdpdGggbmV0d29ya2luZyBkaXNhYmxlZCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXFJZCkge1xuICAgICAgICAgIGJpdGdvLnNldFJlcXVlc3RUcmFjZXIocmVxSWQpO1xuICAgICAgICB9XG4gICAgICAgIHRyYW5zYWN0aW9uQ2FjaGVbdHJhbnNhY3Rpb25JZF0gPSBhd2FpdCBiaXRnby5nZXQoY29pbi51cmwoYC9wdWJsaWMvdHgvJHt0cmFuc2FjdGlvbklkfWApKS5yZXN1bHQoKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uRGV0YWlscyA9IHRyYW5zYWN0aW9uQ2FjaGVbdHJhbnNhY3Rpb25JZF07XG4gICAgICByZXR1cm4gdHJhbnNhY3Rpb25EZXRhaWxzLm91dHB1dHNbY3VycmVudElucHV0LmluZGV4XTtcbiAgICB9KVxuICApO1xufVxuXG5mdW5jdGlvbiBleHBsYWluQ29tbW9uPFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KFxuICB0eDogYml0Z28uVXR4b1RyYW5zYWN0aW9uPFROdW1iZXI+LFxuICBwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnM8VE51bWJlcj4sXG4gIG5ldHdvcms6IHV0eG9saWIuTmV0d29ya1xuKSB7XG4gIGNvbnN0IGRpc3BsYXlPcmRlciA9IFsnaWQnLCAnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnXTtcbiAgbGV0IHNwZW5kQW1vdW50ID0gQmlnSW50KDApO1xuICBsZXQgY2hhbmdlQW1vdW50ID0gQmlnSW50KDApO1xuICBjb25zdCBjaGFuZ2VPdXRwdXRzOiBPdXRwdXRbXSA9IFtdO1xuICBjb25zdCBvdXRwdXRzOiBPdXRwdXRbXSA9IFtdO1xuXG4gIGNvbnN0IHsgY2hhbmdlQWRkcmVzc2VzID0gW10gfSA9IHBhcmFtcy50eEluZm8gPz8ge307XG5cbiAgdHgub3V0cy5mb3JFYWNoKChjdXJyZW50T3V0cHV0KSA9PiB7XG4gICAgY29uc3QgY3VycmVudEFkZHJlc3MgPSB1dHhvbGliLmFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChjdXJyZW50T3V0cHV0LnNjcmlwdCwgbmV0d29yayk7XG4gICAgY29uc3QgY3VycmVudEFtb3VudCA9IEJpZ0ludChjdXJyZW50T3V0cHV0LnZhbHVlKTtcblxuICAgIGlmIChjaGFuZ2VBZGRyZXNzZXMuaW5jbHVkZXMoY3VycmVudEFkZHJlc3MpKSB7XG4gICAgICAvLyB0aGlzIGlzIGNoYW5nZVxuICAgICAgY2hhbmdlQW1vdW50ICs9IGN1cnJlbnRBbW91bnQ7XG4gICAgICBjaGFuZ2VPdXRwdXRzLnB1c2goe1xuICAgICAgICBhZGRyZXNzOiBjdXJyZW50QWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiBjdXJyZW50QW1vdW50LnRvU3RyaW5nKCksXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzcGVuZEFtb3VudCArPSBjdXJyZW50QW1vdW50O1xuICAgIG91dHB1dHMucHVzaCh7XG4gICAgICBhZGRyZXNzOiBjdXJyZW50QWRkcmVzcyxcbiAgICAgIGFtb3VudDogY3VycmVudEFtb3VudC50b1N0cmluZygpLFxuICAgIH0pO1xuICB9KTtcblxuICBjb25zdCBvdXRwdXREZXRhaWxzID0ge1xuICAgIG91dHB1dEFtb3VudDogc3BlbmRBbW91bnQudG9TdHJpbmcoKSxcbiAgICBjaGFuZ2VBbW91bnQ6IGNoYW5nZUFtb3VudC50b1N0cmluZygpLFxuICAgIG91dHB1dHMsXG4gICAgY2hhbmdlT3V0cHV0cyxcbiAgfTtcblxuICBsZXQgZmVlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBsb2NrdGltZTogbnVtYmVyIHwgdW5kZWZpbmVkO1xuXG4gIGlmIChwYXJhbXMuZmVlSW5mbykge1xuICAgIGRpc3BsYXlPcmRlci5wdXNoKCdmZWUnKTtcbiAgICBmZWUgPSBwYXJhbXMuZmVlSW5mbztcbiAgfVxuXG4gIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHR4LmxvY2t0aW1lKSAmJiB0eC5sb2NrdGltZSA+IDApIHtcbiAgICBkaXNwbGF5T3JkZXIucHVzaCgnbG9ja3RpbWUnKTtcbiAgICBsb2NrdGltZSA9IHR4LmxvY2t0aW1lO1xuICB9XG5cbiAgcmV0dXJuIHsgZGlzcGxheU9yZGVyLCBpZDogdHguZ2V0SWQoKSwgLi4ub3V0cHV0RGV0YWlscywgZmVlLCBsb2NrdGltZSB9O1xufVxuXG5mdW5jdGlvbiBnZXRSb290V2FsbGV0S2V5czxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnM8VE51bWJlcj4pIHtcbiAgY29uc3Qga2V5cyA9IHBhcmFtcy5wdWJzPy5tYXAoKHhwdWIpID0+IGJpcDMyLmZyb21CYXNlNTgoeHB1YikpO1xuICByZXR1cm4ga2V5cyAmJiBrZXlzLmxlbmd0aCA9PT0gMyA/IG5ldyBiaXRnby5Sb290V2FsbGV0S2V5cyhrZXlzIGFzIFRyaXBsZTxCSVAzMkludGVyZmFjZT4pIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBnZXRQc2J0SW5wdXRTaWduYXR1cmVzQ291bnQ8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oXG4gIHBzYnQ6IGJpdGdvLlV0eG9Qc2J0LFxuICBwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnM8VE51bWJlcj5cbikge1xuICBjb25zdCByb290V2FsbGV0S2V5cyA9IGdldFJvb3RXYWxsZXRLZXlzKHBhcmFtcyk7XG4gIHJldHVybiByb290V2FsbGV0S2V5c1xuICAgID8gYml0Z28uZ2V0U2lnbmF0dXJlVmFsaWRhdGlvbkFycmF5UHNidChwc2J0LCByb290V2FsbGV0S2V5cykubWFwKChzdikgPT4gc3ZbMV0uZmlsdGVyKCh2KSA9PiB2KS5sZW5ndGgpXG4gICAgOiAoQXJyYXkocHNidC5kYXRhLmlucHV0cy5sZW5ndGgpIGFzIG51bWJlcltdKS5maWxsKDApO1xufVxuXG5mdW5jdGlvbiBnZXRUeElucHV0U2lnbmF0dXJlc0NvdW50PFROdW1iZXIgZXh0ZW5kcyBudW1iZXIgfCBiaWdpbnQ+KFxuICB0eDogYml0Z28uVXR4b1RyYW5zYWN0aW9uPFROdW1iZXI+LFxuICBwYXJhbXM6IEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnM8VE51bWJlcj4sXG4gIG5ldHdvcms6IHV0eG9saWIuTmV0d29ya1xuKSB7XG4gIGNvbnN0IHByZXZPdXRwdXRzID0gcGFyYW1zLnR4SW5mbz8udW5zcGVudHM/Lm1hcCgodSkgPT4gYml0Z28udG9PdXRwdXQ8VE51bWJlcj4odSwgbmV0d29yaykpO1xuICBjb25zdCByb290V2FsbGV0S2V5cyA9IGdldFJvb3RXYWxsZXRLZXlzKHBhcmFtcyk7XG4gIGNvbnN0IHsgdW5zcGVudHMgPSBbXSB9ID0gcGFyYW1zLnR4SW5mbyA/PyB7fTtcblxuICAvLyBnZXQgdGhlIG51bWJlciBvZiBzaWduYXR1cmVzIHBlciBpbnB1dFxuICByZXR1cm4gdHguaW5zLm1hcCgoaW5wdXQsIGlkeCk6IG51bWJlciA9PiB7XG4gICAgaWYgKHVuc3BlbnRzLmxlbmd0aCAhPT0gdHguaW5zLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmICghcHJldk91dHB1dHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBzdGF0ZWApO1xuICAgIH1cbiAgICBpZiAoIXJvb3RXYWxsZXRLZXlzKSB7XG4gICAgICAvLyBubyBwdWIga2V5cyBvciBpbmNvcnJlY3QgbnVtYmVyIG9mIHB1YiBrZXlzXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBiaXRnby52ZXJpZnlTaWduYXR1cmVXaXRoVW5zcGVudDxUTnVtYmVyPih0eCwgaWR4LCB1bnNwZW50cywgcm9vdFdhbGxldEtleXMpLmZpbHRlcigodikgPT4gdikubGVuZ3RoO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIHNvbWUgb3RoZXIgZXJyb3Igb2NjdXJyZWQgYW5kIHdlIGNhbid0IHZhbGlkYXRlIHRoZSBzaWduYXR1cmVzXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIERlY29tcG9zZSBhIHJhdyBwc2J0IGludG8gdXNlZnVsIGluZm9ybWF0aW9uLCBzdWNoIGFzIHRoZSB0b3RhbCBhbW91bnRzLFxuICogY2hhbmdlIGFtb3VudHMsIGFuZCB0cmFuc2FjdGlvbiBvdXRwdXRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXhwbGFpblBzYnQ8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oXG4gIHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9uczxUTnVtYmVyPixcbiAgbmV0d29yazogdXR4b2xpYi5OZXR3b3JrXG4pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgY29uc3QgeyB0eEhleCB9ID0gcGFyYW1zO1xuICBsZXQgcHNidDogYml0Z28uVXR4b1BzYnQ7XG4gIHRyeSB7XG4gICAgcHNidCA9IGJpdGdvLmNyZWF0ZVBzYnRGcm9tSGV4KHR4SGV4LCBuZXR3b3JrKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZmFpbGVkIHRvIHBhcnNlIHBzYnQgaGV4Jyk7XG4gIH1cbiAgY29uc3QgdHhPdXRwdXRzID0gcHNidC50eE91dHB1dHM7XG4gIGZ1bmN0aW9uIGdldENoYW5nZUFkZHJlc3NlcygpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHV0eG9saWIuYml0Z29cbiAgICAgICAgLmZpbmRJbnRlcm5hbE91dHB1dEluZGljZXMocHNidClcbiAgICAgICAgLm1hcCgoaSkgPT4gdXR4b2xpYi5hZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQodHhPdXRwdXRzW2ldLnNjcmlwdCwgbmV0d29yaykpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlIGluc3RhbmNlb2YgdXR4b2xpYi5iaXRnby5FcnJvck5vTXVsdGlTaWdJbnB1dEZvdW5kKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG4gIGNvbnN0IGNoYW5nZUFkZHJlc3NlcyA9IGdldENoYW5nZUFkZHJlc3NlcygpO1xuICBjb25zdCB0eCA9IHBzYnQuZ2V0VW5zaWduZWRUeCgpIGFzIGJpdGdvLlV0eG9UcmFuc2FjdGlvbjxUTnVtYmVyPjtcbiAgY29uc3QgY29tbW9uID0gZXhwbGFpbkNvbW1vbih0eCwgeyAuLi5wYXJhbXMsIHR4SW5mbzogeyAuLi5wYXJhbXMudHhJbmZvLCBjaGFuZ2VBZGRyZXNzZXMgfSB9LCBuZXR3b3JrKTtcbiAgY29uc3QgaW5wdXRTaWduYXR1cmVzQ291bnQgPSBnZXRQc2J0SW5wdXRTaWduYXR1cmVzQ291bnQocHNidCwgcGFyYW1zKTtcblxuICAvLyBTZXQgZmVlIGZyb20gc3VidHJhY3RpbmcgaW5wdXRzIGZyb20gb3V0cHV0c1xuICBjb25zdCBvdXRwdXRBbW91bnQgPSB0eE91dHB1dHMucmVkdWNlKChjdW11bGF0aXZlLCBjdXJyKSA9PiBjdW11bGF0aXZlICsgQmlnSW50KGN1cnIudmFsdWUpLCBCaWdJbnQoMCkpO1xuICBjb25zdCBpbnB1dEFtb3VudCA9IHBzYnQudHhJbnB1dHMucmVkdWNlKChjdW11bGF0aXZlLCB0eElucHV0LCBpKSA9PiB7XG4gICAgY29uc3QgZGF0YSA9IHBzYnQuZGF0YS5pbnB1dHNbaV07XG4gICAgaWYgKGRhdGEud2l0bmVzc1V0eG8pIHtcbiAgICAgIHJldHVybiBjdW11bGF0aXZlICsgQmlnSW50KGRhdGEud2l0bmVzc1V0eG8udmFsdWUpO1xuICAgIH0gZWxzZSBpZiAoZGF0YS5ub25XaXRuZXNzVXR4bykge1xuICAgICAgY29uc3QgdHggPSBiaXRnby5jcmVhdGVUcmFuc2FjdGlvbkZyb21CdWZmZXI8YmlnaW50PihkYXRhLm5vbldpdG5lc3NVdHhvLCBuZXR3b3JrLCB7IGFtb3VudFR5cGU6ICdiaWdpbnQnIH0pO1xuICAgICAgcmV0dXJuIGN1bXVsYXRpdmUgKyBCaWdJbnQodHgub3V0c1t0eElucHV0LmluZGV4XS52YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IGZpbmQgdmFsdWUgb24gaW5wdXQnKTtcbiAgICB9XG4gIH0sIEJpZ0ludCgwKSk7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5jb21tb24sXG4gICAgZmVlOiAoaW5wdXRBbW91bnQgLSBvdXRwdXRBbW91bnQpLnRvU3RyaW5nKCksXG4gICAgaW5wdXRTaWduYXR1cmVzOiBpbnB1dFNpZ25hdHVyZXNDb3VudCxcbiAgICBzaWduYXR1cmVzOiBpbnB1dFNpZ25hdHVyZXNDb3VudC5yZWR1Y2UoKHByZXYsIGN1cnIpID0+IChjdXJyID4gcHJldiA/IGN1cnIgOiBwcmV2KSwgMCksXG4gIH0gYXMgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbjtcbn1cblxuLyoqXG4gKiBEZWNvbXBvc2UgYSByYXcgdHJhbnNhY3Rpb24gaW50byB1c2VmdWwgaW5mb3JtYXRpb24sIHN1Y2ggYXMgdGhlIHRvdGFsIGFtb3VudHMsXG4gKiBjaGFuZ2UgYW1vdW50cywgYW5kIHRyYW5zYWN0aW9uIG91dHB1dHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHBsYWluVHg8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oXG4gIHBhcmFtczogRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9uczxUTnVtYmVyPixcbiAgY29pbjogQWJzdHJhY3RVdHhvQ29pblxuKTogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiB7XG4gIGNvbnN0IHsgdHhIZXggfSA9IHBhcmFtcztcbiAgbGV0IHR4O1xuICB0cnkge1xuICAgIHR4ID0gY29pbi5jcmVhdGVUcmFuc2FjdGlvbkZyb21IZXgodHhIZXgpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdmYWlsZWQgdG8gcGFyc2UgdHJhbnNhY3Rpb24gaGV4Jyk7XG4gIH1cbiAgY29uc3QgY29tbW9uID0gZXhwbGFpbkNvbW1vbih0eCwgcGFyYW1zLCBjb2luLm5ldHdvcmspO1xuICBjb25zdCBpbnB1dFNpZ25hdHVyZXNDb3VudCA9IGdldFR4SW5wdXRTaWduYXR1cmVzQ291bnQodHgsIHBhcmFtcywgY29pbi5uZXR3b3JrKTtcbiAgcmV0dXJuIHtcbiAgICAuLi5jb21tb24sXG4gICAgaW5wdXRTaWduYXR1cmVzOiBpbnB1dFNpZ25hdHVyZXNDb3VudCxcbiAgICBzaWduYXR1cmVzOiBpbnB1dFNpZ25hdHVyZXNDb3VudC5yZWR1Y2UoKHByZXYsIGN1cnIpID0+IChjdXJyID4gcHJldiA/IGN1cnIgOiBwcmV2KSwgMCksXG4gIH0gYXMgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbjtcbn1cbiJdfQ==