@bitgo-beta/sdk-coin-flr 1.0.1-beta.87 → 1.0.1-beta.871

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/src/flr.d.ts +145 -3
  2. package/dist/src/flr.d.ts.map +1 -1
  3. package/dist/src/flr.js +466 -3
  4. package/dist/src/flrToken.d.ts +26 -0
  5. package/dist/src/flrToken.d.ts.map +1 -0
  6. package/dist/src/flrToken.js +49 -0
  7. package/dist/src/iface.d.ts +148 -0
  8. package/dist/src/iface.d.ts.map +1 -0
  9. package/dist/src/iface.js +3 -0
  10. package/dist/src/index.d.ts +2 -0
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/index.js +3 -1
  13. package/dist/src/lib/transactionBuilder.d.ts +2 -0
  14. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  15. package/dist/src/lib/transactionBuilder.js +5 -1
  16. package/dist/src/register.d.ts.map +1 -1
  17. package/dist/src/register.js +5 -1
  18. package/dist/test/resources.d.ts +42 -0
  19. package/dist/test/resources.d.ts.map +1 -0
  20. package/dist/test/resources.js +117 -0
  21. package/dist/test/unit/flr.d.ts +2 -0
  22. package/dist/test/unit/flr.d.ts.map +1 -0
  23. package/dist/test/unit/flr.js +1041 -0
  24. package/dist/test/unit/flrToken.d.ts +2 -0
  25. package/dist/test/unit/flrToken.d.ts.map +1 -0
  26. package/dist/test/unit/flrToken.js +30 -0
  27. package/dist/test/unit/getBuilder.d.ts +3 -0
  28. package/dist/test/unit/getBuilder.d.ts.map +1 -0
  29. package/dist/test/unit/getBuilder.js +10 -0
  30. package/dist/test/unit/transactionBuilder/send.d.ts +2 -0
  31. package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
  32. package/dist/test/unit/transactionBuilder/send.js +19 -0
  33. package/dist/test/unit/utils.d.ts +2 -0
  34. package/dist/test/unit/utils.d.ts.map +1 -0
  35. package/dist/test/unit/utils.js +29 -0
  36. package/dist/tsconfig.tsbuildinfo +1 -0
  37. package/package.json +22 -10
  38. package/.eslintignore +0 -5
  39. package/.mocharc.yml +0 -8
  40. package/CHANGELOG.md +0 -48
