@bitgo-beta/sdk-coin-flr 1.0.1-beta.82 → 1.0.1-beta.821
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/dist/src/flr.d.ts +145 -3
- package/dist/src/flr.d.ts.map +1 -1
- package/dist/src/flr.js +464 -3
- package/dist/src/flrToken.d.ts +26 -0
- package/dist/src/flrToken.d.ts.map +1 -0
- package/dist/src/flrToken.js +49 -0
- package/dist/src/iface.d.ts +148 -0
- package/dist/src/iface.d.ts.map +1 -0
- package/dist/src/iface.js +3 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/lib/transactionBuilder.d.ts +2 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/transactionBuilder.js +5 -1
- package/dist/src/register.d.ts.map +1 -1
- package/dist/src/register.js +5 -1
- package/dist/test/resources.d.ts +42 -0
- package/dist/test/resources.d.ts.map +1 -0
- package/dist/test/resources.js +117 -0
- package/dist/test/unit/flr.d.ts +2 -0
- package/dist/test/unit/flr.d.ts.map +1 -0
- package/dist/test/unit/flr.js +1040 -0
- package/dist/test/unit/flrToken.d.ts +2 -0
- package/dist/test/unit/flrToken.d.ts.map +1 -0
- package/dist/test/unit/flrToken.js +30 -0
- package/dist/test/unit/getBuilder.d.ts +3 -0
- package/dist/test/unit/getBuilder.d.ts.map +1 -0
- package/dist/test/unit/getBuilder.js +10 -0
- package/dist/test/unit/transactionBuilder/send.d.ts +2 -0
- package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder/send.js +19 -0
- package/dist/test/unit/utils.d.ts +2 -0
- package/dist/test/unit/utils.d.ts.map +1 -0
- package/dist/test/unit/utils.js +29 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +22 -10
- package/.eslintignore +0 -5
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -44
|
@@ -0,0 +1,1040 @@
|
|
|
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
|
+
const should = __importStar(require("should"));
|
|
40
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
41
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
42
|
+
const index_1 = require("../../src/index");
|
|
43
|
+
const resources_1 = require("../resources");
|
|
44
|
+
const nock_1 = __importDefault(require("nock"));
|
|
45
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
46
|
+
const tx_1 = require("@ethereumjs/tx");
|
|
47
|
+
const util_1 = require("@ethereumjs/util");
|
|
48
|
+
const sinon = __importStar(require("sinon"));
|
|
49
|
+
const secp256k1_1 = require("@bitgo-beta/secp256k1");
|
|
50
|
+
const secp256k1 = __importStar(require("secp256k1"));
|
|
51
|
+
const keccak_1 = __importDefault(require("keccak"));
|
|
52
|
+
// Helper to calculate tx hash like Flr.getTxHash
|
|
53
|
+
function getTxHash(tx) {
|
|
54
|
+
const hash = (0, keccak_1.default)('keccak256');
|
|
55
|
+
hash.update(tx.startsWith('0x') ? tx.slice(2) : tx, 'hex');
|
|
56
|
+
return hash.digest();
|
|
57
|
+
}
|
|
58
|
+
describe('flr', function () {
|
|
59
|
+
let bitgo;
|
|
60
|
+
let tflrCoin;
|
|
61
|
+
let flrCoin;
|
|
62
|
+
let hopExportTxBitgoSignature;
|
|
63
|
+
const address2 = '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6';
|
|
64
|
+
const hopExportTx = resources_1.EXPORT_C_TEST_DATA.fullsigntxHex;
|
|
65
|
+
const hopExportTxId = '0x' + getTxHash(hopExportTx).toString('hex');
|
|
66
|
+
before(function () {
|
|
67
|
+
const bitgoKeyXprv = 'xprv9s21ZrQH143K3tpWBHWe31sLoXNRQ9AvRYJgitkKxQ4ATFQMwvr7hHNqYRUnS7PsjzB7aK1VxqHLuNQjj1sckJ2Jwo2qxmsvejwECSpFMfC';
|
|
68
|
+
const bitgoKey = secp256k1_1.bip32.fromBase58(bitgoKeyXprv);
|
|
69
|
+
if (!bitgoKey.privateKey) {
|
|
70
|
+
throw new Error('no privateKey');
|
|
71
|
+
}
|
|
72
|
+
const bitgoXpub = bitgoKey.neutered().toBase58();
|
|
73
|
+
hopExportTxBitgoSignature =
|
|
74
|
+
'0xaa' +
|
|
75
|
+
Buffer.from(secp256k1.ecdsaSign(Buffer.from(hopExportTxId.slice(2), 'hex'), bitgoKey.privateKey).signature).toString('hex');
|
|
76
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
77
|
+
bitgo.safeRegister('flr', index_1.Flr.createInstance);
|
|
78
|
+
bitgo.safeRegister('tflr', index_1.Tflr.createInstance);
|
|
79
|
+
sdk_core_1.common.Environments[bitgo.getEnv()].hsmXpub = bitgoXpub;
|
|
80
|
+
bitgo.initializeTestVars();
|
|
81
|
+
});
|
|
82
|
+
beforeEach(function () {
|
|
83
|
+
tflrCoin = bitgo.coin('tflr');
|
|
84
|
+
flrCoin = bitgo.coin('flr');
|
|
85
|
+
});
|
|
86
|
+
describe('Basic Coin Info', function () {
|
|
87
|
+
it('should return the right info for flr', function () {
|
|
88
|
+
const flr = bitgo.coin('flr');
|
|
89
|
+
flr.should.be.an.instanceof(index_1.Flr);
|
|
90
|
+
flr.getChain().should.equal('flr');
|
|
91
|
+
flr.getFamily().should.equal('flr');
|
|
92
|
+
flr.getFullName().should.equal('Flare');
|
|
93
|
+
flr.getBaseFactor().should.equal(1e18);
|
|
94
|
+
flr.supportsTss().should.equal(true);
|
|
95
|
+
flr.allowsAccountConsolidations().should.equal(false);
|
|
96
|
+
});
|
|
97
|
+
it('should return the right info for tflr', function () {
|
|
98
|
+
const tflr = bitgo.coin('tflr');
|
|
99
|
+
tflr.should.be.an.instanceof(index_1.Tflr);
|
|
100
|
+
tflr.getChain().should.equal('tflr');
|
|
101
|
+
tflr.getFamily().should.equal('flr');
|
|
102
|
+
tflr.getFullName().should.equal('Testnet flare');
|
|
103
|
+
tflr.getBaseFactor().should.equal(1e18);
|
|
104
|
+
tflr.supportsTss().should.equal(true);
|
|
105
|
+
tflr.allowsAccountConsolidations().should.equal(false);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('P-Chain Methods', function () {
|
|
109
|
+
it('should return flrp for mainnet', function () {
|
|
110
|
+
flrCoin.getFlrP().should.equal('flrp');
|
|
111
|
+
});
|
|
112
|
+
it('should return tflrp for testnet', function () {
|
|
113
|
+
tflrCoin.getFlrP().should.equal('tflrp');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('Address Validation', function () {
|
|
117
|
+
it('should validate valid eth address', function () {
|
|
118
|
+
const address = '0x1374a2046661f914d1687d85dbbceb9ac7910a29';
|
|
119
|
+
tflrCoin.isValidAddress(address).should.be.true();
|
|
120
|
+
flrCoin.isValidAddress(address).should.be.true();
|
|
121
|
+
});
|
|
122
|
+
it('should validate a P-chain address', function () {
|
|
123
|
+
const pAddresses = resources_1.EXPORT_C_TEST_DATA.pAddresses;
|
|
124
|
+
for (const addr of pAddresses) {
|
|
125
|
+
tflrCoin.isValidAddress(addr).should.be.true();
|
|
126
|
+
flrCoin.isValidAddress(addr).should.be.true();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
it('should validate a P-chain multisig address string', function () {
|
|
130
|
+
const address = resources_1.EXPORT_C_TEST_DATA.pMultisigAddress;
|
|
131
|
+
tflrCoin.isValidAddress(address).should.be.true();
|
|
132
|
+
flrCoin.isValidAddress(address).should.be.true();
|
|
133
|
+
});
|
|
134
|
+
it('should return false for empty address', function () {
|
|
135
|
+
tflrCoin.isValidAddress('').should.be.false();
|
|
136
|
+
flrCoin.isValidAddress('').should.be.false();
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe('Token Check', function () {
|
|
140
|
+
it('should return false for isToken', function () {
|
|
141
|
+
tflrCoin.isToken().should.be.false();
|
|
142
|
+
flrCoin.isToken().should.be.false();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
describe('Hop Transaction Parameters', function () {
|
|
146
|
+
const sandbox = sinon.createSandbox();
|
|
147
|
+
afterEach(function () {
|
|
148
|
+
sandbox.restore();
|
|
149
|
+
});
|
|
150
|
+
it('should create hop transaction parameters with gasPriceMax > 0', async function () {
|
|
151
|
+
const mockFeeEstimate = {
|
|
152
|
+
feeEstimate: 120000,
|
|
153
|
+
gasLimitEstimate: 500000,
|
|
154
|
+
};
|
|
155
|
+
sandbox.stub(tflrCoin, 'feeEstimate').resolves(mockFeeEstimate);
|
|
156
|
+
const recipients = [
|
|
157
|
+
{
|
|
158
|
+
address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
159
|
+
amount: '100000000000000000',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
const result = await tflrCoin.createHopTransactionParams({
|
|
163
|
+
recipients,
|
|
164
|
+
type: 'Export',
|
|
165
|
+
});
|
|
166
|
+
result.should.have.property('hopParams');
|
|
167
|
+
result.hopParams.should.have.properties(['userReqSig', 'gasPriceMax', 'paymentId', 'gasLimit']);
|
|
168
|
+
result.hopParams.userReqSig.should.equal('0x');
|
|
169
|
+
result.hopParams.gasPriceMax.should.be.above(0);
|
|
170
|
+
result.hopParams.paymentId.should.be.a.String();
|
|
171
|
+
result.hopParams.gasLimit.should.equal(500000);
|
|
172
|
+
});
|
|
173
|
+
it('should throw error if no recipients provided', async function () {
|
|
174
|
+
await tflrCoin
|
|
175
|
+
.createHopTransactionParams({
|
|
176
|
+
recipients: [],
|
|
177
|
+
type: 'Export',
|
|
178
|
+
})
|
|
179
|
+
.should.be.rejectedWith('must send to exactly 1 recipient');
|
|
180
|
+
});
|
|
181
|
+
it('should throw error if more than 1 recipient provided', async function () {
|
|
182
|
+
const recipients = [
|
|
183
|
+
{
|
|
184
|
+
address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
185
|
+
amount: '100000000000000000',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
address: resources_1.EXPORT_C_TEST_DATA.cHexAddress,
|
|
189
|
+
amount: '50000000000000000',
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
await tflrCoin
|
|
193
|
+
.createHopTransactionParams({
|
|
194
|
+
recipients,
|
|
195
|
+
type: 'Export',
|
|
196
|
+
})
|
|
197
|
+
.should.be.rejectedWith('must send to exactly 1 recipient');
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('Explain Transaction', function () {
|
|
201
|
+
it('should explain an unsigned export in C transaction', async function () {
|
|
202
|
+
const testData = resources_1.EXPORT_C_TEST_DATA;
|
|
203
|
+
const txExplain = await tflrCoin.explainTransaction({
|
|
204
|
+
txHex: testData.unsignedTxHex,
|
|
205
|
+
crossChainType: 'export',
|
|
206
|
+
});
|
|
207
|
+
txExplain.type.should.equal(sdk_core_1.TransactionType.Export);
|
|
208
|
+
txExplain.inputs[0].address.toLowerCase().should.equal(testData.cHexAddress.toLowerCase());
|
|
209
|
+
// Output address is the sorted P-chain addresses joined with ~
|
|
210
|
+
const sortedPAddresses = testData.pAddresses.slice().sort().join('~');
|
|
211
|
+
txExplain.outputs[0].address.should.equal(sortedPAddresses);
|
|
212
|
+
txExplain.outputAmount.should.equal(testData.amount);
|
|
213
|
+
should.exist(txExplain.fee);
|
|
214
|
+
txExplain.fee.fee.should.equal(testData.fee);
|
|
215
|
+
txExplain.changeOutputs.should.be.empty();
|
|
216
|
+
});
|
|
217
|
+
it('should explain a signed export in C transaction', async function () {
|
|
218
|
+
const testData = resources_1.EXPORT_C_TEST_DATA;
|
|
219
|
+
const txExplain = await tflrCoin.explainTransaction({
|
|
220
|
+
txHex: testData.fullsigntxHex,
|
|
221
|
+
crossChainType: 'export',
|
|
222
|
+
});
|
|
223
|
+
txExplain.type.should.equal(sdk_core_1.TransactionType.Export);
|
|
224
|
+
txExplain.inputs[0].address.toLowerCase().should.equal(testData.cHexAddress.toLowerCase());
|
|
225
|
+
// Output address is the sorted P-chain addresses joined with ~
|
|
226
|
+
const sortedPAddresses = testData.pAddresses.slice().sort().join('~');
|
|
227
|
+
txExplain.outputs[0].address.should.equal(sortedPAddresses);
|
|
228
|
+
txExplain.outputAmount.should.equal(testData.amount);
|
|
229
|
+
should.exist(txExplain.fee);
|
|
230
|
+
txExplain.fee.fee.should.equal(testData.fee);
|
|
231
|
+
txExplain.changeOutputs.should.be.empty();
|
|
232
|
+
});
|
|
233
|
+
it('should throw error when missing txHex', async function () {
|
|
234
|
+
await tflrCoin
|
|
235
|
+
.explainTransaction({ crossChainType: 'export' })
|
|
236
|
+
.should.be.rejectedWith('missing txHex in explain tx parameters');
|
|
237
|
+
});
|
|
238
|
+
it('should throw error when missing feeInfo for non-crossChain transaction', async function () {
|
|
239
|
+
await tflrCoin
|
|
240
|
+
.explainTransaction({ txHex: '0x123' })
|
|
241
|
+
.should.be.rejectedWith('missing feeInfo in explain tx parameters');
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
describe('Transaction Verification', function () {
|
|
245
|
+
it('should reject when client txParams are missing', async function () {
|
|
246
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
247
|
+
const txParams = null;
|
|
248
|
+
const txPrebuild = {
|
|
249
|
+
recipients: [{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' }],
|
|
250
|
+
nextContractSequenceId: 0,
|
|
251
|
+
gasPrice: 20000000000,
|
|
252
|
+
gasLimit: 500000,
|
|
253
|
+
isBatch: false,
|
|
254
|
+
coin: 'tflr',
|
|
255
|
+
walletId: 'fakeWalletId',
|
|
256
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
257
|
+
};
|
|
258
|
+
const verification = {};
|
|
259
|
+
await tflrCoin
|
|
260
|
+
.verifyTransaction({ txParams: txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
261
|
+
.should.be.rejectedWith('missing params');
|
|
262
|
+
});
|
|
263
|
+
it('should reject txPrebuild that is both batch and hop', async function () {
|
|
264
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
265
|
+
const txParams = {
|
|
266
|
+
recipients: [
|
|
267
|
+
{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' },
|
|
268
|
+
{ amount: '2500000000000', address: '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6' },
|
|
269
|
+
],
|
|
270
|
+
wallet: wallet,
|
|
271
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
272
|
+
hop: true,
|
|
273
|
+
};
|
|
274
|
+
const txPrebuild = {
|
|
275
|
+
recipients: [{ amount: '3500000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' }],
|
|
276
|
+
nextContractSequenceId: 0,
|
|
277
|
+
gasPrice: 20000000000,
|
|
278
|
+
gasLimit: 500000,
|
|
279
|
+
isBatch: true,
|
|
280
|
+
coin: 'tflr',
|
|
281
|
+
walletId: 'fakeWalletId',
|
|
282
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
283
|
+
hopTransaction: {
|
|
284
|
+
tx: '0x0',
|
|
285
|
+
id: '0x0',
|
|
286
|
+
signature: '0x0',
|
|
287
|
+
paymentId: '0',
|
|
288
|
+
gasPrice: 20000000000,
|
|
289
|
+
gasLimit: 500000,
|
|
290
|
+
amount: 1000000000000000,
|
|
291
|
+
recipient: '0x1374a2046661f914d1687d85dbbceb9ac7910a29',
|
|
292
|
+
nonce: 0,
|
|
293
|
+
userReqSig: '0x0',
|
|
294
|
+
gasPriceMax: 500000000000,
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
const verification = {};
|
|
298
|
+
await tflrCoin
|
|
299
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
300
|
+
.should.be.rejectedWith('tx cannot be both a batch and hop transaction');
|
|
301
|
+
});
|
|
302
|
+
it('should reject a txPrebuild with more than one recipient', async function () {
|
|
303
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
304
|
+
const txParams = {
|
|
305
|
+
recipients: [
|
|
306
|
+
{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' },
|
|
307
|
+
{ amount: '2500000000000', address: '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6' },
|
|
308
|
+
],
|
|
309
|
+
wallet: wallet,
|
|
310
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
311
|
+
};
|
|
312
|
+
const txPrebuild = {
|
|
313
|
+
recipients: [
|
|
314
|
+
{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' },
|
|
315
|
+
{ amount: '2500000000000', address: '0x7e85bdc27c050e3905ebf4b8e634d9ad6edd0de6' },
|
|
316
|
+
],
|
|
317
|
+
nextContractSequenceId: 0,
|
|
318
|
+
gasPrice: 20000000000,
|
|
319
|
+
gasLimit: 500000,
|
|
320
|
+
isBatch: true,
|
|
321
|
+
coin: 'tflr',
|
|
322
|
+
walletId: 'fakeWalletId',
|
|
323
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
324
|
+
};
|
|
325
|
+
const verification = {};
|
|
326
|
+
await tflrCoin
|
|
327
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
328
|
+
.should.be.rejectedWith(`tflr doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
|
|
329
|
+
});
|
|
330
|
+
it('should reject a txPrebuild from the bitgo server with the wrong coin', async function () {
|
|
331
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
332
|
+
const txParams = {
|
|
333
|
+
recipients: [{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' }],
|
|
334
|
+
wallet: wallet,
|
|
335
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
336
|
+
};
|
|
337
|
+
const txPrebuild = {
|
|
338
|
+
recipients: [{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' }],
|
|
339
|
+
nextContractSequenceId: 0,
|
|
340
|
+
gasPrice: 20000000000,
|
|
341
|
+
gasLimit: 500000,
|
|
342
|
+
isBatch: false,
|
|
343
|
+
coin: 'btc',
|
|
344
|
+
walletId: 'fakeWalletId',
|
|
345
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
346
|
+
};
|
|
347
|
+
const verification = {};
|
|
348
|
+
await tflrCoin
|
|
349
|
+
.verifyTransaction({ txParams, txPrebuild: txPrebuild, wallet, verification })
|
|
350
|
+
.should.be.rejectedWith('coin in txPrebuild did not match that in txParams supplied by client');
|
|
351
|
+
});
|
|
352
|
+
describe('TSS Transaction Verification', function () {
|
|
353
|
+
it('should verify a TSS transfer transaction without txPrebuild.recipients', async function () {
|
|
354
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
355
|
+
const txParams = {
|
|
356
|
+
recipients: [{ amount: '100000000000000000', address: '0x4e1e3d4856ad8b33352eb3add5ff12ea3206169a' }],
|
|
357
|
+
type: 'transfer',
|
|
358
|
+
isTss: true,
|
|
359
|
+
};
|
|
360
|
+
// TSS txPrebuild typically has buildParams.recipients but not recipients directly
|
|
361
|
+
const txPrebuild = {
|
|
362
|
+
walletId: 'fakeWalletId',
|
|
363
|
+
txRequestId: 'fake-tx-request-id',
|
|
364
|
+
txHex: '02f17281d902850ba43b740283061a80944e1e3d4856ad8b33352eb3add5ff12ea3206169a88016345785d8a000080c0808080',
|
|
365
|
+
buildParams: {
|
|
366
|
+
apiVersion: 'full',
|
|
367
|
+
recipients: [{ address: '0x4e1e3d4856ad8b33352eb3add5ff12ea3206169a', amount: '100000000000000000' }],
|
|
368
|
+
type: 'transfer',
|
|
369
|
+
},
|
|
370
|
+
feeInfo: { fee: 10000000000800000, feeString: '10000000000800000' },
|
|
371
|
+
coin: 'tflr',
|
|
372
|
+
};
|
|
373
|
+
const verification = {};
|
|
374
|
+
// When walletType is 'tss', it should delegate to parent's verifyTransaction
|
|
375
|
+
// which handles TSS transactions without requiring txPrebuild.recipients
|
|
376
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction({
|
|
377
|
+
txParams,
|
|
378
|
+
txPrebuild: txPrebuild,
|
|
379
|
+
wallet,
|
|
380
|
+
verification,
|
|
381
|
+
walletType: 'tss',
|
|
382
|
+
});
|
|
383
|
+
isTransactionVerified.should.equal(true);
|
|
384
|
+
});
|
|
385
|
+
it('should verify TSS consolidation transaction when txPrebuild has consolidateId', async function () {
|
|
386
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {
|
|
387
|
+
coinSpecific: {
|
|
388
|
+
baseAddress: '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be',
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
// txParams without recipients (as in consolidation flow)
|
|
392
|
+
const txParams = {
|
|
393
|
+
wallet: wallet,
|
|
394
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
395
|
+
};
|
|
396
|
+
// txPrebuild with consolidateId (set by server during consolidation build)
|
|
397
|
+
const txPrebuild = {
|
|
398
|
+
consolidateId: '68a7d5d0c66e74e216b97173bd558c6d',
|
|
399
|
+
txHex: '0x',
|
|
400
|
+
coin: 'tflr',
|
|
401
|
+
walletId: 'fakeWalletId',
|
|
402
|
+
};
|
|
403
|
+
const verification = {};
|
|
404
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction({
|
|
405
|
+
txParams: txParams,
|
|
406
|
+
txPrebuild: txPrebuild,
|
|
407
|
+
wallet,
|
|
408
|
+
verification,
|
|
409
|
+
walletType: 'tss',
|
|
410
|
+
});
|
|
411
|
+
isTransactionVerified.should.equal(true);
|
|
412
|
+
});
|
|
413
|
+
it('should verify TSS transaction when txParams.type is consolidate', async function () {
|
|
414
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {
|
|
415
|
+
coinSpecific: {
|
|
416
|
+
baseAddress: '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be',
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
const txParams = {
|
|
420
|
+
type: 'consolidate',
|
|
421
|
+
wallet: wallet,
|
|
422
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
423
|
+
};
|
|
424
|
+
const txPrebuild = {
|
|
425
|
+
txHex: '0x',
|
|
426
|
+
coin: 'tflr',
|
|
427
|
+
walletId: 'fakeWalletId',
|
|
428
|
+
};
|
|
429
|
+
const verification = {};
|
|
430
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction({
|
|
431
|
+
txParams: txParams,
|
|
432
|
+
txPrebuild: txPrebuild,
|
|
433
|
+
wallet,
|
|
434
|
+
verification,
|
|
435
|
+
walletType: 'tss',
|
|
436
|
+
});
|
|
437
|
+
isTransactionVerified.should.equal(true);
|
|
438
|
+
});
|
|
439
|
+
it('should verify TSS transaction with acceleration type', async function () {
|
|
440
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {
|
|
441
|
+
coinSpecific: {
|
|
442
|
+
baseAddress: '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be',
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
const txParams = {
|
|
446
|
+
type: 'acceleration',
|
|
447
|
+
wallet: wallet,
|
|
448
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
449
|
+
};
|
|
450
|
+
const txPrebuild = {
|
|
451
|
+
txHex: '0x',
|
|
452
|
+
coin: 'tflr',
|
|
453
|
+
walletId: 'fakeWalletId',
|
|
454
|
+
};
|
|
455
|
+
const verification = {};
|
|
456
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction({
|
|
457
|
+
txParams: txParams,
|
|
458
|
+
txPrebuild: txPrebuild,
|
|
459
|
+
wallet,
|
|
460
|
+
verification,
|
|
461
|
+
walletType: 'tss',
|
|
462
|
+
});
|
|
463
|
+
isTransactionVerified.should.equal(true);
|
|
464
|
+
});
|
|
465
|
+
it('should verify TSS transaction with fillNonce type', async function () {
|
|
466
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {
|
|
467
|
+
coinSpecific: {
|
|
468
|
+
baseAddress: '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be',
|
|
469
|
+
},
|
|
470
|
+
});
|
|
471
|
+
const txParams = {
|
|
472
|
+
type: 'fillNonce',
|
|
473
|
+
wallet: wallet,
|
|
474
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
475
|
+
};
|
|
476
|
+
const txPrebuild = {
|
|
477
|
+
txHex: '0x',
|
|
478
|
+
coin: 'tflr',
|
|
479
|
+
walletId: 'fakeWalletId',
|
|
480
|
+
};
|
|
481
|
+
const verification = {};
|
|
482
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction({
|
|
483
|
+
txParams: txParams,
|
|
484
|
+
txPrebuild: txPrebuild,
|
|
485
|
+
wallet,
|
|
486
|
+
verification,
|
|
487
|
+
walletType: 'tss',
|
|
488
|
+
});
|
|
489
|
+
isTransactionVerified.should.equal(true);
|
|
490
|
+
});
|
|
491
|
+
it('should reject TSS transaction without recipients, consolidateId, or valid type', async function () {
|
|
492
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {
|
|
493
|
+
coinSpecific: {
|
|
494
|
+
baseAddress: '0x174cfd823af8ce27ed0afee3fcf3c3ba259116be',
|
|
495
|
+
},
|
|
496
|
+
});
|
|
497
|
+
const txParams = {
|
|
498
|
+
wallet: wallet,
|
|
499
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
500
|
+
};
|
|
501
|
+
const txPrebuild = {
|
|
502
|
+
txHex: '0x',
|
|
503
|
+
coin: 'tflr',
|
|
504
|
+
walletId: 'fakeWalletId',
|
|
505
|
+
};
|
|
506
|
+
const verification = {};
|
|
507
|
+
await tflrCoin
|
|
508
|
+
.verifyTransaction({
|
|
509
|
+
txParams: txParams,
|
|
510
|
+
txPrebuild: txPrebuild,
|
|
511
|
+
wallet,
|
|
512
|
+
verification,
|
|
513
|
+
walletType: 'tss',
|
|
514
|
+
})
|
|
515
|
+
.should.be.rejectedWith('missing txParams');
|
|
516
|
+
});
|
|
517
|
+
it('should still use FLR-specific verification for non-TSS wallets', async function () {
|
|
518
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
519
|
+
const txParams = {
|
|
520
|
+
recipients: [{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' }],
|
|
521
|
+
wallet: wallet,
|
|
522
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
523
|
+
};
|
|
524
|
+
const txPrebuild = {
|
|
525
|
+
recipients: [{ amount: '1000000000000', address: '0x1374a2046661f914d1687d85dbbceb9ac7910a29' }],
|
|
526
|
+
nextContractSequenceId: 0,
|
|
527
|
+
gasPrice: 20000000000,
|
|
528
|
+
gasLimit: 500000,
|
|
529
|
+
isBatch: false,
|
|
530
|
+
coin: 'tflr',
|
|
531
|
+
walletId: 'fakeWalletId',
|
|
532
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
533
|
+
};
|
|
534
|
+
const verification = {};
|
|
535
|
+
// Without walletType or with walletType: 'onchain', should use FLR's own verification
|
|
536
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction({
|
|
537
|
+
txParams,
|
|
538
|
+
txPrebuild: txPrebuild,
|
|
539
|
+
wallet,
|
|
540
|
+
verification,
|
|
541
|
+
walletType: 'onchain',
|
|
542
|
+
});
|
|
543
|
+
isTransactionVerified.should.equal(true);
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
describe('Hop export tx verify', () => {
|
|
547
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
548
|
+
const hopDestinationAddress = 'P-costwo15msvr27szvhhpmah0c38gcml7vm29xjh7tcek8~P-costwo1cwrdtrgf4xh80ncu7palrjw7gn4mpj0n4dxghh~P-costwo1zt9n96hey4fsvnde35n3k4kt5pu7c784dzewzd';
|
|
549
|
+
const hopAddress = '0x28A05933dC76e4e6c25f35D5c9b2A58769700E76';
|
|
550
|
+
const importTxFee = 1e6;
|
|
551
|
+
const amount = 49000000000000000;
|
|
552
|
+
const txParams = {
|
|
553
|
+
recipients: [{ amount, address: hopDestinationAddress }],
|
|
554
|
+
wallet: wallet,
|
|
555
|
+
walletPassphrase: 'fakeWalletPassphrase',
|
|
556
|
+
hop: true,
|
|
557
|
+
type: 'Export',
|
|
558
|
+
};
|
|
559
|
+
const txPrebuild = {
|
|
560
|
+
recipients: [{ amount: '51000050000000000', address: hopAddress }],
|
|
561
|
+
nextContractSequenceId: 0,
|
|
562
|
+
gasPrice: 20000000000,
|
|
563
|
+
gasLimit: 500000,
|
|
564
|
+
isBatch: false,
|
|
565
|
+
coin: 'tflr',
|
|
566
|
+
walletId: 'fakeWalletId',
|
|
567
|
+
walletContractAddress: 'fakeWalletContractAddress',
|
|
568
|
+
hopTransaction: {
|
|
569
|
+
tx: hopExportTx,
|
|
570
|
+
id: hopExportTxId,
|
|
571
|
+
signature: hopExportTxBitgoSignature,
|
|
572
|
+
paymentId: '4933349984',
|
|
573
|
+
gasPrice: '50',
|
|
574
|
+
gasLimit: 1,
|
|
575
|
+
amount: '50000000',
|
|
576
|
+
recipient: hopDestinationAddress,
|
|
577
|
+
nonce: 0,
|
|
578
|
+
userReqSig: '0x06fd0b1f8859a40d9fb2d1a65d54da5d645a1d81bbb8c1c5b037051843ec0d3c22433ec7f50cc97fa041cbf8d9ff5ddf7ed41f72a08fa3f1983fd651a33a4441',
|
|
579
|
+
gasPriceMax: 7187500000,
|
|
580
|
+
type: 'Export',
|
|
581
|
+
},
|
|
582
|
+
};
|
|
583
|
+
const verification = {};
|
|
584
|
+
const sandbox = sinon.createSandbox();
|
|
585
|
+
before(() => {
|
|
586
|
+
txPrebuild.hopTransaction.signature = hopExportTxBitgoSignature;
|
|
587
|
+
});
|
|
588
|
+
beforeEach(() => {
|
|
589
|
+
sandbox.stub(tflrCoin, 'verifySignatureForAtomicTransaction').resolves(true);
|
|
590
|
+
});
|
|
591
|
+
afterEach(() => {
|
|
592
|
+
sandbox.restore();
|
|
593
|
+
});
|
|
594
|
+
it('should verify successfully', async function () {
|
|
595
|
+
const verifyFlrTransactionOptions = { txParams, txPrebuild, wallet, verification };
|
|
596
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction(verifyFlrTransactionOptions);
|
|
597
|
+
isTransactionVerified.should.equal(true);
|
|
598
|
+
});
|
|
599
|
+
it('should fail verify for amount plus 1', async function () {
|
|
600
|
+
const verifyFlrTransactionOptions = {
|
|
601
|
+
txParams: { ...txParams, recipients: [{ amount: amount + 1e9, address: hopDestinationAddress }] },
|
|
602
|
+
txPrebuild,
|
|
603
|
+
wallet,
|
|
604
|
+
verification,
|
|
605
|
+
};
|
|
606
|
+
await tflrCoin
|
|
607
|
+
.verifyTransaction(verifyFlrTransactionOptions)
|
|
608
|
+
.should.be.rejectedWith(`Hop amount: ${amount / 1e9 + importTxFee} does not equal original amount: ${amount / 1e9 + importTxFee + 1}`);
|
|
609
|
+
});
|
|
610
|
+
it('should fail verify for changed prebuild hop address', async function () {
|
|
611
|
+
const verifyFlrTransactionOptions = {
|
|
612
|
+
txParams,
|
|
613
|
+
txPrebuild: { ...txPrebuild, recipients: [{ address: address2, amount: '51000050000000000' }] },
|
|
614
|
+
wallet,
|
|
615
|
+
verification,
|
|
616
|
+
};
|
|
617
|
+
await tflrCoin
|
|
618
|
+
.verifyTransaction(verifyFlrTransactionOptions)
|
|
619
|
+
.should.be.rejectedWith(`recipient address of txPrebuild does not match hop address`);
|
|
620
|
+
});
|
|
621
|
+
it('should fail verify for changed address', async function () {
|
|
622
|
+
const hopDestinationAddressDiff = 'P-costwo15msvr27szvhhpmah0c38gcml7vm29xjh7tcek9~P-costwo1cwrdtrgf4xh80ncu7palrjw7gn4mpj0n4dxghh~P-costwo1zt9n96hey4fsvnde35n3k4kt5pu7c784dzewzd';
|
|
623
|
+
const verifyFlrTransactionOptions = {
|
|
624
|
+
txParams: { ...txParams, recipients: [{ amount: amount, address: hopDestinationAddressDiff }] },
|
|
625
|
+
txPrebuild,
|
|
626
|
+
wallet,
|
|
627
|
+
verification,
|
|
628
|
+
};
|
|
629
|
+
await tflrCoin
|
|
630
|
+
.verifyTransaction(verifyFlrTransactionOptions)
|
|
631
|
+
.should.be.rejectedWith(`Hop destination: ${hopDestinationAddress} does not equal original recipient: ${hopDestinationAddressDiff}`);
|
|
632
|
+
});
|
|
633
|
+
it('should verify if walletId is used instead of address', async function () {
|
|
634
|
+
const verifyFlrTransactionOptions = {
|
|
635
|
+
txParams: { ...txParams, recipients: [{ amount: amount, walletId: 'same wallet' }] },
|
|
636
|
+
txPrebuild,
|
|
637
|
+
wallet,
|
|
638
|
+
verification,
|
|
639
|
+
};
|
|
640
|
+
const isTransactionVerified = await tflrCoin.verifyTransaction(verifyFlrTransactionOptions);
|
|
641
|
+
isTransactionVerified.should.equal(true);
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
});
|
|
645
|
+
describe('validateHopPrebuild', function () {
|
|
646
|
+
const validateHopSandbox = sinon.createSandbox();
|
|
647
|
+
afterEach(() => {
|
|
648
|
+
validateHopSandbox.restore();
|
|
649
|
+
});
|
|
650
|
+
it('should throw error for invalid HSM signature', async function () {
|
|
651
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
652
|
+
const hopPrebuild = {
|
|
653
|
+
tx: hopExportTx,
|
|
654
|
+
id: hopExportTxId,
|
|
655
|
+
signature: '0x' + 'aa'.repeat(65), // Invalid signature
|
|
656
|
+
paymentId: '12345',
|
|
657
|
+
gasPrice: 20000000000,
|
|
658
|
+
gasLimit: 500000,
|
|
659
|
+
amount: 1000000000000000,
|
|
660
|
+
recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
661
|
+
nonce: 0,
|
|
662
|
+
userReqSig: '0x',
|
|
663
|
+
gasPriceMax: 500000000000,
|
|
664
|
+
type: 'Export',
|
|
665
|
+
};
|
|
666
|
+
await tflrCoin
|
|
667
|
+
.validateHopPrebuild(wallet, hopPrebuild)
|
|
668
|
+
.should.be.rejectedWith('Hop txid signature invalid');
|
|
669
|
+
});
|
|
670
|
+
it('should validate Export hop prebuild successfully', async function () {
|
|
671
|
+
validateHopSandbox.stub(tflrCoin, 'verifySignatureForAtomicTransaction').resolves(true);
|
|
672
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
673
|
+
const hopPrebuild = {
|
|
674
|
+
tx: hopExportTx,
|
|
675
|
+
id: hopExportTxId,
|
|
676
|
+
signature: hopExportTxBitgoSignature,
|
|
677
|
+
paymentId: '12345',
|
|
678
|
+
gasPrice: 20000000000,
|
|
679
|
+
gasLimit: 500000,
|
|
680
|
+
amount: 50000000,
|
|
681
|
+
recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
682
|
+
nonce: 0,
|
|
683
|
+
userReqSig: '0x',
|
|
684
|
+
gasPriceMax: 500000000000,
|
|
685
|
+
type: 'Export',
|
|
686
|
+
};
|
|
687
|
+
// Should not throw
|
|
688
|
+
await tflrCoin.validateHopPrebuild(wallet, hopPrebuild);
|
|
689
|
+
});
|
|
690
|
+
it('should throw error for Export hop prebuild with mismatched amount', async function () {
|
|
691
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
692
|
+
const hopPrebuild = {
|
|
693
|
+
tx: hopExportTx,
|
|
694
|
+
id: hopExportTxId,
|
|
695
|
+
signature: hopExportTxBitgoSignature,
|
|
696
|
+
paymentId: '12345',
|
|
697
|
+
gasPrice: 20000000000,
|
|
698
|
+
gasLimit: 500000,
|
|
699
|
+
amount: 50000000,
|
|
700
|
+
recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
701
|
+
nonce: 0,
|
|
702
|
+
userReqSig: '0x',
|
|
703
|
+
gasPriceMax: 500000000000,
|
|
704
|
+
type: 'Export',
|
|
705
|
+
};
|
|
706
|
+
const originalParams = {
|
|
707
|
+
recipients: [
|
|
708
|
+
{
|
|
709
|
+
address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
710
|
+
amount: '999999999999999999', // Wrong amount
|
|
711
|
+
},
|
|
712
|
+
],
|
|
713
|
+
};
|
|
714
|
+
await tflrCoin
|
|
715
|
+
.validateHopPrebuild(wallet, hopPrebuild, originalParams)
|
|
716
|
+
.should.be.rejectedWith(/Hop amount: .* does not equal original amount/);
|
|
717
|
+
});
|
|
718
|
+
it('should throw error for Export hop prebuild with mismatched destination', async function () {
|
|
719
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
720
|
+
const hopPrebuild = {
|
|
721
|
+
tx: hopExportTx,
|
|
722
|
+
id: hopExportTxId,
|
|
723
|
+
signature: hopExportTxBitgoSignature,
|
|
724
|
+
paymentId: '12345',
|
|
725
|
+
gasPrice: 20000000000,
|
|
726
|
+
gasLimit: 500000,
|
|
727
|
+
amount: 50000000,
|
|
728
|
+
recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
729
|
+
nonce: 0,
|
|
730
|
+
userReqSig: '0x',
|
|
731
|
+
gasPriceMax: 500000000000,
|
|
732
|
+
type: 'Export',
|
|
733
|
+
};
|
|
734
|
+
const originalParams = {
|
|
735
|
+
recipients: [
|
|
736
|
+
{
|
|
737
|
+
address: 'P-costwo1different~P-costwo1address~P-costwo1here',
|
|
738
|
+
amount: '49000000000000000',
|
|
739
|
+
},
|
|
740
|
+
],
|
|
741
|
+
};
|
|
742
|
+
await tflrCoin
|
|
743
|
+
.validateHopPrebuild(wallet, hopPrebuild, originalParams)
|
|
744
|
+
.should.be.rejectedWith(/Hop destination: .* does not equal original recipient/);
|
|
745
|
+
});
|
|
746
|
+
});
|
|
747
|
+
describe('presignTransaction', function () {
|
|
748
|
+
it('should return params unchanged when no hopTransaction', async function () {
|
|
749
|
+
const params = {
|
|
750
|
+
txHex: '0x123',
|
|
751
|
+
wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
|
|
752
|
+
buildParams: { recipients: [] },
|
|
753
|
+
};
|
|
754
|
+
const result = await tflrCoin.presignTransaction(params);
|
|
755
|
+
result.should.equal(params);
|
|
756
|
+
});
|
|
757
|
+
it('should call validateHopPrebuild when hopTransaction is present', async function () {
|
|
758
|
+
const sandbox = sinon.createSandbox();
|
|
759
|
+
const validateStub = sandbox.stub(tflrCoin, 'validateHopPrebuild').resolves();
|
|
760
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
761
|
+
const hopTransaction = {
|
|
762
|
+
tx: hopExportTx,
|
|
763
|
+
id: hopExportTxId,
|
|
764
|
+
signature: hopExportTxBitgoSignature,
|
|
765
|
+
paymentId: '12345',
|
|
766
|
+
gasPrice: 20000000000,
|
|
767
|
+
gasLimit: 500000,
|
|
768
|
+
amount: 50000000,
|
|
769
|
+
recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
770
|
+
nonce: 0,
|
|
771
|
+
userReqSig: '0x',
|
|
772
|
+
gasPriceMax: 500000000000,
|
|
773
|
+
type: 'Export',
|
|
774
|
+
};
|
|
775
|
+
const params = {
|
|
776
|
+
txHex: '0x123',
|
|
777
|
+
wallet: wallet,
|
|
778
|
+
buildParams: { recipients: [] },
|
|
779
|
+
hopTransaction: hopTransaction,
|
|
780
|
+
};
|
|
781
|
+
await tflrCoin.presignTransaction(params);
|
|
782
|
+
validateStub.calledOnce.should.be.true();
|
|
783
|
+
sandbox.restore();
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
describe('postProcessPrebuild', function () {
|
|
787
|
+
it('should return params unchanged when no hopTransaction', async function () {
|
|
788
|
+
const params = {
|
|
789
|
+
txHex: '0x123',
|
|
790
|
+
coin: 'tflr',
|
|
791
|
+
};
|
|
792
|
+
const result = await tflrCoin.postProcessPrebuild(params);
|
|
793
|
+
result.should.equal(params);
|
|
794
|
+
});
|
|
795
|
+
it('should call validateHopPrebuild when hopTransaction is present', async function () {
|
|
796
|
+
const sandbox = sinon.createSandbox();
|
|
797
|
+
const validateStub = sandbox.stub(tflrCoin, 'validateHopPrebuild').resolves();
|
|
798
|
+
const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
|
|
799
|
+
const hopTransaction = {
|
|
800
|
+
tx: hopExportTx,
|
|
801
|
+
id: hopExportTxId,
|
|
802
|
+
signature: hopExportTxBitgoSignature,
|
|
803
|
+
paymentId: '12345',
|
|
804
|
+
gasPrice: 20000000000,
|
|
805
|
+
gasLimit: 500000,
|
|
806
|
+
amount: 50000000,
|
|
807
|
+
recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
|
|
808
|
+
nonce: 0,
|
|
809
|
+
userReqSig: '0x',
|
|
810
|
+
gasPriceMax: 500000000000,
|
|
811
|
+
type: 'Export',
|
|
812
|
+
};
|
|
813
|
+
const params = {
|
|
814
|
+
txHex: '0x123',
|
|
815
|
+
wallet: wallet,
|
|
816
|
+
buildParams: { recipients: [{ address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress, amount: '100000000' }] },
|
|
817
|
+
hopTransaction: hopTransaction,
|
|
818
|
+
coin: 'tflr',
|
|
819
|
+
};
|
|
820
|
+
await tflrCoin.postProcessPrebuild(params);
|
|
821
|
+
validateStub.calledOnce.should.be.true();
|
|
822
|
+
sandbox.restore();
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
describe('getExtraPrebuildParams', function () {
|
|
826
|
+
const sandbox = sinon.createSandbox();
|
|
827
|
+
afterEach(function () {
|
|
828
|
+
sandbox.restore();
|
|
829
|
+
});
|
|
830
|
+
it('should return empty object when hop is not set', async function () {
|
|
831
|
+
const buildParams = {
|
|
832
|
+
recipients: [{ address: '0x1234', amount: '1000000' }],
|
|
833
|
+
};
|
|
834
|
+
const result = await tflrCoin.getExtraPrebuildParams(buildParams);
|
|
835
|
+
result.should.deepEqual({});
|
|
836
|
+
});
|
|
837
|
+
it('should return empty object when hop is false', async function () {
|
|
838
|
+
const buildParams = {
|
|
839
|
+
hop: false,
|
|
840
|
+
recipients: [{ address: '0x1234', amount: '1000000' }],
|
|
841
|
+
wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
|
|
842
|
+
};
|
|
843
|
+
const result = await tflrCoin.getExtraPrebuildParams(buildParams);
|
|
844
|
+
result.should.deepEqual({});
|
|
845
|
+
});
|
|
846
|
+
it('should return empty object when wallet is missing', async function () {
|
|
847
|
+
const buildParams = {
|
|
848
|
+
hop: true,
|
|
849
|
+
recipients: [{ address: '0x1234', amount: '1000000' }],
|
|
850
|
+
};
|
|
851
|
+
const result = await tflrCoin.getExtraPrebuildParams(buildParams);
|
|
852
|
+
result.should.deepEqual({});
|
|
853
|
+
});
|
|
854
|
+
it('should return empty object when recipients is missing', async function () {
|
|
855
|
+
const buildParams = {
|
|
856
|
+
hop: true,
|
|
857
|
+
wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
|
|
858
|
+
};
|
|
859
|
+
const result = await tflrCoin.getExtraPrebuildParams(buildParams);
|
|
860
|
+
result.should.deepEqual({});
|
|
861
|
+
});
|
|
862
|
+
it('should call createHopTransactionParams when hop is true with all required params', async function () {
|
|
863
|
+
const mockFeeEstimate = {
|
|
864
|
+
feeEstimate: 120000,
|
|
865
|
+
gasLimitEstimate: 500000,
|
|
866
|
+
};
|
|
867
|
+
sandbox.stub(tflrCoin, 'feeEstimate').resolves(mockFeeEstimate);
|
|
868
|
+
const buildParams = {
|
|
869
|
+
hop: true,
|
|
870
|
+
wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
|
|
871
|
+
recipients: [{ address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress, amount: '100000000000000000' }],
|
|
872
|
+
type: 'Export',
|
|
873
|
+
};
|
|
874
|
+
const result = await tflrCoin.getExtraPrebuildParams(buildParams);
|
|
875
|
+
result.should.have.property('hopParams');
|
|
876
|
+
});
|
|
877
|
+
});
|
|
878
|
+
describe('feeEstimate', function () {
|
|
879
|
+
it('should make API call with correct query parameters', async function () {
|
|
880
|
+
const expectedFeeEstimate = {
|
|
881
|
+
feeEstimate: 120000,
|
|
882
|
+
gasLimitEstimate: 500000,
|
|
883
|
+
};
|
|
884
|
+
(0, nock_1.default)('https://app.bitgo-test.com')
|
|
885
|
+
.get('/api/v2/tflr/tx/fee')
|
|
886
|
+
.query({
|
|
887
|
+
hop: true,
|
|
888
|
+
recipient: '0x1234',
|
|
889
|
+
amount: '1000000',
|
|
890
|
+
type: 'Export',
|
|
891
|
+
})
|
|
892
|
+
.reply(200, expectedFeeEstimate);
|
|
893
|
+
const result = await tflrCoin.feeEstimate({
|
|
894
|
+
hop: true,
|
|
895
|
+
recipient: '0x1234',
|
|
896
|
+
amount: '1000000',
|
|
897
|
+
type: 'Export',
|
|
898
|
+
});
|
|
899
|
+
result.feeEstimate.should.equal(expectedFeeEstimate.feeEstimate);
|
|
900
|
+
result.gasLimitEstimate.should.equal(expectedFeeEstimate.gasLimitEstimate);
|
|
901
|
+
});
|
|
902
|
+
it('should make API call with data parameter', async function () {
|
|
903
|
+
const expectedFeeEstimate = {
|
|
904
|
+
feeEstimate: 150000,
|
|
905
|
+
gasLimitEstimate: 600000,
|
|
906
|
+
};
|
|
907
|
+
(0, nock_1.default)('https://app.bitgo-test.com')
|
|
908
|
+
.get('/api/v2/tflr/tx/fee')
|
|
909
|
+
.query({
|
|
910
|
+
recipient: '0x5678',
|
|
911
|
+
data: '0xabcdef',
|
|
912
|
+
})
|
|
913
|
+
.reply(200, expectedFeeEstimate);
|
|
914
|
+
const result = await tflrCoin.feeEstimate({
|
|
915
|
+
recipient: '0x5678',
|
|
916
|
+
data: '0xabcdef',
|
|
917
|
+
});
|
|
918
|
+
result.feeEstimate.should.equal(expectedFeeEstimate.feeEstimate);
|
|
919
|
+
result.gasLimitEstimate.should.equal(expectedFeeEstimate.gasLimitEstimate);
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
describe('getTxHash', function () {
|
|
923
|
+
it('should calculate correct keccak256 hash for tx hex', function () {
|
|
924
|
+
const txHex = resources_1.EXPORT_C_TEST_DATA.fullsigntxHex;
|
|
925
|
+
const hash = tflrCoin.constructor.getTxHash(txHex);
|
|
926
|
+
hash.should.be.instanceOf(Buffer);
|
|
927
|
+
hash.length.should.equal(32);
|
|
928
|
+
// Verify it matches our helper function
|
|
929
|
+
const expectedHash = getTxHash(txHex);
|
|
930
|
+
hash.toString('hex').should.equal(expectedHash.toString('hex'));
|
|
931
|
+
});
|
|
932
|
+
it('should handle tx hex with 0x prefix', function () {
|
|
933
|
+
const txHex = '0x' + 'abcd'.repeat(10);
|
|
934
|
+
const hash = tflrCoin.constructor.getTxHash(txHex);
|
|
935
|
+
hash.should.be.instanceOf(Buffer);
|
|
936
|
+
hash.length.should.equal(32);
|
|
937
|
+
});
|
|
938
|
+
it('should handle tx hex without 0x prefix', function () {
|
|
939
|
+
const txHex = 'abcd'.repeat(10);
|
|
940
|
+
const hash = tflrCoin.constructor.getTxHash(txHex);
|
|
941
|
+
hash.should.be.instanceOf(Buffer);
|
|
942
|
+
hash.length.should.equal(32);
|
|
943
|
+
});
|
|
944
|
+
});
|
|
945
|
+
});
|
|
946
|
+
describe('Build Unsigned Sweep for Self-Custody Cold Wallets - (MPCv2)', function () {
|
|
947
|
+
const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
948
|
+
const explorerUrl = sdk_core_1.common.Environments[bitgo.getEnv()].flrExplorerBaseUrl;
|
|
949
|
+
const maxFeePerGasvalue = 30000000000;
|
|
950
|
+
const maxPriorityFeePerGasValue = 15000000000;
|
|
951
|
+
const chain_id = 114;
|
|
952
|
+
const gasLimitvalue = 500000;
|
|
953
|
+
it('should generate an unsigned sweep without derivation path', async () => {
|
|
954
|
+
(0, nock_1.default)(explorerUrl)
|
|
955
|
+
.get('/api')
|
|
956
|
+
.twice()
|
|
957
|
+
.query(resources_1.mockDataUnsignedSweep.getTxListRequest)
|
|
958
|
+
.reply(200, resources_1.mockDataUnsignedSweep.getTxListResponse);
|
|
959
|
+
(0, nock_1.default)(explorerUrl)
|
|
960
|
+
.get('/api')
|
|
961
|
+
.query(resources_1.mockDataUnsignedSweep.getBalanceRequest)
|
|
962
|
+
.reply(200, resources_1.mockDataUnsignedSweep.getBalanceResponse);
|
|
963
|
+
const baseCoin = bitgo.coin('tflr');
|
|
964
|
+
const transaction = (await baseCoin.recover({
|
|
965
|
+
userKey: resources_1.mockDataUnsignedSweep.userKey,
|
|
966
|
+
backupKey: resources_1.mockDataUnsignedSweep.backupKey,
|
|
967
|
+
walletContractAddress: resources_1.mockDataUnsignedSweep.walletBaseAddress,
|
|
968
|
+
recoveryDestination: resources_1.mockDataUnsignedSweep.recoveryDestination,
|
|
969
|
+
isTss: true,
|
|
970
|
+
eip1559: { maxFeePerGas: maxFeePerGasvalue, maxPriorityFeePerGas: maxPriorityFeePerGasValue },
|
|
971
|
+
gasLimit: gasLimitvalue,
|
|
972
|
+
replayProtectionOptions: {
|
|
973
|
+
chain: chain_id,
|
|
974
|
+
hardfork: 'london',
|
|
975
|
+
},
|
|
976
|
+
}));
|
|
977
|
+
should.exist(transaction);
|
|
978
|
+
transaction.should.have.property('txRequests');
|
|
979
|
+
transaction.txRequests.length.should.equal(1);
|
|
980
|
+
const txRequest = transaction.txRequests[0];
|
|
981
|
+
txRequest.should.have.property('walletCoin');
|
|
982
|
+
txRequest.walletCoin.should.equal('tflr');
|
|
983
|
+
txRequest.should.have.property('transactions');
|
|
984
|
+
txRequest.transactions.length.should.equal(1);
|
|
985
|
+
const tx = txRequest.transactions[0];
|
|
986
|
+
tx.should.have.property('nonce');
|
|
987
|
+
tx.should.have.property('unsignedTx');
|
|
988
|
+
tx.unsignedTx.should.have.property('serializedTxHex');
|
|
989
|
+
tx.unsignedTx.should.have.property('signableHex');
|
|
990
|
+
tx.unsignedTx.should.have.property('derivationPath');
|
|
991
|
+
tx.unsignedTx.should.have.property('feeInfo');
|
|
992
|
+
tx.unsignedTx.feeInfo?.should.have.property('fee');
|
|
993
|
+
tx.unsignedTx.feeInfo?.should.have.property('feeString');
|
|
994
|
+
tx.unsignedTx.should.have.property('parsedTx');
|
|
995
|
+
tx.unsignedTx.parsedTx?.should.have.property('spendAmount');
|
|
996
|
+
tx.unsignedTx.parsedTx?.should.have.property('outputs');
|
|
997
|
+
});
|
|
998
|
+
});
|
|
999
|
+
describe('Non Bitgo Recovery for Hot Wallets', function () {
|
|
1000
|
+
const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
1001
|
+
const explorerUrl = sdk_core_1.common.Environments[bitgo.getEnv()].flrExplorerBaseUrl;
|
|
1002
|
+
const maxFeePerGasvalue = 30000000000;
|
|
1003
|
+
const maxPriorityFeePerGasValue = 15000000000;
|
|
1004
|
+
const chain_id = 114;
|
|
1005
|
+
const gasLimitvalue = 500000;
|
|
1006
|
+
it('should generate a signed non-bitgo recovery tx', async () => {
|
|
1007
|
+
(0, nock_1.default)(explorerUrl)
|
|
1008
|
+
.get('/api')
|
|
1009
|
+
.twice()
|
|
1010
|
+
.query(resources_1.mockDataNonBitGoRecovery.getTxListRequest)
|
|
1011
|
+
.reply(200, resources_1.mockDataNonBitGoRecovery.getTxListResponse);
|
|
1012
|
+
(0, nock_1.default)(explorerUrl)
|
|
1013
|
+
.get('/api')
|
|
1014
|
+
.query(resources_1.mockDataNonBitGoRecovery.getBalanceRequest)
|
|
1015
|
+
.reply(200, resources_1.mockDataNonBitGoRecovery.getBalanceResponse);
|
|
1016
|
+
const baseCoin = bitgo.coin('tflr');
|
|
1017
|
+
const transaction = await baseCoin.recover({
|
|
1018
|
+
userKey: resources_1.mockDataNonBitGoRecovery.userKeyData,
|
|
1019
|
+
backupKey: resources_1.mockDataNonBitGoRecovery.backupKeyData,
|
|
1020
|
+
walletContractAddress: resources_1.mockDataNonBitGoRecovery.walletRootAddress,
|
|
1021
|
+
walletPassphrase: resources_1.mockDataNonBitGoRecovery.walletPassphrase,
|
|
1022
|
+
recoveryDestination: resources_1.mockDataNonBitGoRecovery.recoveryDestination,
|
|
1023
|
+
isTss: true,
|
|
1024
|
+
eip1559: { maxFeePerGas: maxFeePerGasvalue, maxPriorityFeePerGas: maxPriorityFeePerGasValue },
|
|
1025
|
+
gasLimit: gasLimitvalue,
|
|
1026
|
+
replayProtectionOptions: {
|
|
1027
|
+
chain: chain_id,
|
|
1028
|
+
hardfork: 'london',
|
|
1029
|
+
},
|
|
1030
|
+
});
|
|
1031
|
+
should.exist(transaction);
|
|
1032
|
+
transaction.should.have.property('id');
|
|
1033
|
+
transaction.should.have.property('tx');
|
|
1034
|
+
const tx = tx_1.FeeMarketEIP1559Transaction.fromSerializedTx(Buffer.from((0, util_1.stripHexPrefix)(transaction.tx), 'hex'));
|
|
1035
|
+
tx.getSenderAddress().toString().should.equal(resources_1.mockDataNonBitGoRecovery.walletRootAddress);
|
|
1036
|
+
const jsonTx = tx.toJSON();
|
|
1037
|
+
jsonTx.to?.should.equal(resources_1.mockDataNonBitGoRecovery.recoveryDestination);
|
|
1038
|
+
});
|
|
1039
|
+
});
|
|
1040
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2Zsci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtDQUFpQztBQUVqQyxtREFBK0Q7QUFDL0QsaURBQStDO0FBRS9DLDJDQUE0QztBQUc1Qyw0Q0FBbUc7QUFDbkcsZ0RBQXdCO0FBQ3hCLG1EQUF1RTtBQUN2RSx1Q0FBNkQ7QUFDN0QsMkNBQWtEO0FBQ2xELDZDQUErQjtBQUMvQixxREFBOEM7QUFDOUMscURBQXVDO0FBQ3ZDLG9EQUE0QjtBQUU1QixpREFBaUQ7QUFDakQsU0FBUyxTQUFTLENBQUMsRUFBVTtJQUMzQixNQUFNLElBQUksR0FBRyxJQUFBLGdCQUFNLEVBQUMsV0FBVyxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDM0QsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7QUFDdkIsQ0FBQztBQUVELFFBQVEsQ0FBQyxLQUFLLEVBQUU7SUFDZCxJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFRLENBQUM7SUFDYixJQUFJLE9BQU8sQ0FBQztJQUNaLElBQUkseUJBQXlCLENBQUM7SUFFOUIsTUFBTSxRQUFRLEdBQUcsNENBQTRDLENBQUM7SUFDOUQsTUFBTSxXQUFXLEdBQUcsOEJBQWtCLENBQUMsYUFBYSxDQUFDO0lBQ3JELE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXBFLE1BQU0sQ0FBQztRQUNMLE1BQU0sWUFBWSxHQUNoQixpSEFB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RUFBRSxRQUFRO2dCQUNmLFFBQVEsRUFBRSxRQUFRO2FBQ25CO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxQixXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sRUFBRSxHQUFHLGdDQUEyQixDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBQSxxQkFBYyxFQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzVHLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsb0NBQXdCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUMxRixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLG9DQUF3QixDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFDeEUsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuXG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWFwaSc7XG5cbmltcG9ydCB7IEZsciwgVGZsciB9IGZyb20gJy4uLy4uL3NyYy9pbmRleCc7XG5pbXBvcnQgeyBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zIH0gZnJvbSAnLi4vLi4vc3JjL2lmYWNlJztcbmltcG9ydCB7IFVuc2lnbmVkU3dlZXBUeE1QQ3YyIH0gZnJvbSAnQGJpdGdvLWJldGEvYWJzdHJhY3QtZXRoJztcbmltcG9ydCB7IG1vY2tEYXRhVW5zaWduZWRTd2VlcCwgbW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LCBFWFBPUlRfQ19URVNUX0RBVEEgfSBmcm9tICcuLi9yZXNvdXJjZXMnO1xuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgeyBjb21tb24sIFRyYW5zYWN0aW9uVHlwZSwgV2FsbGV0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHsgRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uIH0gZnJvbSAnQGV0aGVyZXVtanMvdHgnO1xuaW1wb3J0IHsgc3RyaXBIZXhQcmVmaXggfSBmcm9tICdAZXRoZXJldW1qcy91dGlsJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvLWJldGEvc2VjcDI1NmsxJztcbmltcG9ydCAqIGFzIHNlY3AyNTZrMSBmcm9tICdzZWNwMjU2azEnO1xuaW1wb3J0IEtlY2NhayBmcm9tICdrZWNjYWsnO1xuXG4vLyBIZWxwZXIgdG8gY2FsY3VsYXRlIHR4IGhhc2ggbGlrZSBGbHIuZ2V0VHhIYXNoXG5mdW5jdGlvbiBnZXRUeEhhc2godHg6IHN0cmluZyk6IEJ1ZmZlciB7XG4gIGNvbnN0IGhhc2ggPSBLZWNjYWsoJ2tlY2NhazI1NicpO1xuICBoYXNoLnVwZGF0ZSh0eC5zdGFydHNXaXRoKCcweCcpID8gdHguc2xpY2UoMikgOiB0eCwgJ2hleCcpO1xuICByZXR1cm4gaGFzaC5kaWdlc3QoKTtcbn1cblxuZGVzY3JpYmUoJ2ZscicsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCB0ZmxyQ29pbjtcbiAgbGV0IGZsckNvaW47XG4gIGxldCBob3BFeHBvcnRUeEJpdGdvU2lnbmF0dXJlO1xuXG4gIGNvbnN0IGFkZHJlc3MyID0gJzB4N2U4NWJkYzI3YzA1MGUzOTA1ZWJmNGI4ZTYzNGQ5YWQ2ZWRkMGRlNic7XG4gIGNvbnN0IGhvcEV4cG9ydFR4ID0gRVhQT1JUX0NfVEVTVF9EQVRBLmZ1bGxzaWdudHhIZXg7XG4gIGNvbnN0IGhvcEV4cG9ydFR4SWQgPSAnMHgnICsgZ2V0VHhIYXNoKGhvcEV4cG9ydFR4KS50b1N0cmluZygnaGV4Jyk7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBiaXRnb0tleVhwcnYgPVxuICAgICAgJ3hwcnY5czIxWnJRSDE0M0szdHBXQkhXZTMxc0xvWE5SUTlBdlJZSmdpdGtLeFE0QVRGUU13dnI3aEhOcVlSVW5TN1BzanpCN2FLMVZ4cUhMdU5Ramoxc2NrSjJKd28ycXhtc3ZlandFQ1NwRk1mQyc7XG4gICAgY29uc3QgYml0Z29LZXkgPSBiaXAzMi5mcm9tQmFzZTU4KGJpdGdvS2V5WHBydik7XG4gICAgaWYgKCFiaXRnb0tleS5wcml2YXRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIHByaXZhdGVLZXknKTtcbiAgICB9XG4gICAgY29uc3QgYml0Z29YcHViID0gYml0Z29LZXkubmV1dGVyZWQoKS50b0Jhc2U1OCgpO1xuXG4gICAgaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSA9XG4gICAgICAnMHhhYScgK1xuICAgICAgQnVmZmVyLmZyb20oXG4gICAgICAgIHNlY3AyNTZrMS5lY2RzYVNpZ24oQnVmZmVyLmZyb20oaG9wRXhwb3J0VHhJZC5zbGljZSgyKSwgJ2hleCcpLCBiaXRnb0tleS5wcml2YXRlS2V5KS5zaWduYXR1cmVcbiAgICAgICkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCdmbHInLCBGbHIuY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcigndGZscicsIFRmbHIuY3JlYXRlSW5zdGFuY2UpO1xuICAgIGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLmhzbVhwdWIgPSBiaXRnb1hwdWI7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIHRmbHJDb2luID0gYml0Z28uY29pbigndGZscicpIGFzIFRmbHI7XG4gICAgZmxyQ29pbiA9IGJpdGdvLmNvaW4oJ2ZscicpIGFzIEZscjtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0Jhc2ljIENvaW4gSW5mbycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiB0aGUgcmlnaHQgaW5mbyBmb3IgZmxyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZmxyID0gYml0Z28uY29pbignZmxyJyk7XG5cbiAgICAgIGZsci5zaG91bGQuYmUuYW4uaW5zdGFuY2VvZihGbHIpO1xuICAgICAgZmxyLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKCdmbHInKTtcbiAgICAgIGZsci5nZXRGYW1pbHkoKS5zaG91bGQuZXF1YWwoJ2ZscicpO1xuICAgICAgZmxyLmdldEZ1bGxOYW1lKCkuc2hvdWxkLmVxdWFsKCdGbGFyZScpO1xuICAgICAgZmxyLmdldEJhc2VGYWN0b3IoKS5zaG91bGQuZXF1YWwoMWUxOCk7XG4gICAgICBmbHIuc3VwcG9ydHNUc3MoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBmbHIuYWxsb3dzQWNjb3VudENvbnNvbGlkYXRpb25zKCkuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRoZSByaWdodCBpbmZvIGZvciB0ZmxyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGZsciA9IGJpdGdvLmNvaW4oJ3RmbHInKTtcblxuICAgICAgdGZsci5zaG91bGQuYmUuYW4uaW5zdGFuY2VvZihUZmxyKTtcbiAgICAgIHRmbHIuZ2V0Q2hhaW4oKS5zaG91bGQuZXF1YWwoJ3RmbHInKTtcbiAgICAgIHRmbHIuZ2V0RmFtaWx5KCkuc2hvdWxkLmVxdWFsKCdmbHInKTtcbiAgICAgIHRmbHIuZ2V0RnVsbE5hbWUoKS5zaG91bGQuZXF1YWwoJ1Rlc3RuZXQgZmxhcmUnKTtcbiAgICAgIHRmbHIuZ2V0QmFzZUZhY3RvcigpLnNob3VsZC5lcXVhbCgxZTE4KTtcbiAgICAgIHRmbHIuc3VwcG9ydHNUc3MoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB0ZmxyLmFsbG93c0FjY291bnRDb25zb2xpZGF0aW9ucygpLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdQLUNoYWluIE1ldGhvZHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmxycCBmb3IgbWFpbm5ldCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIChmbHJDb2luIGFzIGFueSkuZ2V0RmxyUCgpLnNob3VsZC5lcXVhbCgnZmxycCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdGZscnAgZm9yIHRlc3RuZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAodGZsckNvaW4gYXMgYW55KS5nZXRGbHJQKCkuc2hvdWxkLmVxdWFsKCd0ZmxycCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQWRkcmVzcyBWYWxpZGF0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgdmFsaWQgZXRoIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOSc7XG4gICAgICB0ZmxyQ29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgZmxyQ29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyZXNzKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhIFAtY2hhaW4gYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBBZGRyZXNzZXMgPSBFWFBPUlRfQ19URVNUX0RBVEEucEFkZHJlc3NlcztcbiAgICAgIGZvciAoY29uc3QgYWRkciBvZiBwQWRkcmVzc2VzKSB7XG4gICAgICAgIHRmbHJDb2luLmlzVmFsaWRBZGRyZXNzKGFkZHIpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICAgIGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcikuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgYSBQLWNoYWluIG11bHRpc2lnIGFkZHJlc3Mgc3RyaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzcyA9IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzO1xuICAgICAgdGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBlbXB0eSBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgdGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoJycpLnNob3VsZC5iZS5mYWxzZSgpO1xuICAgICAgZmxyQ29pbi5pc1ZhbGlkQWRkcmVzcygnJykuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUb2tlbiBDaGVjaycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgaXNUb2tlbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRmbHJDb2luLmlzVG9rZW4oKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICAgIGZsckNvaW4uaXNUb2tlbigpLnNob3VsZC5iZS5mYWxzZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnSG9wIFRyYW5zYWN0aW9uIFBhcmFtZXRlcnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kYm94LnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY3JlYXRlIGhvcCB0cmFuc2FjdGlvbiBwYXJhbWV0ZXJzIHdpdGggZ2FzUHJpY2VNYXggPiAwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja0ZlZUVzdGltYXRlID0ge1xuICAgICAgICBmZWVFc3RpbWF0ZTogMTIwMDAwLFxuICAgICAgICBnYXNMaW1pdEVzdGltYXRlOiA1MDAwMDAsXG4gICAgICB9O1xuICAgICAgc2FuZGJveC5zdHViKHRmbHJDb2luLCAnZmVlRXN0aW1hdGUnKS5yZXNvbHZlcyhtb2NrRmVlRXN0aW1hdGUpO1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCAodGZsckNvaW4gYXMgYW55KS5jcmVhdGVIb3BUcmFuc2FjdGlvblBhcmFtcyh7XG4gICAgICAgIHJlY2lwaWVudHMsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnIGFzIGtleW9mIHR5cGVvZiBUcmFuc2FjdGlvblR5cGUsXG4gICAgICB9KTtcblxuICAgICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdob3BQYXJhbXMnKTtcbiAgICAgIHJlc3VsdC5ob3BQYXJhbXMuc2hvdWxkLmhhdmUucHJvcGVydGllcyhbJ3VzZXJSZXFTaWcnLCAnZ2FzUHJpY2VNYXgnLCAncGF5bWVudElkJywgJ2dhc0xpbWl0J10pO1xuICAgICAgcmVzdWx0LmhvcFBhcmFtcy51c2VyUmVxU2lnLnNob3VsZC5lcXVhbCgnMHgnKTtcbiAgICAgIHJlc3VsdC5ob3BQYXJhbXMuZ2FzUHJpY2VNYXguc2hvdWxkLmJlLmFib3ZlKDApO1xuICAgICAgcmVzdWx0LmhvcFBhcmFtcy5wYXltZW50SWQuc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgICByZXN1bHQuaG9wUGFyYW1zLmdhc0xpbWl0LnNob3VsZC5lcXVhbCg1MDAwMDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBpZiBubyByZWNpcGllbnRzIHByb3ZpZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgKHRmbHJDb2luIGFzIGFueSlcbiAgICAgICAgLmNyZWF0ZUhvcFRyYW5zYWN0aW9uUGFyYW1zKHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbXSxcbiAgICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBrZXlvZiB0eXBlb2YgVHJhbnNhY3Rpb25UeXBlLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbXVzdCBzZW5kIHRvIGV4YWN0bHkgMSByZWNpcGllbnQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgbW9yZSB0aGFuIDEgcmVjaXBpZW50IHByb3ZpZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBFWFBPUlRfQ19URVNUX0RBVEEuY0hleEFkZHJlc3MsXG4gICAgICAgICAgYW1vdW50OiAnNTAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgYXdhaXQgKHRmbHJDb2luIGFzIGFueSlcbiAgICAgICAgLmNyZWF0ZUhvcFRyYW5zYWN0aW9uUGFyYW1zKHtcbiAgICAgICAgICByZWNpcGllbnRzLFxuICAgICAgICAgIHR5cGU6ICdFeHBvcnQnIGFzIGtleW9mIHR5cGVvZiBUcmFuc2FjdGlvblR5cGUsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtdXN0IHNlbmQgdG8gZXhhY3RseSAxIHJlY2lwaWVudCcpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRXhwbGFpbiBUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYW4gdW5zaWduZWQgZXhwb3J0IGluIEMgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0ZXN0RGF0YSA9IEVYUE9SVF9DX1RFU1RfREFUQTtcbiAgICAgIGNvbnN0IHR4RXhwbGFpbiA9IGF3YWl0IHRmbHJDb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiB0ZXN0RGF0YS51bnNpZ25lZFR4SGV4LFxuICAgICAgICBjcm9zc0NoYWluVHlwZTogJ2V4cG9ydCcsXG4gICAgICB9KTtcbiAgICAgIHR4RXhwbGFpbi50eXBlLnNob3VsZC5lcXVhbChUcmFuc2FjdGlvblR5cGUuRXhwb3J0KTtcbiAgICAgIHR4RXhwbGFpbi5pbnB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5jSGV4QWRkcmVzcy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIC8vIE91dHB1dCBhZGRyZXNzIGlzIHRoZSBzb3J0ZWQgUC1jaGFpbiBhZGRyZXNzZXMgam9pbmVkIHdpdGggflxuICAgICAgY29uc3Qgc29ydGVkUEFkZHJlc3NlcyA9IHRlc3REYXRhLnBBZGRyZXNzZXMuc2xpY2UoKS5zb3J0KCkuam9pbignficpO1xuICAgICAgdHhFeHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoc29ydGVkUEFkZHJlc3Nlcyk7XG4gICAgICB0eEV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5hbW91bnQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHR4RXhwbGFpbi5mZWUpO1xuICAgICAgdHhFeHBsYWluLmZlZS5mZWUuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZSk7XG4gICAgICB0eEV4cGxhaW4uY2hhbmdlT3V0cHV0cy5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhIHNpZ25lZCBleHBvcnQgaW4gQyB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRlc3REYXRhID0gRVhQT1JUX0NfVEVTVF9EQVRBO1xuICAgICAgY29uc3QgdHhFeHBsYWluID0gYXdhaXQgdGZsckNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhIZXg6IHRlc3REYXRhLmZ1bGxzaWdudHhIZXgsXG4gICAgICAgIGNyb3NzQ2hhaW5UeXBlOiAnZXhwb3J0JyxcbiAgICAgIH0pO1xuICAgICAgdHhFeHBsYWluLnR5cGUuc2hvdWxkLmVxdWFsKFRyYW5zYWN0aW9uVHlwZS5FeHBvcnQpO1xuICAgICAgdHhFeHBsYWluLmlucHV0c1swXS5hZGRyZXNzLnRvTG93ZXJDYXNlKCkuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmNIZXhBZGRyZXNzLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgLy8gT3V0cHV0IGFkZHJlc3MgaXMgdGhlIHNvcnRlZCBQLWNoYWluIGFkZHJlc3NlcyBqb2luZWQgd2l0aCB+XG4gICAgICBjb25zdCBzb3J0ZWRQQWRkcmVzc2VzID0gdGVzdERhdGEucEFkZHJlc3Nlcy5zbGljZSgpLnNvcnQoKS5qb2luKCd+Jyk7XG4gICAgICB0eEV4cGxhaW4ub3V0cHV0c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbChzb3J0ZWRQQWRkcmVzc2VzKTtcbiAgICAgIHR4RXhwbGFpbi5vdXRwdXRBbW91bnQuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmFtb3VudCk7XG4gICAgICBzaG91bGQuZXhpc3QodHhFeHBsYWluLmZlZSk7XG4gICAgICB0eEV4cGxhaW4uZmVlLmZlZS5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlKTtcbiAgICAgIHR4RXhwbGFpbi5jaGFuZ2VPdXRwdXRzLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIG1pc3NpbmcgdHhIZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAuZXhwbGFpblRyYW5zYWN0aW9uKHsgY3Jvc3NDaGFpblR5cGU6ICdleHBvcnQnIH0gYXMgRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgdHhIZXggaW4gZXhwbGFpbiB0eCBwYXJhbWV0ZXJzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbWlzc2luZyBmZWVJbmZvIGZvciBub24tY3Jvc3NDaGFpbiB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgIC5leHBsYWluVHJhbnNhY3Rpb24oeyB0eEhleDogJzB4MTIzJyB9IGFzIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIGZlZUluZm8gaW4gZXhwbGFpbiB0eCBwYXJhbWV0ZXJzJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgd2hlbiBjbGllbnQgdHhQYXJhbXMgYXJlIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG51bGw7XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiBmYWxzZSxcbiAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyBwYXJhbXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IHR4UHJlYnVpbGQgdGhhdCBpcyBib3RoIGJhdGNoIGFuZCBob3AnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDEzNzRhMjA0NjY2MWY5MTRkMTY4N2Q4NWRiYmNlYjlhYzc5MTBhMjknIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyNTAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4N2U4NWJkYzI3YzA1MGUzOTA1ZWJmNGI4ZTYzNGQ5YWQ2ZWRkMGRlNicgfSxcbiAgICAgICAgXSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIGhvcDogdHJ1ZSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzM1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9XSxcbiAgICAgICAgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBpc0JhdGNoOiB0cnVlLFxuICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6ICcweDAnLFxuICAgICAgICAgIGlkOiAnMHgwJyxcbiAgICAgICAgICBzaWduYXR1cmU6ICcweDAnLFxuICAgICAgICAgIHBheW1lbnRJZDogJzAnLFxuICAgICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICAgIGFtb3VudDogMTAwMDAwMDAwMDAwMDAwMCxcbiAgICAgICAgICByZWNpcGllbnQ6ICcweDEzNzRhMjA0NjY2MWY5MTRkMTY4N2Q4NWRiYmNlYjlhYzc5MTBhMjknLFxuICAgICAgICAgIG5vbmNlOiAwLFxuICAgICAgICAgIHVzZXJSZXFTaWc6ICcweDAnLFxuICAgICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgdGZsckNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LCB3YWxsZXQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgndHggY2Fubm90IGJlIGJvdGggYSBiYXRjaCBhbmQgaG9wIHRyYW5zYWN0aW9uJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBhIHR4UHJlYnVpbGQgd2l0aCBtb3JlIHRoYW4gb25lIHJlY2lwaWVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHg3ZTg1YmRjMjdjMDUwZTM5MDVlYmY0YjhlNjM0ZDlhZDZlZGQwZGU2JyB9LFxuICAgICAgICBdLFxuICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9LFxuICAgICAgICAgIHsgYW1vdW50OiAnMjUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDdlODViZGMyN2MwNTBlMzkwNWViZjRiOGU2MzRkOWFkNmVkZDBkZTYnIH0sXG4gICAgICAgIF0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogdHJ1ZSxcbiAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgYHRmbHIgZG9lc24ndCBzdXBwb3J0IHNlbmRpbmcgdG8gbW9yZSB0aGFuIDEgZGVzdGluYXRpb24gYWRkcmVzcyB3aXRoaW4gYSBzaW5nbGUgdHJhbnNhY3Rpb24uIFRyeSBhZ2FpbiwgdXNpbmcgb25seSBhIHNpbmdsZSByZWNpcGllbnQuYFxuICAgICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSB0eFByZWJ1aWxkIGZyb20gdGhlIGJpdGdvIHNlcnZlciB3aXRoIHRoZSB3cm9uZyBjb2luJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9XSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICdidGMnLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2NvaW4gaW4gdHhQcmVidWlsZCBkaWQgbm90IG1hdGNoIHRoYXQgaW4gdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50Jyk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnVFNTIFRyYW5zYWN0aW9uIFZlcmlmaWNhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgVFNTIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdpdGhvdXQgdHhQcmVidWlsZC5yZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDRlMWUzZDQ4NTZhZDhiMzMzNTJlYjNhZGQ1ZmYxMmVhMzIwNjE2OWEnIH1dLFxuICAgICAgICAgIHR5cGU6ICd0cmFuc2ZlcicsXG4gICAgICAgICAgaXNUc3M6IHRydWUsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gVFNTIHR4UHJlYnVpbGQgdHlwaWNhbGx5IGhhcyBidWlsZFBhcmFtcy5yZWNpcGllbnRzIGJ1dCBub3QgcmVjaXBpZW50cyBkaXJlY3RseVxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgICB0eFJlcXVlc3RJZDogJ2Zha2UtdHgtcmVxdWVzdC1pZCcsXG4gICAgICAgICAgdHhIZXg6XG4gICAgICAgICAgICAnMDJmMTcyODFkOTAyODUwYmE0M2I3NDAyODMwNjFhODA5NDRlMWUzZDQ4NTZhZDhiMzMzNTJlYjNhZGQ1ZmYxMmVhMzIwNjE2OWE4ODAxNjM0NTc4NWQ4YTAwMDA4MGMwODA4MDgwJyxcbiAgICAgICAgICBidWlsZFBhcmFtczoge1xuICAgICAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzB4NGUxZTNkNDg1NmFkOGIzMzM1MmViM2FkZDVmZjEyZWEzMjA2MTY5YScsIGFtb3VudDogJzEwMDAwMDAwMDAwMDAwMDAwMCcgfV0sXG4gICAgICAgICAgICB0eXBlOiAndHJhbnNmZXInLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZmVlSW5mbzogeyBmZWU6IDEwMDAwMDAwMDAwODAwMDAwLCBmZWVTdHJpbmc6ICcxMDAwMDAwMDAwMDgwMDAwMCcgfSxcbiAgICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgLy8gV2hlbiB3YWxsZXRUeXBlIGlzICd0c3MnLCBpdCBzaG91bGQgZGVsZWdhdGUgdG8gcGFyZW50J3MgdmVyaWZ5VHJhbnNhY3Rpb25cbiAgICAgICAgLy8gd2hpY2ggaGFuZGxlcyBUU1MgdHJhbnNhY3Rpb25zIHdpdGhvdXQgcmVxdWlyaW5nIHR4UHJlYnVpbGQucmVjaXBpZW50c1xuICAgICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCB0ZmxyQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXMsXG4gICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIGNvbnNvbGlkYXRpb24gdHJhbnNhY3Rpb24gd2hlbiB0eFByZWJ1aWxkIGhhcyBjb25zb2xpZGF0ZUlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge1xuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHR4UGFyYW1zIHdpdGhvdXQgcmVjaXBpZW50cyAoYXMgaW4gY29uc29saWRhdGlvbiBmbG93KVxuICAgICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHR4UHJlYnVpbGQgd2l0aCBjb25zb2xpZGF0ZUlkIChzZXQgYnkgc2VydmVyIGR1cmluZyBjb25zb2xpZGF0aW9uIGJ1aWxkKVxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2OGE3ZDVkMGM2NmU3NGUyMTZiOTcxNzNiZDU1OGM2ZCcsXG4gICAgICAgICAgdHhIZXg6ICcweCcsXG4gICAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCB0ZmxyQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KTtcbiAgICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBUU1MgdHJhbnNhY3Rpb24gd2hlbiB0eFBhcmFtcy50eXBlIGlzIGNvbnNvbGlkYXRlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge1xuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHR5cGU6ICdjb25zb2xpZGF0ZScsXG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgdGZsckNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIHRyYW5zYWN0aW9uIHdpdGggYWNjZWxlcmF0aW9uIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7XG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBiYXNlQWRkcmVzczogJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgICAgdHlwZTogJ2FjY2VsZXJhdGlvbicsXG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgdGZsckNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIHRyYW5zYWN0aW9uIHdpdGggZmlsbE5vbmNlIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7XG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBiYXNlQWRkcmVzczogJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgICAgdHlwZTogJ2ZpbGxOb25jZScsXG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgdGZsckNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZWplY3QgVFNTIHRyYW5zYWN0aW9uIHdpdGhvdXQgcmVjaXBpZW50cywgY29uc29saWRhdGVJZCwgb3IgdmFsaWQgdHlwZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHtcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgICAgdHhIZXg6ICcweCcsXG4gICAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHR4UGFyYW1zJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBzdGlsbCB1c2UgRkxSLXNwZWNpZmljIHZlcmlmaWNhdGlvbiBmb3Igbm9uLVRTUyB3YWxsZXRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9XSxcbiAgICAgICAgICB3YWxsZXQ6IHdhbGxldCxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDEzNzRhMjA0NjY2MWY5MTRkMTY4N2Q4NWRiYmNlYjlhYzc5MTBhMjknIH1dLFxuICAgICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgICAvLyBXaXRob3V0IHdhbGxldFR5cGUgb3Igd2l0aCB3YWxsZXRUeXBlOiAnb25jaGFpbicsIHNob3VsZCB1c2UgRkxSJ3Mgb3duIHZlcmlmaWNhdGlvblxuICAgICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCB0ZmxyQ29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXMsXG4gICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICB3YWxsZXRUeXBlOiAnb25jaGFpbicsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnSG9wIGV4cG9ydCB0eCB2ZXJpZnknLCAoKSA9PiB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wRGVzdGluYXRpb25BZGRyZXNzID1cbiAgICAgICAgJ1AtY29zdHdvMTVtc3ZyMjdzenZoaHBtYWgwYzM4Z2NtbDd2bTI5eGpoN3RjZWs4flAtY29zdHdvMWN3cmR0cmdmNHhoODBuY3U3cGFscmp3N2duNG1wajBuNGR4Z2hoflAtY29zdHdvMXp0OW45NmhleTRmc3ZuZGUzNW4zazRrdDVwdTdjNzg0ZHpld3pkJztcbiAgICAgIGNvbnN0IGhvcEFkZHJlc3MgPSAnMHgyOEEwNTkzM2RDNzZlNGU2YzI1ZjM1RDVjOWIyQTU4NzY5NzAwRTc2JztcbiAgICAgIGNvbnN0IGltcG9ydFR4RmVlID0gMWU2O1xuICAgICAgY29uc3QgYW1vdW50ID0gNDkwMDAwMDAwMDAwMDAwMDA7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50LCBhZGRyZXNzOiBob3BEZXN0aW5hdGlvbkFkZHJlc3MgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBob3A6IHRydWUsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnNTEwMDAwNTAwMDAwMDAwMDAnLCBhZGRyZXNzOiBob3BBZGRyZXNzIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6IGhvcEV4cG9ydFR4LFxuICAgICAgICAgIGlkOiBob3BFeHBvcnRUeElkLFxuICAgICAgICAgIHNpZ25hdHVyZTogaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgICBwYXltZW50SWQ6ICc0OTMzMzQ5OTg0JyxcbiAgICAgICAgICBnYXNQcmljZTogJzUwJyxcbiAgICAgICAgICBnYXNMaW1pdDogMSxcbiAgICAgICAgICBhbW91bnQ6ICc1MDAwMDAwMCcsXG4gICAgICAgICAgcmVjaXBpZW50OiBob3BEZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgICAgdXNlclJlcVNpZzpcbiAgICAgICAgICAgICcweDA2ZmQwYjFmODg1OWE0MGQ5ZmIyZDFhNjVkNTRkYTVkNjQ1YTFkODFiYmI4YzFjNWIwMzcwNTE4NDNlYzBkM2MyMjQzM2VjN2Y1MGNjOTdmYTA0MWNiZjhkOWZmNWRkZjdlZDQxZjcyYTA4ZmEzZjE5ODNmZDY1MWEzM2E0NDQxJyxcbiAgICAgICAgICBnYXNQcmljZU1heDogNzE4NzUwMDAwMCxcbiAgICAgICAgICB0eXBlOiAnRXhwb3J0JyxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuICAgICAgY29uc3Qgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICAgICAgYmVmb3JlKCgpID0+IHtcbiAgICAgICAgdHhQcmVidWlsZC5ob3BUcmFuc2FjdGlvbi5zaWduYXR1cmUgPSBob3BFeHBvcnRUeEJpdGdvU2lnbmF0dXJlO1xuICAgICAgfSk7XG5cbiAgICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgICBzYW5kYm94LnN0dWIodGZsckNvaW4gYXMgYW55LCAndmVyaWZ5U2lnbmF0dXJlRm9yQXRvbWljVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBhZnRlckVhY2goKCkgPT4ge1xuICAgICAgICBzYW5kYm94LnJlc3RvcmUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBzdWNjZXNzZnVsbHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyA9IHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldCwgdmVyaWZpY2F0aW9uIH07XG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSBmb3IgYW1vdW50IHBsdXMgMScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgdmVyaWZ5RmxyVHJhbnNhY3Rpb25PcHRpb25zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7IC4uLnR4UGFyYW1zLCByZWNpcGllbnRzOiBbeyBhbW91bnQ6IGFtb3VudCArIDFlOSwgYWRkcmVzczogaG9wRGVzdGluYXRpb25BZGRyZXNzIH1dIH0sXG4gICAgICAgICAgdHhQcmVidWlsZCxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucylcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIGBIb3AgYW1vdW50OiAke2Ftb3VudCAvIDFlOSArIGltcG9ydFR4RmVlfSBkb2VzIG5vdCBlcXVhbCBvcmlnaW5hbCBhbW91bnQ6ICR7XG4gICAgICAgICAgICAgIGFtb3VudCAvIDFlOSArIGltcG9ydFR4RmVlICsgMVxuICAgICAgICAgICAgfWBcbiAgICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZmFpbCB2ZXJpZnkgZm9yIGNoYW5nZWQgcHJlYnVpbGQgaG9wIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyA9IHtcbiAgICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IC4uLnR4UHJlYnVpbGQsIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IGFkZHJlc3MyLCBhbW91bnQ6ICc1MTAwMDA1MDAwMDAwMDAwMCcgfV0gfSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih2ZXJpZnlGbHJUcmFuc2FjdGlvbk9wdGlvbnMpXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoYHJlY2lwaWVudCBhZGRyZXNzIG9mIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggaG9wIGFkZHJlc3NgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGZhaWwgdmVyaWZ5IGZvciBjaGFuZ2VkIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGhvcERlc3RpbmF0aW9uQWRkcmVzc0RpZmYgPVxuICAgICAgICAgICdQLWNvc3R3bzE1bXN2cjI3c3p2aGhwbWFoMGMzOGdjbWw3dm0yOXhqaDd0Y2VrOX5QLWNvc3R3bzFjd3JkdHJnZjR4aDgwbmN1N3BhbHJqdzdnbjRtcGowbjRkeGdoaH5QLWNvc3R3bzF6dDluOTZoZXk0ZnN2bmRlMzVuM2s0a3Q1cHU3Yzc4NGR6ZXd6ZCc7XG4gICAgICAgIGNvbnN0IHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyA9IHtcbiAgICAgICAgICB0eFBhcmFtczogeyAuLi50eFBhcmFtcywgcmVjaXBpZW50czogW3sgYW1vdW50OiBhbW91bnQsIGFkZHJlc3M6IGhvcERlc3RpbmF0aW9uQWRkcmVzc0RpZmYgfV0gfSxcbiAgICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucylcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIGBIb3AgZGVzdGluYXRpb246ICR7aG9wRGVzdGluYXRpb25BZGRyZXNzfSBkb2VzIG5vdCBlcXVhbCBvcmlnaW5hbCByZWNpcGllbnQ6ICR7aG9wRGVzdGluYXRpb25BZGRyZXNzRGlmZn1gXG4gICAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBpZiB3YWxsZXRJZCBpcyB1c2VkIGluc3RlYWQgb2YgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgdmVyaWZ5RmxyVHJhbnNhY3Rpb25PcHRpb25zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7IC4uLnR4UGFyYW1zLCByZWNpcGllbnRzOiBbeyBhbW91bnQ6IGFtb3VudCwgd2FsbGV0SWQ6ICdzYW1lIHdhbGxldCcgfV0gfSxcbiAgICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZhbGlkYXRlSG9wUHJlYnVpbGQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdmFsaWRhdGVIb3BTYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIHZhbGlkYXRlSG9wU2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnZhbGlkIEhTTSBzaWduYXR1cmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wUHJlYnVpbGQgPSB7XG4gICAgICAgIHR4OiBob3BFeHBvcnRUeCxcbiAgICAgICAgaWQ6IGhvcEV4cG9ydFR4SWQsXG4gICAgICAgIHNpZ25hdHVyZTogJzB4JyArICdhYScucmVwZWF0KDY1KSwgLy8gSW52YWxpZCBzaWduYXR1cmVcbiAgICAgICAgcGF5bWVudElkOiAnMTIzNDUnLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGFtb3VudDogMTAwMDAwMDAwMDAwMDAwMCxcbiAgICAgICAgcmVjaXBpZW50OiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcyxcbiAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgIHVzZXJSZXFTaWc6ICcweCcsXG4gICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnIGFzIGNvbnN0LFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgKHRmbHJDb2luIGFzIGFueSlcbiAgICAgICAgLnZhbGlkYXRlSG9wUHJlYnVpbGQod2FsbGV0LCBob3BQcmVidWlsZClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0hvcCB0eGlkIHNpZ25hdHVyZSBpbnZhbGlkJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIEV4cG9ydCBob3AgcHJlYnVpbGQgc3VjY2Vzc2Z1bGx5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgdmFsaWRhdGVIb3BTYW5kYm94LnN0dWIodGZsckNvaW4gYXMgYW55LCAndmVyaWZ5U2lnbmF0dXJlRm9yQXRvbWljVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh0cnVlKTtcblxuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcbiAgICAgIGNvbnN0IGhvcFByZWJ1aWxkID0ge1xuICAgICAgICB0eDogaG9wRXhwb3J0VHgsXG4gICAgICAgIGlkOiBob3BFeHBvcnRUeElkLFxuICAgICAgICBzaWduYXR1cmU6IGhvcEV4cG9ydFR4Qml0Z29TaWduYXR1cmUsXG4gICAgICAgIHBheW1lbnRJZDogJzEyMzQ1JyxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBhbW91bnQ6IDUwMDAwMDAwLFxuICAgICAgICByZWNpcGllbnQ6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICBub25jZTogMCxcbiAgICAgICAgdXNlclJlcVNpZzogJzB4JyxcbiAgICAgICAgZ2FzUHJpY2VNYXg6IDUwMDAwMDAwMDAwMCxcbiAgICAgICAgdHlwZTogJ0V4cG9ydCcgYXMgY29uc3QsXG4gICAgICB9O1xuXG4gICAgICAvLyBTaG91bGQgbm90IHRocm93XG4gICAgICBhd2FpdCAodGZsckNvaW4gYXMgYW55KS52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgaG9wUHJlYnVpbGQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgRXhwb3J0IGhvcCBwcmVidWlsZCB3aXRoIG1pc21hdGNoZWQgYW1vdW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcbiAgICAgIGNvbnN0IGhvcFByZWJ1aWxkID0ge1xuICAgICAgICB0eDogaG9wRXhwb3J0VHgsXG4gICAgICAgIGlkOiBob3BFeHBvcnRUeElkLFxuICAgICAgICBzaWduYXR1cmU6IGhvcEV4cG9ydFR4Qml0Z29TaWduYXR1cmUsXG4gICAgICAgIHBheW1lbnRJZDogJzEyMzQ1JyxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBhbW91bnQ6IDUwMDAwMDAwLFxuICAgICAgICByZWNpcGllbnQ6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICBub25jZTogMCxcbiAgICAgICAgdXNlclJlcVNpZzogJzB4JyxcbiAgICAgICAgZ2FzUHJpY2VNYXg6IDUwMDAwMDAwMDAwMCxcbiAgICAgICAgdHlwZTogJ0V4cG9ydCcgYXMgY29uc3QsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICAgICAgYW1vdW50OiAnOTk5OTk5OTk5OTk5OTk5OTk5JywgLy8gV3JvbmcgYW1vdW50XG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0ICh0ZmxyQ29pbiBhcyBhbnkpXG4gICAgICAgIC52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgaG9wUHJlYnVpbGQsIG9yaWdpbmFsUGFyYW1zKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvSG9wIGFtb3VudDogLiogZG9lcyBub3QgZXF1YWwgb3JpZ2luYWwgYW1vdW50Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBFeHBvcnQgaG9wIHByZWJ1aWxkIHdpdGggbWlzbWF0Y2hlZCBkZXN0aW5hdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSk7XG4gICAgICBjb25zdCBob3BQcmVidWlsZCA9IHtcbiAgICAgICAgdHg6IGhvcEV4cG9ydFR4LFxuICAgICAgICBpZDogaG9wRXhwb3J0VHhJZCxcbiAgICAgICAgc2lnbmF0dXJlOiBob3BFeHBvcnRUeEJpdGdvU2lnbmF0dXJlLFxuICAgICAgICBwYXltZW50SWQ6ICcxMjM0NScsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgYW1vdW50OiA1MDAwMDAwMCxcbiAgICAgICAgcmVjaXBpZW50OiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcyxcbiAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgIHVzZXJSZXFTaWc6ICcweCcsXG4gICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnIGFzIGNvbnN0LFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnUC1jb3N0d28xZGlmZmVyZW50flAtY29zdHdvMWFkZHJlc3N+UC1jb3N0d28xaGVyZScsXG4gICAgICAgICAgICBhbW91bnQ6ICc0OTAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0ICh0ZmxyQ29pbiBhcyBhbnkpXG4gICAgICAgIC52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgaG9wUHJlYnVpbGQsIG9yaWdpbmFsUGFyYW1zKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvSG9wIGRlc3RpbmF0aW9uOiAuKiBkb2VzIG5vdCBlcXVhbCBvcmlnaW5hbCByZWNpcGllbnQvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ByZXNpZ25UcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBwYXJhbXMgdW5jaGFuZ2VkIHdoZW4gbm8gaG9wVHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4SGV4OiAnMHgxMjMnLFxuICAgICAgICB3YWxsZXQ6IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSksXG4gICAgICAgIGJ1aWxkUGFyYW1zOiB7IHJlY2lwaWVudHM6IFtdIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5wcmVzaWduVHJhbnNhY3Rpb24ocGFyYW1zIGFzIGFueSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHBhcmFtcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgdmFsaWRhdGVIb3BQcmVidWlsZCB3aGVuIGhvcFRyYW5zYWN0aW9uIGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgY29uc3QgdmFsaWRhdGVTdHViID0gc2FuZGJveC5zdHViKHRmbHJDb2luIGFzIGFueSwgJ3ZhbGlkYXRlSG9wUHJlYnVpbGQnKS5yZXNvbHZlcygpO1xuXG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wVHJhbnNhY3Rpb24gPSB7XG4gICAgICAgIHR4OiBob3BFeHBvcnRUeCxcbiAgICAgICAgaWQ6IGhvcEV4cG9ydFR4SWQsXG4gICAgICAgIHNpZ25hdHVyZTogaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgcGF5bWVudElkOiAnMTIzNDUnLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGFtb3VudDogNTAwMDAwMDAsXG4gICAgICAgIHJlY2lwaWVudDogRVhQT1JUX0NfVEVTVF9EQVRBLnBNdWx0aXNpZ0FkZHJlc3MsXG4gICAgICAgIG5vbmNlOiAwLFxuICAgICAgICB1c2VyUmVxU2lnOiAnMHgnLFxuICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBjb25zdCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhIZXg6ICcweDEyMycsXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbXSB9LFxuICAgICAgICBob3BUcmFuc2FjdGlvbjogaG9wVHJhbnNhY3Rpb24sXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCB0ZmxyQ29pbi5wcmVzaWduVHJhbnNhY3Rpb24ocGFyYW1zIGFzIGFueSk7XG4gICAgICB2YWxpZGF0ZVN0dWIuY2FsbGVkT25jZS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwb3N0UHJvY2Vzc1ByZWJ1aWxkJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHBhcmFtcyB1bmNoYW5nZWQgd2hlbiBubyBob3BUcmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhIZXg6ICcweDEyMycsXG4gICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLnBvc3RQcm9jZXNzUHJlYnVpbGQocGFyYW1zIGFzIGFueSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHBhcmFtcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgdmFsaWRhdGVIb3BQcmVidWlsZCB3aGVuIGhvcFRyYW5zYWN0aW9uIGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgY29uc3QgdmFsaWRhdGVTdHViID0gc2FuZGJveC5zdHViKHRmbHJDb2luIGFzIGFueSwgJ3ZhbGlkYXRlSG9wUHJlYnVpbGQnKS5yZXNvbHZlcygpO1xuXG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wVHJhbnNhY3Rpb24gPSB7XG4gICAgICAgIHR4OiBob3BFeHBvcnRUeCxcbiAgICAgICAgaWQ6IGhvcEV4cG9ydFR4SWQsXG4gICAgICAgIHNpZ25hdHVyZTogaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgcGF5bWVudElkOiAnMTIzNDUnLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGFtb3VudDogNTAwMDAwMDAsXG4gICAgICAgIHJlY2lwaWVudDogRVhQT1JUX0NfVEVTVF9EQVRBLnBNdWx0aXNpZ0FkZHJlc3MsXG4gICAgICAgIG5vbmNlOiAwLFxuICAgICAgICB1c2VyUmVxU2lnOiAnMHgnLFxuICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBjb25zdCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhIZXg6ICcweDEyMycsXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcywgYW1vdW50OiAnMTAwMDAwMDAwJyB9XSB9LFxuICAgICAgICBob3BUcmFuc2FjdGlvbjogaG9wVHJhbnNhY3Rpb24sXG4gICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHRmbHJDb2luLnBvc3RQcm9jZXNzUHJlYnVpbGQocGFyYW1zIGFzIGFueSk7XG4gICAgICB2YWxpZGF0ZVN0dWIuY2FsbGVkT25jZS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRFeHRyYVByZWJ1aWxkUGFyYW1zJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBvYmplY3Qgd2hlbiBob3AgaXMgbm90IHNldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHgxMjM0JywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5nZXRFeHRyYVByZWJ1aWxkUGFyYW1zKGJ1aWxkUGFyYW1zKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZGVlcEVxdWFsKHt9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGVtcHR5IG9iamVjdCB3aGVuIGhvcCBpcyBmYWxzZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICBob3A6IGZhbHNlLFxuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHgxMjM0JywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICAgIHdhbGxldDogbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5kZWVwRXF1YWwoe30pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZW1wdHkgb2JqZWN0IHdoZW4gd2FsbGV0IGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZFBhcmFtcyA9IHtcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHgxMjM0JywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5nZXRFeHRyYVByZWJ1aWxkUGFyYW1zKGJ1aWxkUGFyYW1zKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZGVlcEVxdWFsKHt9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGVtcHR5IG9iamVjdCB3aGVuIHJlY2lwaWVudHMgaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICBob3A6IHRydWUsXG4gICAgICAgIHdhbGxldDogbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5kZWVwRXF1YWwoe30pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGNyZWF0ZUhvcFRyYW5zYWN0aW9uUGFyYW1zIHdoZW4gaG9wIGlzIHRydWUgd2l0aCBhbGwgcmVxdWlyZWQgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja0ZlZUVzdGltYXRlID0ge1xuICAgICAgICBmZWVFc3RpbWF0ZTogMTIwMDAwLFxuICAgICAgICBnYXNMaW1pdEVzdGltYXRlOiA1MDAwMDAsXG4gICAgICB9O1xuICAgICAgc2FuZGJveC5zdHViKHRmbHJDb2luLCAnZmVlRXN0aW1hdGUnKS5yZXNvbHZlcyhtb2NrRmVlRXN0aW1hdGUpO1xuXG4gICAgICBjb25zdCBidWlsZFBhcmFtcyA9IHtcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICB3YWxsZXQ6IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSksXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLCBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnIH1dLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBjb25zdCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdob3BQYXJhbXMnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2ZlZUVzdGltYXRlJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgbWFrZSBBUEkgY2FsbCB3aXRoIGNvcnJlY3QgcXVlcnkgcGFyYW1ldGVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkRmVlRXN0aW1hdGUgPSB7XG4gICAgICAgIGZlZUVzdGltYXRlOiAxMjAwMDAsXG4gICAgICAgIGdhc0xpbWl0RXN0aW1hdGU6IDUwMDAwMCxcbiAgICAgIH07XG5cbiAgICAgIG5vY2soJ2h0dHBzOi8vYXBwLmJpdGdvLXRlc3QuY29tJylcbiAgICAgICAgLmdldCgnL2FwaS92Mi90ZmxyL3R4L2ZlZScpXG4gICAgICAgIC5xdWVyeSh7XG4gICAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICAgIHJlY2lwaWVudDogJzB4MTIzNCcsXG4gICAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgICAgdHlwZTogJ0V4cG9ydCcsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkRmVlRXN0aW1hdGUpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5mZWVFc3RpbWF0ZSh7XG4gICAgICAgIGhvcDogdHJ1ZSxcbiAgICAgICAgcmVjaXBpZW50OiAnMHgxMjM0JyxcbiAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnLFxuICAgICAgfSk7XG5cbiAgICAgIHJlc3VsdC5mZWVFc3RpbWF0ZS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRGZWVFc3RpbWF0ZS5mZWVFc3RpbWF0ZSk7XG4gICAgICByZXN1bHQuZ2FzTGltaXRFc3RpbWF0ZS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRGZWVFc3RpbWF0ZS5nYXNMaW1pdEVzdGltYXRlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbWFrZSBBUEkgY2FsbCB3aXRoIGRhdGEgcGFyYW1ldGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWRGZWVFc3RpbWF0ZSA9IHtcbiAgICAgICAgZmVlRXN0aW1hdGU6IDE1MDAwMCxcbiAgICAgICAgZ2FzTGltaXRFc3RpbWF0ZTogNjAwMDAwLFxuICAgICAgfTtcblxuICAgICAgbm9jaygnaHR0cHM6Ly9hcHAuYml0Z28tdGVzdC5jb20nKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyL3RmbHIvdHgvZmVlJylcbiAgICAgICAgLnF1ZXJ5KHtcbiAgICAgICAgICByZWNpcGllbnQ6ICcweDU2NzgnLFxuICAgICAgICAgIGRhdGE6ICcweGFiY2RlZicsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkRmVlRXN0aW1hdGUpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5mZWVFc3RpbWF0ZSh7XG4gICAgICAgIHJlY2lwaWVudDogJzB4NTY3OCcsXG4gICAgICAgIGRhdGE6ICcweGFiY2RlZicsXG4gICAgICB9KTtcblxuICAgICAgcmVzdWx0LmZlZUVzdGltYXRlLnNob3VsZC5lcXVhbChleHBlY3RlZEZlZUVzdGltYXRlLmZlZUVzdGltYXRlKTtcbiAgICAgIHJlc3VsdC5nYXNMaW1pdEVzdGltYXRlLnNob3VsZC5lcXVhbChleHBlY3RlZEZlZUVzdGltYXRlLmdhc0xpbWl0RXN0aW1hdGUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZ2V0VHhIYXNoJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY2FsY3VsYXRlIGNvcnJlY3Qga2VjY2FrMjU2IGhhc2ggZm9yIHR4IGhleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gRVhQT1JUX0NfVEVTVF9EQVRBLmZ1bGxzaWdudHhIZXg7XG4gICAgICBjb25zdCBoYXNoID0gKHRmbHJDb2luLmNvbnN0cnVjdG9yIGFzIHR5cGVvZiBGbHIpLmdldFR4SGFzaCh0eEhleCk7XG5cbiAgICAgIGhhc2guc2hvdWxkLmJlLmluc3RhbmNlT2YoQnVmZmVyKTtcbiAgICAgIGhhc2gubGVuZ3RoLnNob3VsZC5lcXVhbCgzMik7XG5cbiAgICAgIC8vIFZlcmlmeSBpdCBtYXRjaGVzIG91ciBoZWxwZXIgZnVuY3Rpb25cbiAgICAgIGNvbnN0IGV4cGVjdGVkSGFzaCA9IGdldFR4SGFzaCh0eEhleCk7XG4gICAgICBoYXNoLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRIYXNoLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSB0eCBoZXggd2l0aCAweCBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9ICcweCcgKyAnYWJjZCcucmVwZWF0KDEwKTtcbiAgICAgIGNvbnN0IGhhc2ggPSAodGZsckNvaW4uY29uc3RydWN0b3IgYXMgdHlwZW9mIEZscikuZ2V0VHhIYXNoKHR4SGV4KTtcblxuICAgICAgaGFzaC5zaG91bGQuYmUuaW5zdGFuY2VPZihCdWZmZXIpO1xuICAgICAgaGFzaC5sZW5ndGguc2hvdWxkLmVxdWFsKDMyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIHR4IGhleCB3aXRob3V0IDB4IHByZWZpeCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gJ2FiY2QnLnJlcGVhdCgxMCk7XG4gICAgICBjb25zdCBoYXNoID0gKHRmbHJDb2luLmNvbnN0cnVjdG9yIGFzIHR5cGVvZiBGbHIpLmdldFR4SGFzaCh0eEhleCk7XG5cbiAgICAgIGhhc2guc2hvdWxkLmJlLmluc3RhbmNlT2YoQnVmZmVyKTtcbiAgICAgIGhhc2gubGVuZ3RoLnNob3VsZC5lcXVhbCgzMik7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdCdWlsZCBVbnNpZ25lZCBTd2VlcCBmb3IgU2VsZi1DdXN0b2R5IENvbGQgV2FsbGV0cyAtIChNUEN2MiknLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICBjb25zdCBleHBsb3JlclVybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLmZsckV4cGxvcmVyQmFzZVVybCBhcyBzdHJpbmc7XG4gIGNvbnN0IG1heEZlZVBlckdhc3ZhbHVlID0gMzAwMDAwMDAwMDA7XG4gIGNvbnN0IG1heFByaW9yaXR5RmVlUGVyR2FzVmFsdWUgPSAxNTAwMDAwMDAwMDtcbiAgY29uc3QgY2hhaW5faWQgPSAxMTQ7XG4gIGNvbnN0IGdhc0xpbWl0dmFsdWUgPSA1MDAwMDA7XG5cbiAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCBzd2VlcCB3aXRob3V0IGRlcml2YXRpb24gcGF0aCcsIGFzeW5jICgpID0+IHtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAudHdpY2UoKVxuICAgICAgLnF1ZXJ5KG1vY2tEYXRhVW5zaWduZWRTd2VlcC5nZXRUeExpc3RSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFVbnNpZ25lZFN3ZWVwLmdldFR4TGlzdFJlc3BvbnNlKTtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAucXVlcnkobW9ja0RhdGFVbnNpZ25lZFN3ZWVwLmdldEJhbGFuY2VSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFVbnNpZ25lZFN3ZWVwLmdldEJhbGFuY2VSZXNwb25zZSk7XG5cbiAgICBjb25zdCBiYXNlQ29pbjogYW55ID0gYml0Z28uY29pbigndGZscicpO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGJhc2VDb2luLnJlY292ZXIoe1xuICAgICAgdXNlcktleTogbW9ja0RhdGFVbnNpZ25lZFN3ZWVwLnVzZXJLZXksXG4gICAgICBiYWNrdXBLZXk6IG1vY2tEYXRhVW5zaWduZWRTd2VlcC5iYWNrdXBLZXksXG4gICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IG1vY2tEYXRhVW5zaWduZWRTd2VlcC53YWxsZXRCYXNlQWRkcmVzcyxcbiAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IG1vY2tEYXRhVW5zaWduZWRTd2VlcC5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgaXNUc3M6IHRydWUsXG4gICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogbWF4RmVlUGVyR2FzdmFsdWUsIG1heFByaW9yaXR5RmVlUGVyR2FzOiBtYXhQcmlvcml0eUZlZVBlckdhc1ZhbHVlIH0sXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXR2YWx1ZSxcbiAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgIGNoYWluOiBjaGFpbl9pZCxcbiAgICAgICAgaGFyZGZvcms6ICdsb25kb24nLFxuICAgICAgfSxcbiAgICB9KSkgYXMgVW5zaWduZWRTd2VlcFR4TVBDdjI7XG4gICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uKTtcbiAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhSZXF1ZXN0cycpO1xuICAgIHRyYW5zYWN0aW9uLnR4UmVxdWVzdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICBjb25zdCB0eFJlcXVlc3QgPSB0cmFuc2FjdGlvbi50eFJlcXVlc3RzWzBdO1xuICAgIHR4UmVxdWVzdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0Q29pbicpO1xuICAgIHR4UmVxdWVzdC53YWxsZXRDb2luLnNob3VsZC5lcXVhbCgndGZscicpO1xuICAgIHR4UmVxdWVzdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHJhbnNhY3Rpb25zJyk7XG4gICAgdHhSZXF1ZXN0LnRyYW5zYWN0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgIGNvbnN0IHR4ID0gdHhSZXF1ZXN0LnRyYW5zYWN0aW9uc1swXTtcbiAgICB0eC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9uY2UnKTtcbiAgICB0eC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndW5zaWduZWRUeCcpO1xuICAgIHR4LnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NlcmlhbGl6ZWRUeEhleCcpO1xuICAgIHR4LnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hYmxlSGV4Jyk7XG4gICAgdHgudW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZGVyaXZhdGlvblBhdGgnKTtcbiAgICB0eC51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVJbmZvJyk7XG4gICAgdHgudW5zaWduZWRUeC5mZWVJbmZvPy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlJyk7XG4gICAgdHgudW5zaWduZWRUeC5mZWVJbmZvPy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlU3RyaW5nJyk7XG4gICAgdHgudW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncGFyc2VkVHgnKTtcbiAgICB0eC51bnNpZ25lZFR4LnBhcnNlZFR4Py5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3BlbmRBbW91bnQnKTtcbiAgICB0eC51bnNpZ25lZFR4LnBhcnNlZFR4Py5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnb3V0cHV0cycpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnTm9uIEJpdGdvIFJlY292ZXJ5IGZvciBIb3QgV2FsbGV0cycsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gIGNvbnN0IGV4cGxvcmVyVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0uZmxyRXhwbG9yZXJCYXNlVXJsIGFzIHN0cmluZztcbiAgY29uc3QgbWF4RmVlUGVyR2FzdmFsdWUgPSAzMDAwMDAwMDAwMDtcbiAgY29uc3QgbWF4UHJpb3JpdHlGZWVQZXJHYXNWYWx1ZSA9IDE1MDAwMDAwMDAwO1xuICBjb25zdCBjaGFpbl9pZCA9IDExNDtcbiAgY29uc3QgZ2FzTGltaXR2YWx1ZSA9IDUwMDAwMDtcblxuICBpdCgnc2hvdWxkIGdlbmVyYXRlIGEgc2lnbmVkIG5vbi1iaXRnbyByZWNvdmVyeSB0eCcsIGFzeW5jICgpID0+IHtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAudHdpY2UoKVxuICAgICAgLnF1ZXJ5KG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5nZXRUeExpc3RSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LmdldFR4TGlzdFJlc3BvbnNlKTtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAucXVlcnkobW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LmdldEJhbGFuY2VSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LmdldEJhbGFuY2VSZXNwb25zZSk7XG5cbiAgICBjb25zdCBiYXNlQ29pbjogYW55ID0gYml0Z28uY29pbigndGZscicpO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZUNvaW4ucmVjb3Zlcih7XG4gICAgICB1c2VyS2V5OiBtb2NrRGF0YU5vbkJpdEdvUmVjb3ZlcnkudXNlcktleURhdGEsXG4gICAgICBiYWNrdXBLZXk6IG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5iYWNrdXBLZXlEYXRhLFxuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBtb2NrRGF0YU5vbkJpdEdvUmVjb3Zlcnkud2FsbGV0Um9vdEFkZHJlc3MsXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlOiBtb2NrRGF0YU5vbkJpdEdvUmVjb3Zlcnkud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgaXNUc3M6IHRydWUsXG4gICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogbWF4RmVlUGVyR2FzdmFsdWUsIG1heFByaW9yaXR5RmVlUGVyR2FzOiBtYXhQcmlvcml0eUZlZVBlckdhc1ZhbHVlIH0sXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXR2YWx1ZSxcbiAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgIGNoYWluOiBjaGFpbl9pZCxcbiAgICAgICAgaGFyZGZvcms6ICdsb25kb24nLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24pO1xuICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcpO1xuICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgIGNvbnN0IHR4ID0gRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkVHgoQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgodHJhbnNhY3Rpb24udHgpLCAnaGV4JykpO1xuICAgIHR4LmdldFNlbmRlckFkZHJlc3MoKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChtb2NrRGF0YU5vbkJpdEdvUmVjb3Zlcnkud2FsbGV0Um9vdEFkZHJlc3MpO1xuICAgIGNvbnN0IGpzb25UeCA9IHR4LnRvSlNPTigpO1xuICAgIGpzb25UeC50bz8uc2hvdWxkLmVxdWFsKG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5yZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgfSk7XG59KTtcbiJdfQ==
|