@@ -0,0 +1,1041 @@
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 = 200000; // Match FlarePTestnet txFee from networks.ts
551
+ // Adjusted amount to work backwards from hop amount (50000000): 50000000 - 200000 = 49800000 nanoFLR
552
+ const amount = 49800000000000000;
553
+ const txParams = {
554
+ recipients: [{ amount, address: hopDestinationAddress }],
555
+ wallet: wallet,
556
+ walletPassphrase: 'fakeWalletPassphrase',
557
+ hop: true,
558
+ type: 'Export',
559
+ };
560
+ const txPrebuild = {
561
+ recipients: [{ amount: '51000050000000000', address: hopAddress }],
562
+ nextContractSequenceId: 0,
563
+ gasPrice: 20000000000,
564
+ gasLimit: 500000,
565
+ isBatch: false,
566
+ coin: 'tflr',
567
+ walletId: 'fakeWalletId',
568
+ walletContractAddress: 'fakeWalletContractAddress',
569
+ hopTransaction: {
570
+ tx: hopExportTx,
571
+ id: hopExportTxId,
572
+ signature: hopExportTxBitgoSignature,
573
+ paymentId: '4933349984',
574
+ gasPrice: '50',
575
+ gasLimit: 1,
576
+ amount: '50000000',
577
+ recipient: hopDestinationAddress,
578
+ nonce: 0,
579
+ userReqSig: '0x06fd0b1f8859a40d9fb2d1a65d54da5d645a1d81bbb8c1c5b037051843ec0d3c22433ec7f50cc97fa041cbf8d9ff5ddf7ed41f72a08fa3f1983fd651a33a4441',
580
+ gasPriceMax: 7187500000,
581
+ type: 'Export',
582
+ },
583
+ };
584
+ const verification = {};
585
+ const sandbox = sinon.createSandbox();
586
+ before(() => {
587
+ txPrebuild.hopTransaction.signature = hopExportTxBitgoSignature;
588
+ });
589
+ beforeEach(() => {
590
+ sandbox.stub(tflrCoin, 'verifySignatureForAtomicTransaction').resolves(true);
591
+ });
592
+ afterEach(() => {
593
+ sandbox.restore();
594
+ });
595
+ it('should verify successfully', async function () {
596
+ const verifyFlrTransactionOptions = { txParams, txPrebuild, wallet, verification };
597
+ const isTransactionVerified = await tflrCoin.verifyTransaction(verifyFlrTransactionOptions);
598
+ isTransactionVerified.should.equal(true);
599
+ });
600
+ it('should fail verify for amount plus 1', async function () {
601
+ const verifyFlrTransactionOptions = {
602
+ txParams: { ...txParams, recipients: [{ amount: amount + 1e9, address: hopDestinationAddress }] },
603
+ txPrebuild,
604
+ wallet,
605
+ verification,
606
+ };
607
+ await tflrCoin
608
+ .verifyTransaction(verifyFlrTransactionOptions)
609
+ .should.be.rejectedWith(`Hop amount: ${amount / 1e9 + importTxFee} does not equal original amount: ${amount / 1e9 + importTxFee + 1}`);
610
+ });
611
+ it('should fail verify for changed prebuild hop address', async function () {
612
+ const verifyFlrTransactionOptions = {
613
+ txParams,
614
+ txPrebuild: { ...txPrebuild, recipients: [{ address: address2, amount: '51000050000000000' }] },
615
+ wallet,
616
+ verification,
617
+ };
618
+ await tflrCoin
619
+ .verifyTransaction(verifyFlrTransactionOptions)
620
+ .should.be.rejectedWith(`recipient address of txPrebuild does not match hop address`);
621
+ });
622
+ it('should fail verify for changed address', async function () {
623
+ const hopDestinationAddressDiff = 'P-costwo15msvr27szvhhpmah0c38gcml7vm29xjh7tcek9~P-costwo1cwrdtrgf4xh80ncu7palrjw7gn4mpj0n4dxghh~P-costwo1zt9n96hey4fsvnde35n3k4kt5pu7c784dzewzd';
624
+ const verifyFlrTransactionOptions = {
625
+ txParams: { ...txParams, recipients: [{ amount: amount, address: hopDestinationAddressDiff }] },
626
+ txPrebuild,
627
+ wallet,
628
+ verification,
629
+ };
630
+ await tflrCoin
631
+ .verifyTransaction(verifyFlrTransactionOptions)
632
+ .should.be.rejectedWith(`Hop destination: ${hopDestinationAddress} does not equal original recipient: ${hopDestinationAddressDiff}`);
633
+ });
634
+ it('should verify if walletId is used instead of address', async function () {
635
+ const verifyFlrTransactionOptions = {
636
+ txParams: { ...txParams, recipients: [{ amount: amount, walletId: 'same wallet' }] },
637
+ txPrebuild,
638
+ wallet,
639
+ verification,
640
+ };
641
+ const isTransactionVerified = await tflrCoin.verifyTransaction(verifyFlrTransactionOptions);
642
+ isTransactionVerified.should.equal(true);
643
+ });
644
+ });
645
+ });
646
+ describe('validateHopPrebuild', function () {
647
+ const validateHopSandbox = sinon.createSandbox();
648
+ afterEach(() => {
649
+ validateHopSandbox.restore();
650
+ });
651
+ it('should throw error for invalid HSM signature', async function () {
652
+ const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
653
+ const hopPrebuild = {
654
+ tx: hopExportTx,
655
+ id: hopExportTxId,
656
+ signature: '0x' + 'aa'.repeat(65), // Invalid signature
657
+ paymentId: '12345',
658
+ gasPrice: 20000000000,
659
+ gasLimit: 500000,
660
+ amount: 1000000000000000,
661
+ recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
662
+ nonce: 0,
663
+ userReqSig: '0x',
664
+ gasPriceMax: 500000000000,
665
+ type: 'Export',
666
+ };
667
+ await tflrCoin
668
+ .validateHopPrebuild(wallet, hopPrebuild)
669
+ .should.be.rejectedWith('Hop txid signature invalid');
670
+ });
671
+ it('should validate Export hop prebuild successfully', async function () {
672
+ validateHopSandbox.stub(tflrCoin, 'verifySignatureForAtomicTransaction').resolves(true);
673
+ const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
674
+ const hopPrebuild = {
675
+ tx: hopExportTx,
676
+ id: hopExportTxId,
677
+ signature: hopExportTxBitgoSignature,
678
+ paymentId: '12345',
679
+ gasPrice: 20000000000,
680
+ gasLimit: 500000,
681
+ amount: 50000000,
682
+ recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
683
+ nonce: 0,
684
+ userReqSig: '0x',
685
+ gasPriceMax: 500000000000,
686
+ type: 'Export',
687
+ };
688
+ // Should not throw
689
+ await tflrCoin.validateHopPrebuild(wallet, hopPrebuild);
690
+ });
691
+ it('should throw error for Export hop prebuild with mismatched amount', async function () {
692
+ const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
693
+ const hopPrebuild = {
694
+ tx: hopExportTx,
695
+ id: hopExportTxId,
696
+ signature: hopExportTxBitgoSignature,
697
+ paymentId: '12345',
698
+ gasPrice: 20000000000,
699
+ gasLimit: 500000,
700
+ amount: 50000000,
701
+ recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
702
+ nonce: 0,
703
+ userReqSig: '0x',
704
+ gasPriceMax: 500000000000,
705
+ type: 'Export',
706
+ };
707
+ const originalParams = {
708
+ recipients: [
709
+ {
710
+ address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
711
+ amount: '999999999999999999', // Wrong amount
712
+ },
713
+ ],
714
+ };
715
+ await tflrCoin
716
+ .validateHopPrebuild(wallet, hopPrebuild, originalParams)
717
+ .should.be.rejectedWith(/Hop amount: .* does not equal original amount/);
718
+ });
719
+ it('should throw error for Export hop prebuild with mismatched destination', async function () {
720
+ const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
721
+ const hopPrebuild = {
722
+ tx: hopExportTx,
723
+ id: hopExportTxId,
724
+ signature: hopExportTxBitgoSignature,
725
+ paymentId: '12345',
726
+ gasPrice: 20000000000,
727
+ gasLimit: 500000,
728
+ amount: 50000000,
729
+ recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
730
+ nonce: 0,
731
+ userReqSig: '0x',
732
+ gasPriceMax: 500000000000,
733
+ type: 'Export',
734
+ };
735
+ const originalParams = {
736
+ recipients: [
737
+ {
738
+ address: 'P-costwo1different~P-costwo1address~P-costwo1here',
739
+ amount: '49800000000000000', // 50000000 - 200000 (txFee) = 49800000 nanoFLR = 49800000000000000 wei
740
+ },
741
+ ],
742
+ };
743
+ await tflrCoin
744
+ .validateHopPrebuild(wallet, hopPrebuild, originalParams)
745
+ .should.be.rejectedWith(/Hop destination: .* does not equal original recipient/);
746
+ });
747
+ });
748
+ describe('presignTransaction', function () {
749
+ it('should return params unchanged when no hopTransaction', async function () {
750
+ const params = {
751
+ txHex: '0x123',
752
+ wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
753
+ buildParams: { recipients: [] },
754
+ };
755
+ const result = await tflrCoin.presignTransaction(params);
756
+ result.should.equal(params);
757
+ });
758
+ it('should call validateHopPrebuild when hopTransaction is present', async function () {
759
+ const sandbox = sinon.createSandbox();
760
+ const validateStub = sandbox.stub(tflrCoin, 'validateHopPrebuild').resolves();
761
+ const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
762
+ const hopTransaction = {
763
+ tx: hopExportTx,
764
+ id: hopExportTxId,
765
+ signature: hopExportTxBitgoSignature,
766
+ paymentId: '12345',
767
+ gasPrice: 20000000000,
768
+ gasLimit: 500000,
769
+ amount: 50000000,
770
+ recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
771
+ nonce: 0,
772
+ userReqSig: '0x',
773
+ gasPriceMax: 500000000000,
774
+ type: 'Export',
775
+ };
776
+ const params = {
777
+ txHex: '0x123',
778
+ wallet: wallet,
779
+ buildParams: { recipients: [] },
780
+ hopTransaction: hopTransaction,
781
+ };
782
+ await tflrCoin.presignTransaction(params);
783
+ validateStub.calledOnce.should.be.true();
784
+ sandbox.restore();
785
+ });
786
+ });
787
+ describe('postProcessPrebuild', function () {
788
+ it('should return params unchanged when no hopTransaction', async function () {
789
+ const params = {
790
+ txHex: '0x123',
791
+ coin: 'tflr',
792
+ };
793
+ const result = await tflrCoin.postProcessPrebuild(params);
794
+ result.should.equal(params);
795
+ });
796
+ it('should call validateHopPrebuild when hopTransaction is present', async function () {
797
+ const sandbox = sinon.createSandbox();
798
+ const validateStub = sandbox.stub(tflrCoin, 'validateHopPrebuild').resolves();
799
+ const wallet = new sdk_core_1.Wallet(bitgo, tflrCoin, {});
800
+ const hopTransaction = {
801
+ tx: hopExportTx,
802
+ id: hopExportTxId,
803
+ signature: hopExportTxBitgoSignature,
804
+ paymentId: '12345',
805
+ gasPrice: 20000000000,
806
+ gasLimit: 500000,
807
+ amount: 50000000,
808
+ recipient: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress,
809
+ nonce: 0,
810
+ userReqSig: '0x',
811
+ gasPriceMax: 500000000000,
812
+ type: 'Export',
813
+ };
814
+ const params = {
815
+ txHex: '0x123',
816
+ wallet: wallet,
817
+ buildParams: { recipients: [{ address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress, amount: '100000000' }] },
818
+ hopTransaction: hopTransaction,
819
+ coin: 'tflr',
820
+ };
821
+ await tflrCoin.postProcessPrebuild(params);
822
+ validateStub.calledOnce.should.be.true();
823
+ sandbox.restore();
824
+ });
825
+ });
826
+ describe('getExtraPrebuildParams', function () {
827
+ const sandbox = sinon.createSandbox();
828
+ afterEach(function () {
829
+ sandbox.restore();
830
+ });
831
+ it('should return empty object when hop is not set', async function () {
832
+ const buildParams = {
833
+ recipients: [{ address: '0x1234', amount: '1000000' }],
834
+ };
835
+ const result = await tflrCoin.getExtraPrebuildParams(buildParams);
836
+ result.should.deepEqual({});
837
+ });
838
+ it('should return empty object when hop is false', async function () {
839
+ const buildParams = {
840
+ hop: false,
841
+ recipients: [{ address: '0x1234', amount: '1000000' }],
842
+ wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
843
+ };
844
+ const result = await tflrCoin.getExtraPrebuildParams(buildParams);
845
+ result.should.deepEqual({});
846
+ });
847
+ it('should return empty object when wallet is missing', async function () {
848
+ const buildParams = {
849
+ hop: true,
850
+ recipients: [{ address: '0x1234', amount: '1000000' }],
851
+ };
852
+ const result = await tflrCoin.getExtraPrebuildParams(buildParams);
853
+ result.should.deepEqual({});
854
+ });
855
+ it('should return empty object when recipients is missing', async function () {
856
+ const buildParams = {
857
+ hop: true,
858
+ wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
859
+ };
860
+ const result = await tflrCoin.getExtraPrebuildParams(buildParams);
861
+ result.should.deepEqual({});
862
+ });
863
+ it('should call createHopTransactionParams when hop is true with all required params', async function () {
864
+ const mockFeeEstimate = {
865
+ feeEstimate: 120000,
866
+ gasLimitEstimate: 500000,
867
+ };
868
+ sandbox.stub(tflrCoin, 'feeEstimate').resolves(mockFeeEstimate);
869
+ const buildParams = {
870
+ hop: true,
871
+ wallet: new sdk_core_1.Wallet(bitgo, tflrCoin, {}),
872
+ recipients: [{ address: resources_1.EXPORT_C_TEST_DATA.pMultisigAddress, amount: '100000000000000000' }],
873
+ type: 'Export',
874
+ };
875
+ const result = await tflrCoin.getExtraPrebuildParams(buildParams);
876
+ result.should.have.property('hopParams');
877
+ });
878
+ });
879
+ describe('feeEstimate', function () {
880
+ it('should make API call with correct query parameters', async function () {
881
+ const expectedFeeEstimate = {
882
+ feeEstimate: 120000,
883
+ gasLimitEstimate: 500000,
884
+ };
885
+ (0, nock_1.default)('https://app.bitgo-test.com')
886
+ .get('/api/v2/tflr/tx/fee')
887
+ .query({
888
+ hop: true,
889
+ recipient: '0x1234',
890
+ amount: '1000000',
891
+ type: 'Export',
892
+ })
893
+ .reply(200, expectedFeeEstimate);
894
+ const result = await tflrCoin.feeEstimate({
895
+ hop: true,
896
+ recipient: '0x1234',
897
+ amount: '1000000',
898
+ type: 'Export',
899
+ });
900
+ result.feeEstimate.should.equal(expectedFeeEstimate.feeEstimate);
901
+ result.gasLimitEstimate.should.equal(expectedFeeEstimate.gasLimitEstimate);
902
+ });
903
+ it('should make API call with data parameter', async function () {
904
+ const expectedFeeEstimate = {
905
+ feeEstimate: 150000,
906
+ gasLimitEstimate: 600000,
907
+ };
908
+ (0, nock_1.default)('https://app.bitgo-test.com')
909
+ .get('/api/v2/tflr/tx/fee')
910
+ .query({
911
+ recipient: '0x5678',
912
+ data: '0xabcdef',
913
+ })
914
+ .reply(200, expectedFeeEstimate);
915
+ const result = await tflrCoin.feeEstimate({
916
+ recipient: '0x5678',
917
+ data: '0xabcdef',
918
+ });
919
+ result.feeEstimate.should.equal(expectedFeeEstimate.feeEstimate);
920
+ result.gasLimitEstimate.should.equal(expectedFeeEstimate.gasLimitEstimate);
921
+ });
922
+ });
923
+ describe('getTxHash', function () {
924
+ it('should calculate correct keccak256 hash for tx hex', function () {
925
+ const txHex = resources_1.EXPORT_C_TEST_DATA.fullsigntxHex;
926
+ const hash = tflrCoin.constructor.getTxHash(txHex);
927
+ hash.should.be.instanceOf(Buffer);
928
+ hash.length.should.equal(32);
929
+ // Verify it matches our helper function
930
+ const expectedHash = getTxHash(txHex);
931
+ hash.toString('hex').should.equal(expectedHash.toString('hex'));
932
+ });
933
+ it('should handle tx hex with 0x prefix', function () {
934
+ const txHex = '0x' + 'abcd'.repeat(10);
935
+ const hash = tflrCoin.constructor.getTxHash(txHex);
936
+ hash.should.be.instanceOf(Buffer);
937
+ hash.length.should.equal(32);
938
+ });
939
+ it('should handle tx hex without 0x prefix', function () {
940
+ const txHex = 'abcd'.repeat(10);
941
+ const hash = tflrCoin.constructor.getTxHash(txHex);
942
+ hash.should.be.instanceOf(Buffer);
943
+ hash.length.should.equal(32);
944
+ });
945
+ });
946
+ });
947
+ describe('Build Unsigned Sweep for Self-Custody Cold Wallets - (MPCv2)', function () {
948
+ const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
949
+ const explorerUrl = sdk_core_1.common.Environments[bitgo.getEnv()].flrExplorerBaseUrl;
950
+ const maxFeePerGasvalue = 30000000000;
951
+ const maxPriorityFeePerGasValue = 15000000000;
952
+ const chain_id = 114;
953
+ const gasLimitvalue = 500000;
954
+ it('should generate an unsigned sweep without derivation path', async () => {
955
+ (0, nock_1.default)(explorerUrl)
956
+ .get('/api')
957
+ .twice()
958
+ .query(resources_1.mockDataUnsignedSweep.getTxListRequest)
959
+ .reply(200, resources_1.mockDataUnsignedSweep.getTxListResponse);
960
+ (0, nock_1.default)(explorerUrl)
961
+ .get('/api')
962
+ .query(resources_1.mockDataUnsignedSweep.getBalanceRequest)
963
+ .reply(200, resources_1.mockDataUnsignedSweep.getBalanceResponse);
964
+ const baseCoin = bitgo.coin('tflr');
965
+ const transaction = (await baseCoin.recover({
966
+ userKey: resources_1.mockDataUnsignedSweep.userKey,
967
+ backupKey: resources_1.mockDataUnsignedSweep.backupKey,
968
+ walletContractAddress: resources_1.mockDataUnsignedSweep.walletBaseAddress,
969
+ recoveryDestination: resources_1.mockDataUnsignedSweep.recoveryDestination,
970
+ isTss: true,
971
+ eip1559: { maxFeePerGas: maxFeePerGasvalue, maxPriorityFeePerGas: maxPriorityFeePerGasValue },
972
+ gasLimit: gasLimitvalue,
973
+ replayProtectionOptions: {
974
+ chain: chain_id,
975
+ hardfork: 'london',
976
+ },
977
+ }));
978
+ should.exist(transaction);
979
+ transaction.should.have.property('txRequests');
980
+ transaction.txRequests.length.should.equal(1);
981
+ const txRequest = transaction.txRequests[0];
982
+ txRequest.should.have.property('walletCoin');
983
+ txRequest.walletCoin.should.equal('tflr');
984
+ txRequest.should.have.property('transactions');
985
+ txRequest.transactions.length.should.equal(1);
986
+ const tx = txRequest.transactions[0];
987
+ tx.should.have.property('nonce');
988
+ tx.should.have.property('unsignedTx');
989
+ tx.unsignedTx.should.have.property('serializedTxHex');
990
+ tx.unsignedTx.should.have.property('signableHex');
991
+ tx.unsignedTx.should.have.property('derivationPath');
992
+ tx.unsignedTx.should.have.property('feeInfo');
993
+ tx.unsignedTx.feeInfo?.should.have.property('fee');
994
+ tx.unsignedTx.feeInfo?.should.have.property('feeString');
995
+ tx.unsignedTx.should.have.property('parsedTx');
996
+ tx.unsignedTx.parsedTx?.should.have.property('spendAmount');
997
+ tx.unsignedTx.parsedTx?.should.have.property('outputs');
998
+ });
999
+ });
1000
+ describe('Non Bitgo Recovery for Hot Wallets', function () {
1001
+ const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1002
+ const explorerUrl = sdk_core_1.common.Environments[bitgo.getEnv()].flrExplorerBaseUrl;
1003
+ const maxFeePerGasvalue = 30000000000;
1004
+ const maxPriorityFeePerGasValue = 15000000000;
1005
+ const chain_id = 114;
1006
+ const gasLimitvalue = 500000;
1007
+ it('should generate a signed non-bitgo recovery tx', async () => {
1008
+ (0, nock_1.default)(explorerUrl)
1009
+ .get('/api')
1010
+ .twice()
1011
+ .query(resources_1.mockDataNonBitGoRecovery.getTxListRequest)
1012
+ .reply(200, resources_1.mockDataNonBitGoRecovery.getTxListResponse);
1013
+ (0, nock_1.default)(explorerUrl)
1014
+ .get('/api')
1015
+ .query(resources_1.mockDataNonBitGoRecovery.getBalanceRequest)
1016
+ .reply(200, resources_1.mockDataNonBitGoRecovery.getBalanceResponse);
1017
+ const baseCoin = bitgo.coin('tflr');
1018
+ const transaction = await baseCoin.recover({
1019
+ userKey: resources_1.mockDataNonBitGoRecovery.userKeyData,
1020
+ backupKey: resources_1.mockDataNonBitGoRecovery.backupKeyData,
1021
+ walletContractAddress: resources_1.mockDataNonBitGoRecovery.walletRootAddress,
1022
+ walletPassphrase: resources_1.mockDataNonBitGoRecovery.walletPassphrase,
1023
+ recoveryDestination: resources_1.mockDataNonBitGoRecovery.recoveryDestination,
1024
+ isTss: true,
1025
+ eip1559: { maxFeePerGas: maxFeePerGasvalue, maxPriorityFeePerGas: maxPriorityFeePerGasValue },
1026
+ gasLimit: gasLimitvalue,
1027
+ replayProtectionOptions: {
1028
+ chain: chain_id,
1029
+ hardfork: 'london',
1030
+ },
1031
+ });
1032
+ should.exist(transaction);
1033
+ transaction.should.have.property('id');
1034
+ transaction.should.have.property('tx');
1035
+ const tx = tx_1.FeeMarketEIP1559Transaction.fromSerializedTx(Buffer.from((0, util_1.stripHexPrefix)(transaction.tx), 'hex'));
1036
+ tx.getSenderAddress().toString().should.equal(resources_1.mockDataNonBitGoRecovery.walletRootAddress);
1037
+ const jsonTx = tx.toJSON();
1038
+ jsonTx.to?.should.equal(resources_1.mockDataNonBitGoRecovery.recoveryDestination);
1039
+ });
1040
+ });
1041
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2Zsci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtDQUFpQztBQUVqQyxtREFBK0Q7QUFDL0QsaURBQStDO0FBRS9DLDJDQUE0QztBQUc1Qyw0Q0FBbUc7QUFDbkcsZ0RBQXdCO0FBQ3hCLG1EQUF1RTtBQUN2RSx1Q0FBNkQ7QUFDN0QsMkNBQWtEO0FBQ2xELDZDQUErQjtBQUMvQixxREFBOEM7QUFDOUMscURBQXVDO0FBQ3ZDLG9EQUE0QjtBQUU1QixpREFBaUQ7QUFDakQsU0FBUyxTQUFTLENBQUMsRUFBVTtJQUMzQixNQUFNLElBQUksR0FBRyxJQUFBLGdCQUFNLEVBQUMsV0FBVyxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDM0QsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7QUFDdkIsQ0FBQztBQUVELFFBQVEsQ0FBQyxLQUFLLEVBQUU7SUFDZCxJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFRLENBQUM7SUFDYixJQUFJLE9BQU8sQ0FBQztJQUNaLElBQUkseUJBQXlCLENBQUM7SUFFOUIsTUFBTSxRQUFRLEdBQUcsNENBQTRDLENBQUM7SUFDOUQsTUFBTSxXQUFXLEdBQUcsOEJBQWtCLENBQUMsYUFBYSxDQUFDO0lBQ3JELE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXBFLE1BQU0sQ0FBQztRQUNMLE1BQU0sWUFBWSxHQUNoQixpSEFB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RSxhQUFhO1lBQ3ZCLHVCQUF1QixFQUFFO2dCQUN2QixLQUFLLEVBQUUsUUFBUTtnQkFDZixRQUFRLEVBQUUsUUFBUTthQUNuQjtTQUNGLENBQUMsQ0FBQztRQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDMUIsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxNQUFNLEVBQUUsR0FBRyxnQ0FBMkIsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUEscUJBQWMsRUFBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUM1RyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLG9DQUF3QixDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDMUYsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzNCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxvQ0FBd0IsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ3hFLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBzaG91bGQgZnJvbSAnc2hvdWxkJztcblxuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuXG5pbXBvcnQgeyBGbHIsIFRmbHIgfSBmcm9tICcuLi8uLi9zcmMvaW5kZXgnO1xuaW1wb3J0IHsgRXhwbGFpblRyYW5zYWN0aW9uT3B0aW9ucyB9IGZyb20gJy4uLy4uL3NyYy9pZmFjZSc7XG5pbXBvcnQgeyBVbnNpZ25lZFN3ZWVwVHhNUEN2MiB9IGZyb20gJ0BiaXRnby1iZXRhL2Fic3RyYWN0LWV0aCc7XG5pbXBvcnQgeyBtb2NrRGF0YVVuc2lnbmVkU3dlZXAsIG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeSwgRVhQT1JUX0NfVEVTVF9EQVRBIH0gZnJvbSAnLi4vcmVzb3VyY2VzJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0IHsgY29tbW9uLCBUcmFuc2FjdGlvblR5cGUsIFdhbGxldCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IEZlZU1hcmtldEVJUDE1NTlUcmFuc2FjdGlvbiB9IGZyb20gJ0BldGhlcmV1bWpzL3R4JztcbmltcG9ydCB7IHN0cmlwSGV4UHJlZml4IH0gZnJvbSAnQGV0aGVyZXVtanMvdXRpbCc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgeyBiaXAzMiB9IGZyb20gJ0BiaXRnby1iZXRhL3NlY3AyNTZrMSc7XG5pbXBvcnQgKiBhcyBzZWNwMjU2azEgZnJvbSAnc2VjcDI1NmsxJztcbmltcG9ydCBLZWNjYWsgZnJvbSAna2VjY2FrJztcblxuLy8gSGVscGVyIHRvIGNhbGN1bGF0ZSB0eCBoYXNoIGxpa2UgRmxyLmdldFR4SGFzaFxuZnVuY3Rpb24gZ2V0VHhIYXNoKHR4OiBzdHJpbmcpOiBCdWZmZXIge1xuICBjb25zdCBoYXNoID0gS2VjY2FrKCdrZWNjYWsyNTYnKTtcbiAgaGFzaC51cGRhdGUodHguc3RhcnRzV2l0aCgnMHgnKSA/IHR4LnNsaWNlKDIpIDogdHgsICdoZXgnKTtcbiAgcmV0dXJuIGhhc2guZGlnZXN0KCk7XG59XG5cbmRlc2NyaWJlKCdmbHInLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgdGZsckNvaW47XG4gIGxldCBmbHJDb2luO1xuICBsZXQgaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZTtcblxuICBjb25zdCBhZGRyZXNzMiA9ICcweDdlODViZGMyN2MwNTBlMzkwNWViZjRiOGU2MzRkOWFkNmVkZDBkZTYnO1xuICBjb25zdCBob3BFeHBvcnRUeCA9IEVYUE9SVF9DX1RFU1RfREFUQS5mdWxsc2lnbnR4SGV4O1xuICBjb25zdCBob3BFeHBvcnRUeElkID0gJzB4JyArIGdldFR4SGFzaChob3BFeHBvcnRUeCkudG9TdHJpbmcoJ2hleCcpO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYml0Z29LZXlYcHJ2ID1cbiAgICAgICd4cHJ2OXMyMVpyUUgxNDNLM3RwV0JIV2UzMXNMb1hOUlE5QXZSWUpnaXRrS3hRNEFURlFNd3ZyN2hITnFZUlVuUzdQc2p6QjdhSzFWeHFITHVOUWpqMXNja0oySndvMnF4bXN2ZWp3RUNTcEZNZkMnO1xuICAgIGNvbnN0IGJpdGdvS2V5ID0gYmlwMzIuZnJvbUJhc2U1OChiaXRnb0tleVhwcnYpO1xuICAgIGlmICghYml0Z29LZXkucHJpdmF0ZUtleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlS2V5Jyk7XG4gICAgfVxuICAgIGNvbnN0IGJpdGdvWHB1YiA9IGJpdGdvS2V5Lm5ldXRlcmVkKCkudG9CYXNlNTgoKTtcblxuICAgIGhvcEV4cG9ydFR4Qml0Z29TaWduYXR1cmUgPVxuICAgICAgJzB4YWEnICtcbiAgICAgIEJ1ZmZlci5mcm9tKFxuICAgICAgICBzZWNwMjU2azEuZWNkc2FTaWduKEJ1ZmZlci5mcm9tKGhvcEV4cG9ydFR4SWQuc2xpY2UoMiksICdoZXgnKSwgYml0Z29LZXkucHJpdmF0ZUtleSkuc2lnbmF0dXJlXG4gICAgICApLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcignZmxyJywgRmxyLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3RmbHInLCBUZmxyLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS5oc21YcHViID0gYml0Z29YcHViO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICB9KTtcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICB0ZmxyQ29pbiA9IGJpdGdvLmNvaW4oJ3RmbHInKSBhcyBUZmxyO1xuICAgIGZsckNvaW4gPSBiaXRnby5jb2luKCdmbHInKSBhcyBGbHI7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCYXNpYyBDb2luIEluZm8nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdGhlIHJpZ2h0IGluZm8gZm9yIGZscicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGZsciA9IGJpdGdvLmNvaW4oJ2ZscicpO1xuXG4gICAgICBmbHIuc2hvdWxkLmJlLmFuLmluc3RhbmNlb2YoRmxyKTtcbiAgICAgIGZsci5nZXRDaGFpbigpLnNob3VsZC5lcXVhbCgnZmxyJyk7XG4gICAgICBmbHIuZ2V0RmFtaWx5KCkuc2hvdWxkLmVxdWFsKCdmbHInKTtcbiAgICAgIGZsci5nZXRGdWxsTmFtZSgpLnNob3VsZC5lcXVhbCgnRmxhcmUnKTtcbiAgICAgIGZsci5nZXRCYXNlRmFjdG9yKCkuc2hvdWxkLmVxdWFsKDFlMTgpO1xuICAgICAgZmxyLnN1cHBvcnRzVHNzKCkuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgZmxyLmFsbG93c0FjY291bnRDb25zb2xpZGF0aW9ucygpLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0aGUgcmlnaHQgaW5mbyBmb3IgdGZscicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRmbHIgPSBiaXRnby5jb2luKCd0ZmxyJyk7XG5cbiAgICAgIHRmbHIuc2hvdWxkLmJlLmFuLmluc3RhbmNlb2YoVGZscik7XG4gICAgICB0ZmxyLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKCd0ZmxyJyk7XG4gICAgICB0ZmxyLmdldEZhbWlseSgpLnNob3VsZC5lcXVhbCgnZmxyJyk7XG4gICAgICB0ZmxyLmdldEZ1bGxOYW1lKCkuc2hvdWxkLmVxdWFsKCdUZXN0bmV0IGZsYXJlJyk7XG4gICAgICB0ZmxyLmdldEJhc2VGYWN0b3IoKS5zaG91bGQuZXF1YWwoMWUxOCk7XG4gICAgICB0ZmxyLnN1cHBvcnRzVHNzKCkuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgdGZsci5hbGxvd3NBY2NvdW50Q29uc29saWRhdGlvbnMoKS5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUC1DaGFpbiBNZXRob2RzJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZscnAgZm9yIG1haW5uZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAoZmxyQ29pbiBhcyBhbnkpLmdldEZsclAoKS5zaG91bGQuZXF1YWwoJ2ZscnAnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRmbHJwIGZvciB0ZXN0bmV0JywgZnVuY3Rpb24gKCkge1xuICAgICAgKHRmbHJDb2luIGFzIGFueSkuZ2V0RmxyUCgpLnNob3VsZC5lcXVhbCgndGZscnAnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0FkZHJlc3MgVmFsaWRhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHZhbGlkIGV0aCBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcmVzcyA9ICcweDEzNzRhMjA0NjY2MWY5MTRkMTY4N2Q4NWRiYmNlYjlhYzc5MTBhMjknO1xuICAgICAgdGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykuc2hvdWxkLmJlLnRydWUoKTtcbiAgICAgIGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoYWRkcmVzcykuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgYSBQLWNoYWluIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwQWRkcmVzc2VzID0gRVhQT1JUX0NfVEVTVF9EQVRBLnBBZGRyZXNzZXM7XG4gICAgICBmb3IgKGNvbnN0IGFkZHIgb2YgcEFkZHJlc3Nlcykge1xuICAgICAgICB0ZmxyQ29pbi5pc1ZhbGlkQWRkcmVzcyhhZGRyKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgICBmbHJDb2luLmlzVmFsaWRBZGRyZXNzKGFkZHIpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIGEgUC1jaGFpbiBtdWx0aXNpZyBhZGRyZXNzIHN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPSBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcztcbiAgICAgIHRmbHJDb2luLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBmbHJDb2luLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgZW1wdHkgYWRkcmVzcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRmbHJDb2luLmlzVmFsaWRBZGRyZXNzKCcnKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICAgIGZsckNvaW4uaXNWYWxpZEFkZHJlc3MoJycpLnNob3VsZC5iZS5mYWxzZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVG9rZW4gQ2hlY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGlzVG9rZW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0ZmxyQ29pbi5pc1Rva2VuKCkuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgICBmbHJDb2luLmlzVG9rZW4oKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0hvcCBUcmFuc2FjdGlvbiBQYXJhbWV0ZXJzJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBob3AgdHJhbnNhY3Rpb24gcGFyYW1ldGVycyB3aXRoIGdhc1ByaWNlTWF4ID4gMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1vY2tGZWVFc3RpbWF0ZSA9IHtcbiAgICAgICAgZmVlRXN0aW1hdGU6IDEyMDAwMCxcbiAgICAgICAgZ2FzTGltaXRFc3RpbWF0ZTogNTAwMDAwLFxuICAgICAgfTtcbiAgICAgIHNhbmRib3guc3R1Yih0ZmxyQ29pbiwgJ2ZlZUVzdGltYXRlJykucmVzb2x2ZXMobW9ja0ZlZUVzdGltYXRlKTtcbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcyxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgKHRmbHJDb2luIGFzIGFueSkuY3JlYXRlSG9wVHJhbnNhY3Rpb25QYXJhbXMoe1xuICAgICAgICByZWNpcGllbnRzLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBrZXlvZiB0eXBlb2YgVHJhbnNhY3Rpb25UeXBlLFxuICAgICAgfSk7XG5cbiAgICAgIHJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaG9wUGFyYW1zJyk7XG4gICAgICByZXN1bHQuaG9wUGFyYW1zLnNob3VsZC5oYXZlLnByb3BlcnRpZXMoWyd1c2VyUmVxU2lnJywgJ2dhc1ByaWNlTWF4JywgJ3BheW1lbnRJZCcsICdnYXNMaW1pdCddKTtcbiAgICAgIHJlc3VsdC5ob3BQYXJhbXMudXNlclJlcVNpZy5zaG91bGQuZXF1YWwoJzB4Jyk7XG4gICAgICByZXN1bHQuaG9wUGFyYW1zLmdhc1ByaWNlTWF4LnNob3VsZC5iZS5hYm92ZSgwKTtcbiAgICAgIHJlc3VsdC5ob3BQYXJhbXMucGF5bWVudElkLnNob3VsZC5iZS5hLlN0cmluZygpO1xuICAgICAgcmVzdWx0LmhvcFBhcmFtcy5nYXNMaW1pdC5zaG91bGQuZXF1YWwoNTAwMDAwKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgbm8gcmVjaXBpZW50cyBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0ICh0ZmxyQ29pbiBhcyBhbnkpXG4gICAgICAgIC5jcmVhdGVIb3BUcmFuc2FjdGlvblBhcmFtcyh7XG4gICAgICAgICAgcmVjaXBpZW50czogW10sXG4gICAgICAgICAgdHlwZTogJ0V4cG9ydCcgYXMga2V5b2YgdHlwZW9mIFRyYW5zYWN0aW9uVHlwZSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ211c3Qgc2VuZCB0byBleGFjdGx5IDEgcmVjaXBpZW50Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGlmIG1vcmUgdGhhbiAxIHJlY2lwaWVudCBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcyxcbiAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczogRVhQT1JUX0NfVEVTVF9EQVRBLmNIZXhBZGRyZXNzLFxuICAgICAgICAgIGFtb3VudDogJzUwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGF3YWl0ICh0ZmxyQ29pbiBhcyBhbnkpXG4gICAgICAgIC5jcmVhdGVIb3BUcmFuc2FjdGlvblBhcmFtcyh7XG4gICAgICAgICAgcmVjaXBpZW50cyxcbiAgICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBrZXlvZiB0eXBlb2YgVHJhbnNhY3Rpb25UeXBlLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbXVzdCBzZW5kIHRvIGV4YWN0bHkgMSByZWNpcGllbnQnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0V4cGxhaW4gVHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIHVuc2lnbmVkIGV4cG9ydCBpbiBDIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGVzdERhdGEgPSBFWFBPUlRfQ19URVNUX0RBVEE7XG4gICAgICBjb25zdCB0eEV4cGxhaW4gPSBhd2FpdCB0ZmxyQ29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eEhleDogdGVzdERhdGEudW5zaWduZWRUeEhleCxcbiAgICAgICAgY3Jvc3NDaGFpblR5cGU6ICdleHBvcnQnLFxuICAgICAgfSk7XG4gICAgICB0eEV4cGxhaW4udHlwZS5zaG91bGQuZXF1YWwoVHJhbnNhY3Rpb25UeXBlLkV4cG9ydCk7XG4gICAgICB0eEV4cGxhaW4uaW5wdXRzWzBdLmFkZHJlc3MudG9Mb3dlckNhc2UoKS5zaG91bGQuZXF1YWwodGVzdERhdGEuY0hleEFkZHJlc3MudG9Mb3dlckNhc2UoKSk7XG4gICAgICAvLyBPdXRwdXQgYWRkcmVzcyBpcyB0aGUgc29ydGVkIFAtY2hhaW4gYWRkcmVzc2VzIGpvaW5lZCB3aXRoIH5cbiAgICAgIGNvbnN0IHNvcnRlZFBBZGRyZXNzZXMgPSB0ZXN0RGF0YS5wQWRkcmVzc2VzLnNsaWNlKCkuc29ydCgpLmpvaW4oJ34nKTtcbiAgICAgIHR4RXhwbGFpbi5vdXRwdXRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHNvcnRlZFBBZGRyZXNzZXMpO1xuICAgICAgdHhFeHBsYWluLm91dHB1dEFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEuYW1vdW50KTtcbiAgICAgIHNob3VsZC5leGlzdCh0eEV4cGxhaW4uZmVlKTtcbiAgICAgIHR4RXhwbGFpbi5mZWUuZmVlLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mZWUpO1xuICAgICAgdHhFeHBsYWluLmNoYW5nZU91dHB1dHMuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBzaWduZWQgZXhwb3J0IGluIEMgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0ZXN0RGF0YSA9IEVYUE9SVF9DX1RFU1RfREFUQTtcbiAgICAgIGNvbnN0IHR4RXhwbGFpbiA9IGF3YWl0IHRmbHJDb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4SGV4OiB0ZXN0RGF0YS5mdWxsc2lnbnR4SGV4LFxuICAgICAgICBjcm9zc0NoYWluVHlwZTogJ2V4cG9ydCcsXG4gICAgICB9KTtcbiAgICAgIHR4RXhwbGFpbi50eXBlLnNob3VsZC5lcXVhbChUcmFuc2FjdGlvblR5cGUuRXhwb3J0KTtcbiAgICAgIHR4RXhwbGFpbi5pbnB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5jSGV4QWRkcmVzcy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgIC8vIE91dHB1dCBhZGRyZXNzIGlzIHRoZSBzb3J0ZWQgUC1jaGFpbiBhZGRyZXNzZXMgam9pbmVkIHdpdGggflxuICAgICAgY29uc3Qgc29ydGVkUEFkZHJlc3NlcyA9IHRlc3REYXRhLnBBZGRyZXNzZXMuc2xpY2UoKS5zb3J0KCkuam9pbignficpO1xuICAgICAgdHhFeHBsYWluLm91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoc29ydGVkUEFkZHJlc3Nlcyk7XG4gICAgICB0eEV4cGxhaW4ub3V0cHV0QW1vdW50LnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5hbW91bnQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHR4RXhwbGFpbi5mZWUpO1xuICAgICAgdHhFeHBsYWluLmZlZS5mZWUuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZSk7XG4gICAgICB0eEV4cGxhaW4uY2hhbmdlT3V0cHV0cy5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBtaXNzaW5nIHR4SGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgdGZsckNvaW5cbiAgICAgICAgLmV4cGxhaW5UcmFuc2FjdGlvbih7IGNyb3NzQ2hhaW5UeXBlOiAnZXhwb3J0JyB9IGFzIEV4cGxhaW5UcmFuc2FjdGlvbk9wdGlvbnMpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHR4SGV4IGluIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIG1pc3NpbmcgZmVlSW5mbyBmb3Igbm9uLWNyb3NzQ2hhaW4gdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAuZXhwbGFpblRyYW5zYWN0aW9uKHsgdHhIZXg6ICcweDEyMycgfSBhcyBFeHBsYWluVHJhbnNhY3Rpb25PcHRpb25zKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyBmZWVJbmZvIGluIGV4cGxhaW4gdHggcGFyYW1ldGVycycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVHJhbnNhY3Rpb24gVmVyaWZpY2F0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gY2xpZW50IHR4UGFyYW1zIGFyZSBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSBudWxsO1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogZmFsc2UsXG4gICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcGFyYW1zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCB0eFByZWJ1aWxkIHRoYXQgaXMgYm90aCBiYXRjaCBhbmQgaG9wJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9LFxuICAgICAgICAgIHsgYW1vdW50OiAnMjUwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDdlODViZGMyN2MwNTBlMzkwNWViZjRiOGU2MzRkOWFkNmVkZDBkZTYnIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBob3A6IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICczNTAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfV0sXG4gICAgICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgaXNCYXRjaDogdHJ1ZSxcbiAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ2Zha2VXYWxsZXRDb250cmFjdEFkZHJlc3MnLFxuICAgICAgICBob3BUcmFuc2FjdGlvbjoge1xuICAgICAgICAgIHR4OiAnMHgwJyxcbiAgICAgICAgICBpZDogJzB4MCcsXG4gICAgICAgICAgc2lnbmF0dXJlOiAnMHgwJyxcbiAgICAgICAgICBwYXltZW50SWQ6ICcwJyxcbiAgICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgICBhbW91bnQ6IDEwMDAwMDAwMDAwMDAwMDAsXG4gICAgICAgICAgcmVjaXBpZW50OiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyxcbiAgICAgICAgICBub25jZTogMCxcbiAgICAgICAgICB1c2VyUmVxU2lnOiAnMHgwJyxcbiAgICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkOiB0eFByZWJ1aWxkIGFzIGFueSwgd2FsbGV0LCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3R4IGNhbm5vdCBiZSBib3RoIGEgYmF0Y2ggYW5kIGhvcCB0cmFuc2FjdGlvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgYSB0eFByZWJ1aWxkIHdpdGggbW9yZSB0aGFuIG9uZSByZWNpcGllbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHsgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDEzNzRhMjA0NjY2MWY5MTRkMTY4N2Q4NWRiYmNlYjlhYzc5MTBhMjknIH0sXG4gICAgICAgICAgeyBhbW91bnQ6ICcyNTAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4N2U4NWJkYzI3YzA1MGUzOTA1ZWJmNGI4ZTYzNGQ5YWQ2ZWRkMGRlNicgfSxcbiAgICAgICAgXSxcbiAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfSxcbiAgICAgICAgICB7IGFtb3VudDogJzI1MDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHg3ZTg1YmRjMjdjMDUwZTM5MDVlYmY0YjhlNjM0ZDlhZDZlZGQwZGU2JyB9LFxuICAgICAgICBdLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IHRydWUsXG4gICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIGB0ZmxyIGRvZXNuJ3Qgc3VwcG9ydCBzZW5kaW5nIHRvIG1vcmUgdGhhbiAxIGRlc3RpbmF0aW9uIGFkZHJlc3Mgd2l0aGluIGEgc2luZ2xlIHRyYW5zYWN0aW9uLiBUcnkgYWdhaW4sIHVzaW5nIG9ubHkgYSBzaW5nbGUgcmVjaXBpZW50LmBcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgdHhQcmVidWlsZCBmcm9tIHRoZSBiaXRnbyBzZXJ2ZXIgd2l0aCB0aGUgd3JvbmcgY29pbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnMTAwMDAwMDAwMDAwMCcsIGFkZHJlc3M6ICcweDEzNzRhMjA0NjY2MWY5MTRkMTY4N2Q4NWRiYmNlYjlhYzc5MTBhMjknIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAnYnRjJyxcbiAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6ICdmYWtlV2FsbGV0Q29udHJhY3RBZGRyZXNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksIHdhbGxldCwgdmVyaWZpY2F0aW9uIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdjb2luIGluIHR4UHJlYnVpbGQgZGlkIG5vdCBtYXRjaCB0aGF0IGluIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCcpO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ1RTUyBUcmFuc2FjdGlvbiBWZXJpZmljYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIFRTUyB0cmFuc2ZlciB0cmFuc2FjdGlvbiB3aXRob3V0IHR4UHJlYnVpbGQucmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcblxuICAgICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHg0ZTFlM2Q0ODU2YWQ4YjMzMzUyZWIzYWRkNWZmMTJlYTMyMDYxNjlhJyB9XSxcbiAgICAgICAgICB0eXBlOiAndHJhbnNmZXInLFxuICAgICAgICAgIGlzVHNzOiB0cnVlLFxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFRTUyB0eFByZWJ1aWxkIHR5cGljYWxseSBoYXMgYnVpbGRQYXJhbXMucmVjaXBpZW50cyBidXQgbm90IHJlY2lwaWVudHMgZGlyZWN0bHlcbiAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgICAgdHhSZXF1ZXN0SWQ6ICdmYWtlLXR4LXJlcXVlc3QtaWQnLFxuICAgICAgICAgIHR4SGV4OlxuICAgICAgICAgICAgJzAyZjE3MjgxZDkwMjg1MGJhNDNiNzQwMjgzMDYxYTgwOTQ0ZTFlM2Q0ODU2YWQ4YjMzMzUyZWIzYWRkNWZmMTJlYTMyMDYxNjlhODgwMTYzNDU3ODVkOGEwMDAwODBjMDgwODA4MCcsXG4gICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6ICcweDRlMWUzZDQ4NTZhZDhiMzMzNTJlYjNhZGQ1ZmYxMmVhMzIwNjE2OWEnLCBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnIH1dLFxuICAgICAgICAgICAgdHlwZTogJ3RyYW5zZmVyJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZlZUluZm86IHsgZmVlOiAxMDAwMDAwMDAwMDgwMDAwMCwgZmVlU3RyaW5nOiAnMTAwMDAwMDAwMDA4MDAwMDAnIH0sXG4gICAgICAgICAgY29pbjogJ3RmbHInLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICAgIC8vIFdoZW4gd2FsbGV0VHlwZSBpcyAndHNzJywgaXQgc2hvdWxkIGRlbGVnYXRlIHRvIHBhcmVudCdzIHZlcmlmeVRyYW5zYWN0aW9uXG4gICAgICAgIC8vIHdoaWNoIGhhbmRsZXMgVFNTIHRyYW5zYWN0aW9ucyB3aXRob3V0IHJlcXVpcmluZyB0eFByZWJ1aWxkLnJlY2lwaWVudHNcbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgdGZsckNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zLFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyBjb25zb2xpZGF0aW9uIHRyYW5zYWN0aW9uIHdoZW4gdHhQcmVidWlsZCBoYXMgY29uc29saWRhdGVJZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHtcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyB0eFBhcmFtcyB3aXRob3V0IHJlY2lwaWVudHMgKGFzIGluIGNvbnNvbGlkYXRpb24gZmxvdylcbiAgICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyB0eFByZWJ1aWxkIHdpdGggY29uc29saWRhdGVJZCAoc2V0IGJ5IHNlcnZlciBkdXJpbmcgY29uc29saWRhdGlvbiBidWlsZClcbiAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgICBjb25zb2xpZGF0ZUlkOiAnNjhhN2Q1ZDBjNjZlNzRlMjE2Yjk3MTczYmQ1NThjNmQnLFxuICAgICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgdGZsckNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB0eFBhcmFtcyBhcyBhbnksXG4gICAgICAgICAgdHhQcmVidWlsZDogdHhQcmVidWlsZCBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbixcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB2ZXJpZnkgVFNTIHRyYW5zYWN0aW9uIHdoZW4gdHhQYXJhbXMudHlwZSBpcyBjb25zb2xpZGF0ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHtcbiAgICAgICAgICBjb2luU3BlY2lmaWM6IHtcbiAgICAgICAgICAgIGJhc2VBZGRyZXNzOiAnMHgxNzRjZmQ4MjNhZjhjZTI3ZWQwYWZlZTNmY2YzYzNiYTI1OTExNmJlJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgICB0eXBlOiAnY29uc29saWRhdGUnLFxuICAgICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgICB0eEhleDogJzB4JyxcbiAgICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyB0cmFuc2FjdGlvbiB3aXRoIGFjY2VsZXJhdGlvbiB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge1xuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHR5cGU6ICdhY2NlbGVyYXRpb24nLFxuICAgICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgICB0eEhleDogJzB4JyxcbiAgICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdmVyaWZ5IFRTUyB0cmFuc2FjdGlvbiB3aXRoIGZpbGxOb25jZSB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge1xuICAgICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgICAgYmFzZUFkZHJlc3M6ICcweDE3NGNmZDgyM2FmOGNlMjdlZDBhZmVlM2ZjZjNjM2JhMjU5MTE2YmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICAgIHR5cGU6ICdmaWxsTm9uY2UnLFxuICAgICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdmYWtlV2FsbGV0UGFzc3BocmFzZScsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgICB0eEhleDogJzB4JyxcbiAgICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgICAgd2FsbGV0SWQ6ICdmYWtlV2FsbGV0SWQnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogdHhQYXJhbXMgYXMgYW55LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pO1xuICAgICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IFRTUyB0cmFuc2FjdGlvbiB3aXRob3V0IHJlY2lwaWVudHMsIGNvbnNvbGlkYXRlSWQsIG9yIHZhbGlkIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7XG4gICAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgICBiYXNlQWRkcmVzczogJzB4MTc0Y2ZkODIzYWY4Y2UyN2VkMGFmZWUzZmNmM2MzYmEyNTkxMTZiZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIHR4SGV4OiAnMHgnLFxuICAgICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgYXdhaXQgdGZsckNvaW5cbiAgICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQYXJhbXM6IHR4UGFyYW1zIGFzIGFueSxcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgICAgd2FsbGV0LFxuICAgICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyB0eFBhcmFtcycpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgc3RpbGwgdXNlIEZMUi1zcGVjaWZpYyB2ZXJpZmljYXRpb24gZm9yIG5vbi1UU1Mgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcblxuICAgICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwJywgYWRkcmVzczogJzB4MTM3NGEyMDQ2NjYxZjkxNGQxNjg3ZDg1ZGJiY2ViOWFjNzkxMGEyOScgfV0sXG4gICAgICAgICAgd2FsbGV0OiB3YWxsZXQsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ2Zha2VXYWxsZXRQYXNzcGhyYXNlJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFtb3VudDogJzEwMDAwMDAwMDAwMDAnLCBhZGRyZXNzOiAnMHgxMzc0YTIwNDY2NjFmOTE0ZDE2ODdkODVkYmJjZWI5YWM3OTEwYTI5JyB9XSxcbiAgICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgICAgICB3YWxsZXRJZDogJ2Zha2VXYWxsZXRJZCcsXG4gICAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgICAgLy8gV2l0aG91dCB3YWxsZXRUeXBlIG9yIHdpdGggd2FsbGV0VHlwZTogJ29uY2hhaW4nLCBzaG91bGQgdXNlIEZMUidzIG93biB2ZXJpZmljYXRpb25cbiAgICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgdGZsckNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zLFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHR4UHJlYnVpbGQgYXMgYW55LFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ29uY2hhaW4nLFxuICAgICAgICB9KTtcbiAgICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ0hvcCBleHBvcnQgdHggdmVyaWZ5JywgKCkgPT4ge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcbiAgICAgIGNvbnN0IGhvcERlc3RpbmF0aW9uQWRkcmVzcyA9XG4gICAgICAgICdQLWNvc3R3bzE1bXN2cjI3c3p2aGhwbWFoMGMzOGdjbWw3dm0yOXhqaDd0Y2VrOH5QLWNvc3R3bzFjd3JkdHJnZjR4aDgwbmN1N3BhbHJqdzdnbjRtcGowbjRkeGdoaH5QLWNvc3R3bzF6dDluOTZoZXk0ZnN2bmRlMzVuM2s0a3Q1cHU3Yzc4NGR6ZXd6ZCc7XG4gICAgICBjb25zdCBob3BBZGRyZXNzID0gJzB4MjhBMDU5MzNkQzc2ZTRlNmMyNWYzNUQ1YzliMkE1ODc2OTcwMEU3Nic7XG4gICAgICBjb25zdCBpbXBvcnRUeEZlZSA9IDIwMDAwMDsgLy8gTWF0Y2ggRmxhcmVQVGVzdG5ldCB0eEZlZSBmcm9tIG5ldHdvcmtzLnRzXG4gICAgICAvLyBBZGp1c3RlZCBhbW91bnQgdG8gd29yayBiYWNrd2FyZHMgZnJvbSBob3AgYW1vdW50ICg1MDAwMDAwMCk6IDUwMDAwMDAwIC0gMjAwMDAwID0gNDk4MDAwMDAgbmFub0ZMUlxuICAgICAgY29uc3QgYW1vdW50ID0gNDk4MDAwMDAwMDAwMDAwMDA7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50LCBhZGRyZXNzOiBob3BEZXN0aW5hdGlvbkFkZHJlc3MgfV0sXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiAnZmFrZVdhbGxldFBhc3NwaHJhc2UnLFxuICAgICAgICBob3A6IHRydWUsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYW1vdW50OiAnNTEwMDAwNTAwMDAwMDAwMDAnLCBhZGRyZXNzOiBob3BBZGRyZXNzIH1dLFxuICAgICAgICBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGlzQmF0Y2g6IGZhbHNlLFxuICAgICAgICBjb2luOiAndGZscicsXG4gICAgICAgIHdhbGxldElkOiAnZmFrZVdhbGxldElkJyxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiAnZmFrZVdhbGxldENvbnRyYWN0QWRkcmVzcycsXG4gICAgICAgIGhvcFRyYW5zYWN0aW9uOiB7XG4gICAgICAgICAgdHg6IGhvcEV4cG9ydFR4LFxuICAgICAgICAgIGlkOiBob3BFeHBvcnRUeElkLFxuICAgICAgICAgIHNpZ25hdHVyZTogaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgICBwYXltZW50SWQ6ICc0OTMzMzQ5OTg0JyxcbiAgICAgICAgICBnYXNQcmljZTogJzUwJyxcbiAgICAgICAgICBnYXNMaW1pdDogMSxcbiAgICAgICAgICBhbW91bnQ6ICc1MDAwMDAwMCcsXG4gICAgICAgICAgcmVjaXBpZW50OiBob3BEZXN0aW5hdGlvbkFkZHJlc3MsXG4gICAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgICAgdXNlclJlcVNpZzpcbiAgICAgICAgICAgICcweDA2ZmQwYjFmODg1OWE0MGQ5ZmIyZDFhNjVkNTRkYTVkNjQ1YTFkODFiYmI4YzFjNWIwMzcwNTE4NDNlYzBkM2MyMjQzM2VjN2Y1MGNjOTdmYTA0MWNiZjhkOWZmNWRkZjdlZDQxZjcyYTA4ZmEzZjE5ODNmZDY1MWEzM2E0NDQxJyxcbiAgICAgICAgICBnYXNQcmljZU1heDogNzE4NzUwMDAwMCxcbiAgICAgICAgICB0eXBlOiAnRXhwb3J0JyxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuICAgICAgY29uc3Qgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICAgICAgYmVmb3JlKCgpID0+IHtcbiAgICAgICAgdHhQcmVidWlsZC5ob3BUcmFuc2FjdGlvbi5zaWduYXR1cmUgPSBob3BFeHBvcnRUeEJpdGdvU2lnbmF0dXJlO1xuICAgICAgfSk7XG5cbiAgICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgICBzYW5kYm94LnN0dWIodGZsckNvaW4gYXMgYW55LCAndmVyaWZ5U2lnbmF0dXJlRm9yQXRvbWljVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBhZnRlckVhY2goKCkgPT4ge1xuICAgICAgICBzYW5kYm94LnJlc3RvcmUoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBzdWNjZXNzZnVsbHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyA9IHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHdhbGxldCwgdmVyaWZpY2F0aW9uIH07XG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSBmb3IgYW1vdW50IHBsdXMgMScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgdmVyaWZ5RmxyVHJhbnNhY3Rpb25PcHRpb25zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7IC4uLnR4UGFyYW1zLCByZWNpcGllbnRzOiBbeyBhbW91bnQ6IGFtb3VudCArIDFlOSwgYWRkcmVzczogaG9wRGVzdGluYXRpb25BZGRyZXNzIH1dIH0sXG4gICAgICAgICAgdHhQcmVidWlsZCxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucylcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIGBIb3AgYW1vdW50OiAke2Ftb3VudCAvIDFlOSArIGltcG9ydFR4RmVlfSBkb2VzIG5vdCBlcXVhbCBvcmlnaW5hbCBhbW91bnQ6ICR7XG4gICAgICAgICAgICAgIGFtb3VudCAvIDFlOSArIGltcG9ydFR4RmVlICsgMVxuICAgICAgICAgICAgfWBcbiAgICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZmFpbCB2ZXJpZnkgZm9yIGNoYW5nZWQgcHJlYnVpbGQgaG9wIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyA9IHtcbiAgICAgICAgICB0eFBhcmFtcyxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IC4uLnR4UHJlYnVpbGQsIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IGFkZHJlc3MyLCBhbW91bnQ6ICc1MTAwMDA1MDAwMDAwMDAwMCcgfV0gfSxcbiAgICAgICAgICB3YWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uLFxuICAgICAgICB9O1xuICAgICAgICBhd2FpdCB0ZmxyQ29pblxuICAgICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih2ZXJpZnlGbHJUcmFuc2FjdGlvbk9wdGlvbnMpXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoYHJlY2lwaWVudCBhZGRyZXNzIG9mIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggaG9wIGFkZHJlc3NgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGZhaWwgdmVyaWZ5IGZvciBjaGFuZ2VkIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGhvcERlc3RpbmF0aW9uQWRkcmVzc0RpZmYgPVxuICAgICAgICAgICdQLWNvc3R3bzE1bXN2cjI3c3p2aGhwbWFoMGMzOGdjbWw3dm0yOXhqaDd0Y2VrOX5QLWNvc3R3bzFjd3JkdHJnZjR4aDgwbmN1N3BhbHJqdzdnbjRtcGowbjRkeGdoaH5QLWNvc3R3bzF6dDluOTZoZXk0ZnN2bmRlMzVuM2s0a3Q1cHU3Yzc4NGR6ZXd6ZCc7XG4gICAgICAgIGNvbnN0IHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyA9IHtcbiAgICAgICAgICB0eFBhcmFtczogeyAuLi50eFBhcmFtcywgcmVjaXBpZW50czogW3sgYW1vdW50OiBhbW91bnQsIGFkZHJlc3M6IGhvcERlc3RpbmF0aW9uQWRkcmVzc0RpZmYgfV0gfSxcbiAgICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IHRmbHJDb2luXG4gICAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucylcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIGBIb3AgZGVzdGluYXRpb246ICR7aG9wRGVzdGluYXRpb25BZGRyZXNzfSBkb2VzIG5vdCBlcXVhbCBvcmlnaW5hbCByZWNpcGllbnQ6ICR7aG9wRGVzdGluYXRpb25BZGRyZXNzRGlmZn1gXG4gICAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHZlcmlmeSBpZiB3YWxsZXRJZCBpcyB1c2VkIGluc3RlYWQgb2YgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgdmVyaWZ5RmxyVHJhbnNhY3Rpb25PcHRpb25zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7IC4uLnR4UGFyYW1zLCByZWNpcGllbnRzOiBbeyBhbW91bnQ6IGFtb3VudCwgd2FsbGV0SWQ6ICdzYW1lIHdhbGxldCcgfV0gfSxcbiAgICAgICAgICB0eFByZWJ1aWxkLFxuICAgICAgICAgIHdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb24sXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IHRmbHJDb2luLnZlcmlmeVRyYW5zYWN0aW9uKHZlcmlmeUZsclRyYW5zYWN0aW9uT3B0aW9ucyk7XG4gICAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ZhbGlkYXRlSG9wUHJlYnVpbGQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdmFsaWRhdGVIb3BTYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgIHZhbGlkYXRlSG9wU2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnZhbGlkIEhTTSBzaWduYXR1cmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wUHJlYnVpbGQgPSB7XG4gICAgICAgIHR4OiBob3BFeHBvcnRUeCxcbiAgICAgICAgaWQ6IGhvcEV4cG9ydFR4SWQsXG4gICAgICAgIHNpZ25hdHVyZTogJzB4JyArICdhYScucmVwZWF0KDY1KSwgLy8gSW52YWxpZCBzaWduYXR1cmVcbiAgICAgICAgcGF5bWVudElkOiAnMTIzNDUnLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGFtb3VudDogMTAwMDAwMDAwMDAwMDAwMCxcbiAgICAgICAgcmVjaXBpZW50OiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcyxcbiAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgIHVzZXJSZXFTaWc6ICcweCcsXG4gICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnIGFzIGNvbnN0LFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgKHRmbHJDb2luIGFzIGFueSlcbiAgICAgICAgLnZhbGlkYXRlSG9wUHJlYnVpbGQod2FsbGV0LCBob3BQcmVidWlsZClcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0hvcCB0eGlkIHNpZ25hdHVyZSBpbnZhbGlkJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIEV4cG9ydCBob3AgcHJlYnVpbGQgc3VjY2Vzc2Z1bGx5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgdmFsaWRhdGVIb3BTYW5kYm94LnN0dWIodGZsckNvaW4gYXMgYW55LCAndmVyaWZ5U2lnbmF0dXJlRm9yQXRvbWljVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyh0cnVlKTtcblxuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcbiAgICAgIGNvbnN0IGhvcFByZWJ1aWxkID0ge1xuICAgICAgICB0eDogaG9wRXhwb3J0VHgsXG4gICAgICAgIGlkOiBob3BFeHBvcnRUeElkLFxuICAgICAgICBzaWduYXR1cmU6IGhvcEV4cG9ydFR4Qml0Z29TaWduYXR1cmUsXG4gICAgICAgIHBheW1lbnRJZDogJzEyMzQ1JyxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBhbW91bnQ6IDUwMDAwMDAwLFxuICAgICAgICByZWNpcGllbnQ6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICBub25jZTogMCxcbiAgICAgICAgdXNlclJlcVNpZzogJzB4JyxcbiAgICAgICAgZ2FzUHJpY2VNYXg6IDUwMDAwMDAwMDAwMCxcbiAgICAgICAgdHlwZTogJ0V4cG9ydCcgYXMgY29uc3QsXG4gICAgICB9O1xuXG4gICAgICAvLyBTaG91bGQgbm90IHRocm93XG4gICAgICBhd2FpdCAodGZsckNvaW4gYXMgYW55KS52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgaG9wUHJlYnVpbGQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgRXhwb3J0IGhvcCBwcmVidWlsZCB3aXRoIG1pc21hdGNoZWQgYW1vdW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KTtcbiAgICAgIGNvbnN0IGhvcFByZWJ1aWxkID0ge1xuICAgICAgICB0eDogaG9wRXhwb3J0VHgsXG4gICAgICAgIGlkOiBob3BFeHBvcnRUeElkLFxuICAgICAgICBzaWduYXR1cmU6IGhvcEV4cG9ydFR4Qml0Z29TaWduYXR1cmUsXG4gICAgICAgIHBheW1lbnRJZDogJzEyMzQ1JyxcbiAgICAgICAgZ2FzUHJpY2U6IDIwMDAwMDAwMDAwLFxuICAgICAgICBnYXNMaW1pdDogNTAwMDAwLFxuICAgICAgICBhbW91bnQ6IDUwMDAwMDAwLFxuICAgICAgICByZWNpcGllbnQ6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICBub25jZTogMCxcbiAgICAgICAgdXNlclJlcVNpZzogJzB4JyxcbiAgICAgICAgZ2FzUHJpY2VNYXg6IDUwMDAwMDAwMDAwMCxcbiAgICAgICAgdHlwZTogJ0V4cG9ydCcgYXMgY29uc3QsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLFxuICAgICAgICAgICAgYW1vdW50OiAnOTk5OTk5OTk5OTk5OTk5OTk5JywgLy8gV3JvbmcgYW1vdW50XG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0ICh0ZmxyQ29pbiBhcyBhbnkpXG4gICAgICAgIC52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgaG9wUHJlYnVpbGQsIG9yaWdpbmFsUGFyYW1zKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvSG9wIGFtb3VudDogLiogZG9lcyBub3QgZXF1YWwgb3JpZ2luYWwgYW1vdW50Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBFeHBvcnQgaG9wIHByZWJ1aWxkIHdpdGggbWlzbWF0Y2hlZCBkZXN0aW5hdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSk7XG4gICAgICBjb25zdCBob3BQcmVidWlsZCA9IHtcbiAgICAgICAgdHg6IGhvcEV4cG9ydFR4LFxuICAgICAgICBpZDogaG9wRXhwb3J0VHhJZCxcbiAgICAgICAgc2lnbmF0dXJlOiBob3BFeHBvcnRUeEJpdGdvU2lnbmF0dXJlLFxuICAgICAgICBwYXltZW50SWQ6ICcxMjM0NScsXG4gICAgICAgIGdhc1ByaWNlOiAyMDAwMDAwMDAwMCxcbiAgICAgICAgZ2FzTGltaXQ6IDUwMDAwMCxcbiAgICAgICAgYW1vdW50OiA1MDAwMDAwMCxcbiAgICAgICAgcmVjaXBpZW50OiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcyxcbiAgICAgICAgbm9uY2U6IDAsXG4gICAgICAgIHVzZXJSZXFTaWc6ICcweCcsXG4gICAgICAgIGdhc1ByaWNlTWF4OiA1MDAwMDAwMDAwMDAsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnIGFzIGNvbnN0LFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnUC1jb3N0d28xZGlmZmVyZW50flAtY29zdHdvMWFkZHJlc3N+UC1jb3N0d28xaGVyZScsXG4gICAgICAgICAgICBhbW91bnQ6ICc0OTgwMDAwMDAwMDAwMDAwMCcsIC8vIDUwMDAwMDAwIC0gMjAwMDAwICh0eEZlZSkgPSA0OTgwMDAwMCBuYW5vRkxSID0gNDk4MDAwMDAwMDAwMDAwMDAgd2VpXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0ICh0ZmxyQ29pbiBhcyBhbnkpXG4gICAgICAgIC52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgaG9wUHJlYnVpbGQsIG9yaWdpbmFsUGFyYW1zKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvSG9wIGRlc3RpbmF0aW9uOiAuKiBkb2VzIG5vdCBlcXVhbCBvcmlnaW5hbCByZWNpcGllbnQvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ByZXNpZ25UcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBwYXJhbXMgdW5jaGFuZ2VkIHdoZW4gbm8gaG9wVHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4SGV4OiAnMHgxMjMnLFxuICAgICAgICB3YWxsZXQ6IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSksXG4gICAgICAgIGJ1aWxkUGFyYW1zOiB7IHJlY2lwaWVudHM6IFtdIH0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5wcmVzaWduVHJhbnNhY3Rpb24ocGFyYW1zIGFzIGFueSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHBhcmFtcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgdmFsaWRhdGVIb3BQcmVidWlsZCB3aGVuIGhvcFRyYW5zYWN0aW9uIGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgY29uc3QgdmFsaWRhdGVTdHViID0gc2FuZGJveC5zdHViKHRmbHJDb2luIGFzIGFueSwgJ3ZhbGlkYXRlSG9wUHJlYnVpbGQnKS5yZXNvbHZlcygpO1xuXG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wVHJhbnNhY3Rpb24gPSB7XG4gICAgICAgIHR4OiBob3BFeHBvcnRUeCxcbiAgICAgICAgaWQ6IGhvcEV4cG9ydFR4SWQsXG4gICAgICAgIHNpZ25hdHVyZTogaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgcGF5bWVudElkOiAnMTIzNDUnLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGFtb3VudDogNTAwMDAwMDAsXG4gICAgICAgIHJlY2lwaWVudDogRVhQT1JUX0NfVEVTVF9EQVRBLnBNdWx0aXNpZ0FkZHJlc3MsXG4gICAgICAgIG5vbmNlOiAwLFxuICAgICAgICB1c2VyUmVxU2lnOiAnMHgnLFxuICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBjb25zdCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhIZXg6ICcweDEyMycsXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbXSB9LFxuICAgICAgICBob3BUcmFuc2FjdGlvbjogaG9wVHJhbnNhY3Rpb24sXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCB0ZmxyQ29pbi5wcmVzaWduVHJhbnNhY3Rpb24ocGFyYW1zIGFzIGFueSk7XG4gICAgICB2YWxpZGF0ZVN0dWIuY2FsbGVkT25jZS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwb3N0UHJvY2Vzc1ByZWJ1aWxkJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHBhcmFtcyB1bmNoYW5nZWQgd2hlbiBubyBob3BUcmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhIZXg6ICcweDEyMycsXG4gICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLnBvc3RQcm9jZXNzUHJlYnVpbGQocGFyYW1zIGFzIGFueSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHBhcmFtcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgdmFsaWRhdGVIb3BQcmVidWlsZCB3aGVuIGhvcFRyYW5zYWN0aW9uIGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzYW5kYm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgICAgY29uc3QgdmFsaWRhdGVTdHViID0gc2FuZGJveC5zdHViKHRmbHJDb2luIGFzIGFueSwgJ3ZhbGlkYXRlSG9wUHJlYnVpbGQnKS5yZXNvbHZlcygpO1xuXG4gICAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB0ZmxyQ29pbiwge30pO1xuICAgICAgY29uc3QgaG9wVHJhbnNhY3Rpb24gPSB7XG4gICAgICAgIHR4OiBob3BFeHBvcnRUeCxcbiAgICAgICAgaWQ6IGhvcEV4cG9ydFR4SWQsXG4gICAgICAgIHNpZ25hdHVyZTogaG9wRXhwb3J0VHhCaXRnb1NpZ25hdHVyZSxcbiAgICAgICAgcGF5bWVudElkOiAnMTIzNDUnLFxuICAgICAgICBnYXNQcmljZTogMjAwMDAwMDAwMDAsXG4gICAgICAgIGdhc0xpbWl0OiA1MDAwMDAsXG4gICAgICAgIGFtb3VudDogNTAwMDAwMDAsXG4gICAgICAgIHJlY2lwaWVudDogRVhQT1JUX0NfVEVTVF9EQVRBLnBNdWx0aXNpZ0FkZHJlc3MsXG4gICAgICAgIG5vbmNlOiAwLFxuICAgICAgICB1c2VyUmVxU2lnOiAnMHgnLFxuICAgICAgICBnYXNQcmljZU1heDogNTAwMDAwMDAwMDAwLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBjb25zdCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhIZXg6ICcweDEyMycsXG4gICAgICAgIHdhbGxldDogd2FsbGV0LFxuICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBFWFBPUlRfQ19URVNUX0RBVEEucE11bHRpc2lnQWRkcmVzcywgYW1vdW50OiAnMTAwMDAwMDAwJyB9XSB9LFxuICAgICAgICBob3BUcmFuc2FjdGlvbjogaG9wVHJhbnNhY3Rpb24sXG4gICAgICAgIGNvaW46ICd0ZmxyJyxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHRmbHJDb2luLnBvc3RQcm9jZXNzUHJlYnVpbGQocGFyYW1zIGFzIGFueSk7XG4gICAgICB2YWxpZGF0ZVN0dWIuY2FsbGVkT25jZS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRFeHRyYVByZWJ1aWxkUGFyYW1zJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBvYmplY3Qgd2hlbiBob3AgaXMgbm90IHNldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHgxMjM0JywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5nZXRFeHRyYVByZWJ1aWxkUGFyYW1zKGJ1aWxkUGFyYW1zKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZGVlcEVxdWFsKHt9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGVtcHR5IG9iamVjdCB3aGVuIGhvcCBpcyBmYWxzZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICBob3A6IGZhbHNlLFxuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHgxMjM0JywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICAgIHdhbGxldDogbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5kZWVwRXF1YWwoe30pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZW1wdHkgb2JqZWN0IHdoZW4gd2FsbGV0IGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZFBhcmFtcyA9IHtcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiAnMHgxMjM0JywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5nZXRFeHRyYVByZWJ1aWxkUGFyYW1zKGJ1aWxkUGFyYW1zKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZGVlcEVxdWFsKHt9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGVtcHR5IG9iamVjdCB3aGVuIHJlY2lwaWVudHMgaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICBob3A6IHRydWUsXG4gICAgICAgIHdhbGxldDogbmV3IFdhbGxldChiaXRnbywgdGZsckNvaW4sIHt9KSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5kZWVwRXF1YWwoe30pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjYWxsIGNyZWF0ZUhvcFRyYW5zYWN0aW9uUGFyYW1zIHdoZW4gaG9wIGlzIHRydWUgd2l0aCBhbGwgcmVxdWlyZWQgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja0ZlZUVzdGltYXRlID0ge1xuICAgICAgICBmZWVFc3RpbWF0ZTogMTIwMDAwLFxuICAgICAgICBnYXNMaW1pdEVzdGltYXRlOiA1MDAwMDAsXG4gICAgICB9O1xuICAgICAgc2FuZGJveC5zdHViKHRmbHJDb2luLCAnZmVlRXN0aW1hdGUnKS5yZXNvbHZlcyhtb2NrRmVlRXN0aW1hdGUpO1xuXG4gICAgICBjb25zdCBidWlsZFBhcmFtcyA9IHtcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICB3YWxsZXQ6IG5ldyBXYWxsZXQoYml0Z28sIHRmbHJDb2luLCB7fSksXG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IEVYUE9SVF9DX1RFU1RfREFUQS5wTXVsdGlzaWdBZGRyZXNzLCBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnIH1dLFxuICAgICAgICB0eXBlOiAnRXhwb3J0JyBhcyBjb25zdCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRmbHJDb2luLmdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdob3BQYXJhbXMnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2ZlZUVzdGltYXRlJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgbWFrZSBBUEkgY2FsbCB3aXRoIGNvcnJlY3QgcXVlcnkgcGFyYW1ldGVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkRmVlRXN0aW1hdGUgPSB7XG4gICAgICAgIGZlZUVzdGltYXRlOiAxMjAwMDAsXG4gICAgICAgIGdhc0xpbWl0RXN0aW1hdGU6IDUwMDAwMCxcbiAgICAgIH07XG5cbiAgICAgIG5vY2soJ2h0dHBzOi8vYXBwLmJpdGdvLXRlc3QuY29tJylcbiAgICAgICAgLmdldCgnL2FwaS92Mi90ZmxyL3R4L2ZlZScpXG4gICAgICAgIC5xdWVyeSh7XG4gICAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICAgIHJlY2lwaWVudDogJzB4MTIzNCcsXG4gICAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgICAgdHlwZTogJ0V4cG9ydCcsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkRmVlRXN0aW1hdGUpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5mZWVFc3RpbWF0ZSh7XG4gICAgICAgIGhvcDogdHJ1ZSxcbiAgICAgICAgcmVjaXBpZW50OiAnMHgxMjM0JyxcbiAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgIHR5cGU6ICdFeHBvcnQnLFxuICAgICAgfSk7XG5cbiAgICAgIHJlc3VsdC5mZWVFc3RpbWF0ZS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRGZWVFc3RpbWF0ZS5mZWVFc3RpbWF0ZSk7XG4gICAgICByZXN1bHQuZ2FzTGltaXRFc3RpbWF0ZS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRGZWVFc3RpbWF0ZS5nYXNMaW1pdEVzdGltYXRlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbWFrZSBBUEkgY2FsbCB3aXRoIGRhdGEgcGFyYW1ldGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWRGZWVFc3RpbWF0ZSA9IHtcbiAgICAgICAgZmVlRXN0aW1hdGU6IDE1MDAwMCxcbiAgICAgICAgZ2FzTGltaXRFc3RpbWF0ZTogNjAwMDAwLFxuICAgICAgfTtcblxuICAgICAgbm9jaygnaHR0cHM6Ly9hcHAuYml0Z28tdGVzdC5jb20nKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyL3RmbHIvdHgvZmVlJylcbiAgICAgICAgLnF1ZXJ5KHtcbiAgICAgICAgICByZWNpcGllbnQ6ICcweDU2NzgnLFxuICAgICAgICAgIGRhdGE6ICcweGFiY2RlZicsXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIGV4cGVjdGVkRmVlRXN0aW1hdGUpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZmxyQ29pbi5mZWVFc3RpbWF0ZSh7XG4gICAgICAgIHJlY2lwaWVudDogJzB4NTY3OCcsXG4gICAgICAgIGRhdGE6ICcweGFiY2RlZicsXG4gICAgICB9KTtcblxuICAgICAgcmVzdWx0LmZlZUVzdGltYXRlLnNob3VsZC5lcXVhbChleHBlY3RlZEZlZUVzdGltYXRlLmZlZUVzdGltYXRlKTtcbiAgICAgIHJlc3VsdC5nYXNMaW1pdEVzdGltYXRlLnNob3VsZC5lcXVhbChleHBlY3RlZEZlZUVzdGltYXRlLmdhc0xpbWl0RXN0aW1hdGUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZ2V0VHhIYXNoJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY2FsY3VsYXRlIGNvcnJlY3Qga2VjY2FrMjU2IGhhc2ggZm9yIHR4IGhleCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gRVhQT1JUX0NfVEVTVF9EQVRBLmZ1bGxzaWdudHhIZXg7XG4gICAgICBjb25zdCBoYXNoID0gKHRmbHJDb2luLmNvbnN0cnVjdG9yIGFzIHR5cGVvZiBGbHIpLmdldFR4SGFzaCh0eEhleCk7XG5cbiAgICAgIGhhc2guc2hvdWxkLmJlLmluc3RhbmNlT2YoQnVmZmVyKTtcbiAgICAgIGhhc2gubGVuZ3RoLnNob3VsZC5lcXVhbCgzMik7XG5cbiAgICAgIC8vIFZlcmlmeSBpdCBtYXRjaGVzIG91ciBoZWxwZXIgZnVuY3Rpb25cbiAgICAgIGNvbnN0IGV4cGVjdGVkSGFzaCA9IGdldFR4SGFzaCh0eEhleCk7XG4gICAgICBoYXNoLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRIYXNoLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGhhbmRsZSB0eCBoZXggd2l0aCAweCBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9ICcweCcgKyAnYWJjZCcucmVwZWF0KDEwKTtcbiAgICAgIGNvbnN0IGhhc2ggPSAodGZsckNvaW4uY29uc3RydWN0b3IgYXMgdHlwZW9mIEZscikuZ2V0VHhIYXNoKHR4SGV4KTtcblxuICAgICAgaGFzaC5zaG91bGQuYmUuaW5zdGFuY2VPZihCdWZmZXIpO1xuICAgICAgaGFzaC5sZW5ndGguc2hvdWxkLmVxdWFsKDMyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIHR4IGhleCB3aXRob3V0IDB4IHByZWZpeCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gJ2FiY2QnLnJlcGVhdCgxMCk7XG4gICAgICBjb25zdCBoYXNoID0gKHRmbHJDb2luLmNvbnN0cnVjdG9yIGFzIHR5cGVvZiBGbHIpLmdldFR4SGFzaCh0eEhleCk7XG5cbiAgICAgIGhhc2guc2hvdWxkLmJlLmluc3RhbmNlT2YoQnVmZmVyKTtcbiAgICAgIGhhc2gubGVuZ3RoLnNob3VsZC5lcXVhbCgzMik7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdCdWlsZCBVbnNpZ25lZCBTd2VlcCBmb3IgU2VsZi1DdXN0b2R5IENvbGQgV2FsbGV0cyAtIChNUEN2MiknLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICBjb25zdCBleHBsb3JlclVybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLmZsckV4cGxvcmVyQmFzZVVybCBhcyBzdHJpbmc7XG4gIGNvbnN0IG1heEZlZVBlckdhc3ZhbHVlID0gMzAwMDAwMDAwMDA7XG4gIGNvbnN0IG1heFByaW9yaXR5RmVlUGVyR2FzVmFsdWUgPSAxNTAwMDAwMDAwMDtcbiAgY29uc3QgY2hhaW5faWQgPSAxMTQ7XG4gIGNvbnN0IGdhc0xpbWl0dmFsdWUgPSA1MDAwMDA7XG5cbiAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBhbiB1bnNpZ25lZCBzd2VlcCB3aXRob3V0IGRlcml2YXRpb24gcGF0aCcsIGFzeW5jICgpID0+IHtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAudHdpY2UoKVxuICAgICAgLnF1ZXJ5KG1vY2tEYXRhVW5zaWduZWRTd2VlcC5nZXRUeExpc3RSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFVbnNpZ25lZFN3ZWVwLmdldFR4TGlzdFJlc3BvbnNlKTtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAucXVlcnkobW9ja0RhdGFVbnNpZ25lZFN3ZWVwLmdldEJhbGFuY2VSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFVbnNpZ25lZFN3ZWVwLmdldEJhbGFuY2VSZXNwb25zZSk7XG5cbiAgICBjb25zdCBiYXNlQ29pbjogYW55ID0gYml0Z28uY29pbigndGZscicpO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGJhc2VDb2luLnJlY292ZXIoe1xuICAgICAgdXNlcktleTogbW9ja0RhdGFVbnNpZ25lZFN3ZWVwLnVzZXJLZXksXG4gICAgICBiYWNrdXBLZXk6IG1vY2tEYXRhVW5zaWduZWRTd2VlcC5iYWNrdXBLZXksXG4gICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IG1vY2tEYXRhVW5zaWduZWRTd2VlcC53YWxsZXRCYXNlQWRkcmVzcyxcbiAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IG1vY2tEYXRhVW5zaWduZWRTd2VlcC5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgaXNUc3M6IHRydWUsXG4gICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogbWF4RmVlUGVyR2FzdmFsdWUsIG1heFByaW9yaXR5RmVlUGVyR2FzOiBtYXhQcmlvcml0eUZlZVBlckdhc1ZhbHVlIH0sXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXR2YWx1ZSxcbiAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgIGNoYWluOiBjaGFpbl9pZCxcbiAgICAgICAgaGFyZGZvcms6ICdsb25kb24nLFxuICAgICAgfSxcbiAgICB9KSkgYXMgVW5zaWduZWRTd2VlcFR4TVBDdjI7XG4gICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uKTtcbiAgICB0cmFuc2FjdGlvbi5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHhSZXF1ZXN0cycpO1xuICAgIHRyYW5zYWN0aW9uLnR4UmVxdWVzdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICBjb25zdCB0eFJlcXVlc3QgPSB0cmFuc2FjdGlvbi50eFJlcXVlc3RzWzBdO1xuICAgIHR4UmVxdWVzdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnd2FsbGV0Q29pbicpO1xuICAgIHR4UmVxdWVzdC53YWxsZXRDb2luLnNob3VsZC5lcXVhbCgndGZscicpO1xuICAgIHR4UmVxdWVzdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHJhbnNhY3Rpb25zJyk7XG4gICAgdHhSZXF1ZXN0LnRyYW5zYWN0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgIGNvbnN0IHR4ID0gdHhSZXF1ZXN0LnRyYW5zYWN0aW9uc1swXTtcbiAgICB0eC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnbm9uY2UnKTtcbiAgICB0eC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndW5zaWduZWRUeCcpO1xuICAgIHR4LnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NlcmlhbGl6ZWRUeEhleCcpO1xuICAgIHR4LnVuc2lnbmVkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hYmxlSGV4Jyk7XG4gICAgdHgudW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZGVyaXZhdGlvblBhdGgnKTtcbiAgICB0eC51bnNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdmZWVJbmZvJyk7XG4gICAgdHgudW5zaWduZWRUeC5mZWVJbmZvPy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlJyk7XG4gICAgdHgudW5zaWduZWRUeC5mZWVJbmZvPy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZmVlU3RyaW5nJyk7XG4gICAgdHgudW5zaWduZWRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncGFyc2VkVHgnKTtcbiAgICB0eC51bnNpZ25lZFR4LnBhcnNlZFR4Py5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3BlbmRBbW91bnQnKTtcbiAgICB0eC51bnNpZ25lZFR4LnBhcnNlZFR4Py5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnb3V0cHV0cycpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnTm9uIEJpdGdvIFJlY292ZXJ5IGZvciBIb3QgV2FsbGV0cycsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gIGNvbnN0IGV4cGxvcmVyVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0uZmxyRXhwbG9yZXJCYXNlVXJsIGFzIHN0cmluZztcbiAgY29uc3QgbWF4RmVlUGVyR2FzdmFsdWUgPSAzMDAwMDAwMDAwMDtcbiAgY29uc3QgbWF4UHJpb3JpdHlGZWVQZXJHYXNWYWx1ZSA9IDE1MDAwMDAwMDAwO1xuICBjb25zdCBjaGFpbl9pZCA9IDExNDtcbiAgY29uc3QgZ2FzTGltaXR2YWx1ZSA9IDUwMDAwMDtcblxuICBpdCgnc2hvdWxkIGdlbmVyYXRlIGEgc2lnbmVkIG5vbi1iaXRnbyByZWNvdmVyeSB0eCcsIGFzeW5jICgpID0+IHtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAudHdpY2UoKVxuICAgICAgLnF1ZXJ5KG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5nZXRUeExpc3RSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LmdldFR4TGlzdFJlc3BvbnNlKTtcbiAgICBub2NrKGV4cGxvcmVyVXJsKVxuICAgICAgLmdldCgnL2FwaScpXG4gICAgICAucXVlcnkobW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LmdldEJhbGFuY2VSZXF1ZXN0KVxuICAgICAgLnJlcGx5KDIwMCwgbW9ja0RhdGFOb25CaXRHb1JlY292ZXJ5LmdldEJhbGFuY2VSZXNwb25zZSk7XG5cbiAgICBjb25zdCBiYXNlQ29pbjogYW55ID0gYml0Z28uY29pbigndGZscicpO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZUNvaW4ucmVjb3Zlcih7XG4gICAgICB1c2VyS2V5OiBtb2NrRGF0YU5vbkJpdEdvUmVjb3ZlcnkudXNlcktleURhdGEsXG4gICAgICBiYWNrdXBLZXk6IG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5iYWNrdXBLZXlEYXRhLFxuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBtb2NrRGF0YU5vbkJpdEdvUmVjb3Zlcnkud2FsbGV0Um9vdEFkZHJlc3MsXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlOiBtb2NrRGF0YU5vbkJpdEdvUmVjb3Zlcnkud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgaXNUc3M6IHRydWUsXG4gICAgICBlaXAxNTU5OiB7IG1heEZlZVBlckdhczogbWF4RmVlUGVyR2FzdmFsdWUsIG1heFByaW9yaXR5RmVlUGVyR2FzOiBtYXhQcmlvcml0eUZlZVBlckdhc1ZhbHVlIH0sXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXR2YWx1ZSxcbiAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiB7XG4gICAgICAgIGNoYWluOiBjaGFpbl9pZCxcbiAgICAgICAgaGFyZGZvcms6ICdsb25kb24nLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24pO1xuICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcpO1xuICAgIHRyYW5zYWN0aW9uLnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgIGNvbnN0IHR4ID0gRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21TZXJpYWxpemVkVHgoQnVmZmVyLmZyb20oc3RyaXBIZXhQcmVmaXgodHJhbnNhY3Rpb24udHgpLCAnaGV4JykpO1xuICAgIHR4LmdldFNlbmRlckFkZHJlc3MoKS50b1N0cmluZygpLnNob3VsZC5lcXVhbChtb2NrRGF0YU5vbkJpdEdvUmVjb3Zlcnkud2FsbGV0Um9vdEFkZHJlc3MpO1xuICAgIGNvbnN0IGpzb25UeCA9IHR4LnRvSlNPTigpO1xuICAgIGpzb25UeC50bz8uc2hvdWxkLmVxdWFsKG1vY2tEYXRhTm9uQml0R29SZWNvdmVyeS5yZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgfSk7XG59KTtcbiJdfQ==