@bitgo-beta/sdk-api 1.10.1-beta.185 → 1.10.1-beta.1850

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 (79) hide show
  1. package/dist/package.json +20 -27
  2. package/dist/src/api.d.ts +8 -5
  3. package/dist/src/api.d.ts.map +1 -1
  4. package/dist/src/api.js +130 -71
  5. package/dist/src/bitgoAPI.d.ts +133 -16
  6. package/dist/src/bitgoAPI.d.ts.map +1 -1
  7. package/dist/src/bitgoAPI.js +796 -306
  8. package/dist/src/encrypt.d.ts +23 -4
  9. package/dist/src/encrypt.d.ts.map +1 -1
  10. package/dist/src/encrypt.js +86 -13
  11. package/dist/src/encryptV2.d.ts +68 -0
  12. package/dist/src/encryptV2.d.ts.map +1 -0
  13. package/dist/src/encryptV2.js +202 -0
  14. package/dist/src/encryptionSession.d.ts +34 -0
  15. package/dist/src/encryptionSession.d.ts.map +1 -0
  16. package/dist/src/encryptionSession.js +95 -0
  17. package/dist/src/index.d.ts +2 -0
  18. package/dist/src/index.d.ts.map +1 -1
  19. package/dist/src/index.js +8 -2
  20. package/dist/src/types.d.ts +64 -44
  21. package/dist/src/types.d.ts.map +1 -1
  22. package/dist/src/types.js +4 -2
  23. package/dist/src/util.d.ts +12 -0
  24. package/dist/src/util.d.ts.map +1 -1
  25. package/dist/src/util.js +57 -4
  26. package/dist/src/v1/blockchain.js +25 -12
  27. package/dist/src/v1/keychains.js +39 -26
  28. package/dist/src/v1/markets.js +10 -5
  29. package/dist/src/v1/pendingapproval.d.ts.map +1 -1
  30. package/dist/src/v1/pendingapproval.js +57 -18
  31. package/dist/src/v1/pendingapprovals.d.ts.map +1 -1
  32. package/dist/src/v1/pendingapprovals.js +41 -7
  33. package/dist/src/v1/signPsbt.d.ts +14 -0
  34. package/dist/src/v1/signPsbt.d.ts.map +1 -0
  35. package/dist/src/v1/signPsbt.js +69 -0
  36. package/dist/src/v1/transactionBuilder.js +221 -91
  37. package/dist/src/v1/travelRule.js +163 -66
  38. package/dist/src/v1/verifyAddress.d.ts +6 -0
  39. package/dist/src/v1/verifyAddress.d.ts.map +1 -0
  40. package/dist/src/v1/verifyAddress.js +50 -0
  41. package/dist/src/v1/wallet.d.ts.map +1 -1
  42. package/dist/src/v1/wallet.js +501 -230
  43. package/dist/src/v1/wallets.js +118 -53
  44. package/dist/test/unit/api.d.ts +2 -0
  45. package/dist/test/unit/api.d.ts.map +1 -0
  46. package/dist/test/unit/api.js +307 -0
  47. package/dist/test/unit/bitgoAPI.d.ts +2 -0
  48. package/dist/test/unit/bitgoAPI.d.ts.map +1 -0
  49. package/dist/test/unit/bitgoAPI.js +1027 -0
  50. package/dist/test/unit/encrypt.d.ts +2 -0
  51. package/dist/test/unit/encrypt.d.ts.map +1 -0
  52. package/dist/test/unit/encrypt.js +415 -0
  53. package/dist/test/unit/hmacStrategy.d.ts +2 -0
  54. package/dist/test/unit/hmacStrategy.d.ts.map +1 -0
  55. package/dist/test/unit/hmacStrategy.js +136 -0
  56. package/dist/test/unit/utils.d.ts +2 -0
  57. package/dist/test/unit/utils.d.ts.map +1 -0
  58. package/dist/test/unit/utils.js +65 -0
  59. package/dist/test/unit/v1/fixtures/accelerate-tx.d.ts +4 -0
  60. package/dist/test/unit/v1/fixtures/accelerate-tx.d.ts.map +1 -0
  61. package/dist/test/unit/v1/fixtures/accelerate-tx.js +53 -0
  62. package/dist/test/unit/v1/fixtures/index.d.ts +3 -0
  63. package/dist/test/unit/v1/fixtures/index.d.ts.map +1 -0
  64. package/dist/test/unit/v1/fixtures/index.js +24 -0
  65. package/dist/test/unit/v1/signPsbt.d.ts +2 -0
  66. package/dist/test/unit/v1/signPsbt.d.ts.map +1 -0
  67. package/dist/test/unit/v1/signPsbt.js +53 -0
  68. package/dist/test/unit/v1/travelRule.d.ts +2 -0
  69. package/dist/test/unit/v1/travelRule.d.ts.map +1 -0
  70. package/dist/test/unit/v1/travelRule.js +173 -0
  71. package/dist/test/unit/v1/wallet.d.ts +2 -0
  72. package/dist/test/unit/v1/wallet.d.ts.map +1 -0
  73. package/dist/test/unit/v1/wallet.js +1658 -0
  74. package/dist/tsconfig.tsbuildinfo +1 -0
  75. package/package.json +20 -27
  76. package/.eslintignore +0 -5
  77. package/CHANGELOG.md +0 -571
  78. package/dist/web/main.js +0 -2
  79. package/dist/web/main.js.LICENSE.txt +0 -110
@@ -0,0 +1,1658 @@
1
+ "use strict";
2
+ //
3
+ // Tests for Wallet
4
+ //
5
+ // Copyright 2014, BitGo, Inc. All Rights Reserved.
6
+ //
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ const fixtures_1 = require("./fixtures");
45
+ const Wallet = require('../../../src/v1/wallet');
46
+ const bitgoAPI_1 = require("../../../src/bitgoAPI");
47
+ const _ = __importStar(require("lodash"));
48
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
49
+ const utxolib = __importStar(require("@bitgo-beta/utxo-lib"));
50
+ const should = __importStar(require("should"));
51
+ const nock_1 = __importDefault(require("nock"));
52
+ const sinon = __importStar(require("sinon"));
53
+ const accelerate_tx_1 = require("./fixtures/accelerate-tx");
54
+ nock_1.default.disableNetConnect();
55
+ const TestBitGo = {
56
+ TEST_WALLET1_PASSCODE: 'iVWeATjqLS1jJShrPpETti0b',
57
+ };
58
+ describe('Wallet Prototype Methods', function () {
59
+ const fixtures = (0, accelerate_tx_1.getFixtures)();
60
+ let bitgo = new bitgoAPI_1.BitGoAPI({ env: 'test', clientConstants: { constants: {} } });
61
+ // bitgo.initializeTestVars();
62
+ const userKeypair = {
63
+ xprv: 'xprv9s21ZrQH143K2fJ91S4BRsupcYrE6mmY96fcX5HkhoTrrwmwjd16Cn87cWinJjByrfpojjx7ezsJLx7TAKLT8m8hM5Kax9YcoxnBeJZ3t2k',
64
+ xpub: 'xpub661MyMwAqRbcF9Nc7TbBo1rZAagiWEVPWKbDKThNG8zqjk76HAKLkaSbTn6dK2dQPfuD7xjicxCZVWvj67fP5nQ9W7QURmoMVAX8m6jZsGp',
65
+ rawPub: '02c103ac74481874b5ef0f385d12725e4f14aedc9e00bc814ce96f47f62ce7adf2',
66
+ rawPrv: '936c5af3f8af81f75cdad1b08f29e7d9c01e598e2db2d7be18b9e5a8646e87c6',
67
+ path: 'm',
68
+ walletSubPath: '/0/0',
69
+ };
70
+ const backupKeypair = {
71
+ xprv: 'xprv9s21ZrQH143K47sEkLkykgYmq1xF5ZWrPYhUZcmBpPFMQojvGUmEcr5jFXYGfr8CpFdpTvhQ7L9NN2rLtsBFjSix3BAjwJcBj6U3D5hxTPc',
72
+ xpub: 'xpub661MyMwAqRbcGbwhrNHz7pVWP3njV2Ehkmd5N1AoNinLHc54p25VAeQD6q2oTS3uuDMDnfnXnthbS9ufC8JVYpNnWU5Rn3pYaNuLCNywkw1',
73
+ rawPub: '03bbcb73997977068d9e36666bbd5cd37579acae8e2bd5ce9d0a6e5c150a423bc3',
74
+ rawPrv: '77a15f14796f4001d1092ae84f766bd869e9bee6bffae6547def5045b96fa943',
75
+ path: 'm',
76
+ walletSubPath: '/0/0',
77
+ };
78
+ const bitgoKey = {
79
+ xpub: 'xpub661MyMwAqRbcGQcVFiwcrtc7c3vopsX96jsJUYPcFMREcRTqAqsqbv2ZRyCJAPLm5NMHCy85E3ZwpT4EAUw9WGU7vMhG6z83hDeKXBWn6Lf',
80
+ path: 'm',
81
+ walletSubPath: '/0/0',
82
+ };
83
+ const fakeWallet = new Wallet(bitgo, {
84
+ id: '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4',
85
+ private: { keychains: [userKeypair, backupKeypair, bitgoKey] },
86
+ });
87
+ describe('Generate Address', function () {
88
+ before(() => nock_1.default.pendingMocks().should.be.empty());
89
+ it('generate first address', function () {
90
+ const idAddress = fakeWallet.generateAddress({ path: '/0/0', segwit: false });
91
+ idAddress.address.should.equal(fakeWallet.id());
92
+ idAddress.chain.should.equal(0);
93
+ idAddress.index.should.equal(0);
94
+ idAddress.chainPath.should.equal('/0/0');
95
+ idAddress.path.should.equal('/0/0');
96
+ idAddress.outputScript.should.equal('a914d682476e9bd54454a885f9dff1e604e99cef43dc87');
97
+ idAddress.redeemScript.should.equal('522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae');
98
+ idAddress.wallet.should.equal(fakeWallet.id());
99
+ });
100
+ it('generate second address', function () {
101
+ const p2shAddress = fakeWallet.generateAddress({ path: '/0/1', segwit: false });
102
+ p2shAddress.address.should.equal('2N5y5RLVqdZi7qp5PmzMdPR6YvQzUqBQFWK');
103
+ p2shAddress.chain.should.equal(0);
104
+ p2shAddress.index.should.equal(1);
105
+ p2shAddress.chainPath.should.equal('/0/1');
106
+ p2shAddress.path.should.equal('/0/1');
107
+ p2shAddress.outputScript.should.equal('a9148b8bd3da68ef0f2465523146bd2de33c86b9c87187');
108
+ p2shAddress.redeemScript.should.equal('522102709edb6a2198d364c485a76b981d12065eabde8aa2d85bd7e7a035f7ecb3579b2102a724efed499c05fdb4da1e139700951fae00c006b3283888bdfd1b46979292242102b32abe44d61986ff57b835e3bd16293d93f303d0d8fb0454e2c9cceda5c4929853ae');
109
+ p2shAddress.wallet.should.equal(fakeWallet.id());
110
+ });
111
+ it('generate change address', function () {
112
+ const p2shAddress = fakeWallet.generateAddress({ path: '/1/0', segwit: false });
113
+ p2shAddress.address.should.equal('2NFj9JrpZc5MyYnCouyREtzNY4eoyKWDfgP');
114
+ p2shAddress.chain.should.equal(1);
115
+ p2shAddress.index.should.equal(0);
116
+ p2shAddress.chainPath.should.equal('/1/0');
117
+ p2shAddress.path.should.equal('/1/0');
118
+ p2shAddress.outputScript.should.equal('a914f69a81fad75ea65ad166da76515291679a4f1ad887');
119
+ p2shAddress.redeemScript.should.equal('5221020b4c4f891a5520f5a0b6818d8d53919552a0d4d806b5fa05c97708079d83737e2102c5cc49bf0331eb0b0890a7e7d87f7e9e0dea515438280dc76834c21d198efe08210370e52cf741ebf4513749d028839d696891eb789ba7a58592cfbc857cdc0a9de753ae');
120
+ p2shAddress.wallet.should.equal(fakeWallet.id());
121
+ });
122
+ it('generate segwit address', function () {
123
+ const segwitAddress = fakeWallet.generateAddress({ path: '/10/0', segwit: true });
124
+ segwitAddress.address.should.equal('2N5EVegRPWnmed2PpqDggZPw7DcNDguRYv8');
125
+ segwitAddress.chain.should.equal(10);
126
+ segwitAddress.index.should.equal(0);
127
+ segwitAddress.chainPath.should.equal('/10/0');
128
+ segwitAddress.path.should.equal('/10/0');
129
+ segwitAddress.outputScript.should.equal('a914837e2adcb6f6386fea3c5d40316b282ccf39121d87');
130
+ segwitAddress.redeemScript.should.equal('0020a62afee1d211c5adb9739f81ed4e36330e6cda651c7bdd314e32ccc465ec2203');
131
+ segwitAddress.witnessScript.should.equal('5221027b30505777a4ed8947b069fcb0116e287995d97278d84da4db6c613270649d3d21034c30e51f1e614cad667815c91d041404c18225d0b2f79e2c0bcb63fd2604316b2103b65ddfc06159b691693390761e75a0b8cc7a65b6ff305d094f3ad972f17953fe53ae');
132
+ segwitAddress.wallet.should.equal(fakeWallet.id());
133
+ });
134
+ });
135
+ describe('Create Transaction', function () {
136
+ let bgUrl, bgUrlTest;
137
+ let fakeProdWallet;
138
+ before(function () {
139
+ nock_1.default.pendingMocks().should.be.empty();
140
+ const prodBitgo = new bitgoAPI_1.BitGoAPI({ env: 'prod', clientConstants: { constants: {} } });
141
+ // prodBitgo.initializeTestVars();
142
+ bgUrl = sdk_core_1.common.Environments[prodBitgo.getEnv()].uri;
143
+ fakeProdWallet = new Wallet(prodBitgo, {
144
+ id: '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4',
145
+ private: { keychains: [userKeypair, backupKeypair, bitgoKey] },
146
+ });
147
+ bgUrlTest = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
148
+ });
149
+ it('extra unspent fetch params', async function () {
150
+ const billingAddress = '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy';
151
+ const customUnspentsFetchParams = { test: 123 };
152
+ const sendAmount = 1e5;
153
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: billingAddress });
154
+ const scope = (0, nock_1.default)(bgUrl)
155
+ .get(`/api/v1/wallet/${fakeProdWallet.id()}/unspents`)
156
+ .query(_.merge(customUnspentsFetchParams, {
157
+ segwit: true,
158
+ target: sendAmount,
159
+ minSize: 0,
160
+ }))
161
+ .reply(200, { unspents: [] });
162
+ await fakeProdWallet
163
+ .createTransaction({
164
+ unspentsFetchParams: customUnspentsFetchParams,
165
+ recipients: { [billingAddress]: sendAmount },
166
+ feeRate: 10000,
167
+ bitgoFee: {
168
+ amount: 0,
169
+ address: '',
170
+ },
171
+ })
172
+ .should.be.rejectedWith('0 unspents available for transaction creation');
173
+ scope.isDone().should.be.true();
174
+ });
175
+ it('default p2sh', async function () {
176
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
177
+ const unspent = {
178
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
179
+ value: '0.00504422',
180
+ value_int: 504422,
181
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
182
+ n: 1,
183
+ script_pub_key: {
184
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
185
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
186
+ },
187
+ req_sigs: 1,
188
+ type: 'scripthash',
189
+ confirmations: 9,
190
+ id: 61330229,
191
+ };
192
+ _.extend(unspent, p2shAddress);
193
+ unspent.value = unspent.value_int;
194
+ unspent.tx_hash = unspent.txid;
195
+ unspent.tx_output_n = unspent.n;
196
+ unspent.script = unspent.outputScript;
197
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
198
+ const transaction = (await fakeProdWallet.createTransaction({
199
+ changeAddress: p2shAddress.address,
200
+ unspents: [unspent],
201
+ recipients: {},
202
+ noSplitChange: true,
203
+ forceChangeAtEnd: true,
204
+ feeRate: 10000,
205
+ bitgoFee: {
206
+ amount: 0,
207
+ address: '',
208
+ },
209
+ opReturns: { 'BitGo p2sh test': 1000 },
210
+ usePsbt: false,
211
+ }));
212
+ transaction.transactionHex.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b80100000000ffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
213
+ // add first signature
214
+ transaction.keychain = userKeypair;
215
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
216
+ signature1.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000b600473044022021fa73d5fe61ac8942cd70ff4507c574677ce747de5bc46c3dd2e38ec2448fce022047906d2c0154337ab96041e8fb58c243b9bce5f8818fa991643c1260a1859ad80100004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
217
+ // add second signature
218
+ transaction.transactionHex = signature1.tx;
219
+ transaction.keychain = backupKeypair;
220
+ transaction.fullLocalSigning = true;
221
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
222
+ // This transaction has actually worked: https://testnet.smartbit.com.au/tx/a8ccb928169032d6e1f37bf81dfd9ab6d90362a4f84e577397fa690aa711550c
223
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
224
+ // changed, changing the output amounts and thus the tx hex.
225
+ signature2.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000fdfd0000473044022021fa73d5fe61ac8942cd70ff4507c574677ce747de5bc46c3dd2e38ec2448fce022047906d2c0154337ab96041e8fb58c243b9bce5f8818fa991643c1260a1859ad80147304402202ae01f01b5ae0c3fa7d67ac73db81932cb5aca10db16a99063fef45e3f1398cd022055001ba7e163cb350910fc7321ecd7eb6359b321d4c04887484d9c7284b78c4701004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
226
+ });
227
+ it('p2sh PSBT produces same unsigned tx as legacy', async function () {
228
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
229
+ const unspent = {
230
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
231
+ value: '0.00504422',
232
+ value_int: 504422,
233
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
234
+ n: 1,
235
+ script_pub_key: {
236
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
237
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
238
+ },
239
+ req_sigs: 1,
240
+ type: 'scripthash',
241
+ confirmations: 9,
242
+ id: 61330229,
243
+ };
244
+ _.extend(unspent, p2shAddress);
245
+ unspent.value = unspent.value_int;
246
+ unspent.tx_hash = unspent.txid;
247
+ unspent.tx_output_n = unspent.n;
248
+ unspent.script = unspent.outputScript;
249
+ const txParams = {
250
+ changeAddress: p2shAddress.address,
251
+ unspents: [unspent],
252
+ recipients: {},
253
+ noSplitChange: true,
254
+ forceChangeAtEnd: true,
255
+ feeRate: 10000,
256
+ bitgoFee: {
257
+ amount: 0,
258
+ address: '',
259
+ },
260
+ opReturns: { 'BitGo p2sh test': 1000 },
261
+ };
262
+ // Create legacy transaction
263
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
264
+ const legacyTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: false }));
265
+ // Create PSBT transaction (explicitly)
266
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
267
+ const psbtTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: true }));
268
+ // Extract unsigned tx from PSBT and compare
269
+ const psbt = utxolib.bitgo.createPsbtFromHex(psbtTx.transactionHex, utxolib.networks.bitcoin);
270
+ const unsignedTxFromPsbt = psbt.getUnsignedTx().toHex();
271
+ // The unsigned transaction hex should be identical
272
+ legacyTx.transactionHex.should.equal(unsignedTxFromPsbt);
273
+ // Fees should also match
274
+ legacyTx.fee.should.equal(psbtTx.fee);
275
+ // Clean up nock mocks to avoid interference with other tests
276
+ nock_1.default.cleanAll();
277
+ });
278
+ it('segwit PSBT produces same unsigned tx as legacy', async function () {
279
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
280
+ const unspent = {
281
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
282
+ value: '0.18750000',
283
+ value_int: 18750000,
284
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
285
+ n: 0,
286
+ script_pub_key: {
287
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
288
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
289
+ },
290
+ req_sigs: 1,
291
+ type: 'scripthash',
292
+ confirmations: 0,
293
+ id: 61331617,
294
+ };
295
+ _.extend(unspent, segwitAddress);
296
+ unspent.value = unspent.value_int;
297
+ unspent.tx_hash = unspent.txid;
298
+ unspent.tx_output_n = unspent.n;
299
+ unspent.script = unspent.outputScript;
300
+ const txParams = {
301
+ changeAddress: segwitAddress.address,
302
+ unspents: [unspent],
303
+ recipients: {},
304
+ noSplitChange: true,
305
+ forceChangeAtEnd: true,
306
+ feeRate: 10000,
307
+ bitgoFee: {
308
+ amount: 0,
309
+ address: '',
310
+ },
311
+ opReturns: { 'BitGo segwit test': 1000 },
312
+ };
313
+ // Create legacy transaction
314
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
315
+ const legacyTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: false }));
316
+ // Create PSBT transaction (explicitly)
317
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
318
+ const psbtTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: true }));
319
+ // Extract unsigned tx from PSBT and compare
320
+ const psbt = utxolib.bitgo.createPsbtFromHex(psbtTx.transactionHex, utxolib.networks.bitcoin);
321
+ const unsignedTxFromPsbt = psbt.getUnsignedTx().toHex();
322
+ // The unsigned transaction hex should be identical
323
+ legacyTx.transactionHex.should.equal(unsignedTxFromPsbt);
324
+ // Fees should also match
325
+ legacyTx.fee.should.equal(psbtTx.fee);
326
+ // Clean up nock mocks to avoid interference with other tests
327
+ nock_1.default.cleanAll();
328
+ });
329
+ it('p2sh with PSBT format', async function () {
330
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
331
+ const unspent = {
332
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
333
+ value: '0.00504422',
334
+ value_int: 504422,
335
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
336
+ n: 1,
337
+ script_pub_key: {
338
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
339
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
340
+ },
341
+ req_sigs: 1,
342
+ type: 'scripthash',
343
+ confirmations: 9,
344
+ id: 61330229,
345
+ };
346
+ _.extend(unspent, p2shAddress);
347
+ unspent.value = unspent.value_int;
348
+ unspent.tx_hash = unspent.txid;
349
+ unspent.tx_output_n = unspent.n;
350
+ unspent.script = unspent.outputScript;
351
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
352
+ const transaction = (await fakeProdWallet.createTransaction({
353
+ changeAddress: p2shAddress.address,
354
+ unspents: [unspent],
355
+ recipients: {},
356
+ noSplitChange: true,
357
+ forceChangeAtEnd: true,
358
+ feeRate: 10000,
359
+ bitgoFee: {
360
+ amount: 0,
361
+ address: '',
362
+ },
363
+ opReturns: { 'BitGo p2sh test': 1000 },
364
+ usePsbt: true, // Explicitly request PSBT format
365
+ }));
366
+ // Verify PSBT format is returned in transactionHex
367
+ should.exist(transaction.transactionHex);
368
+ should.ok(utxolib.bitgo.isPsbt(transaction.transactionHex));
369
+ should.not.exist(transaction.unspents);
370
+ // Parse and validate the PSBT
371
+ const psbt = utxolib.bitgo.createPsbtFromHex(transaction.transactionHex, utxolib.networks.bitcoin);
372
+ psbt.data.inputs.length.should.equal(1);
373
+ psbt.data.outputs.length.should.equal(2); // OP_RETURN + change
374
+ // Verify input has required PSBT metadata
375
+ const input = psbt.data.inputs[0];
376
+ should.exist(input.witnessUtxo);
377
+ should.exist(input.redeemScript);
378
+ should.exist(input.bip32Derivation);
379
+ input.bip32Derivation.length.should.equal(3); // user, backup, bitgo
380
+ // Verify globalXpubs are set
381
+ should.exist(psbt.data.globalMap.globalXpub);
382
+ psbt.data.globalMap.globalXpub.length.should.equal(3);
383
+ // Sign with user key - auto-detects PSBT in transactionHex
384
+ const signedResult = (await fakeProdWallet.signTransaction({
385
+ transactionHex: transaction.transactionHex,
386
+ keychain: userKeypair,
387
+ }));
388
+ should.exist(signedResult.tx);
389
+ // Parse signed PSBT and verify signature
390
+ const signedPsbt = utxolib.bitgo.createPsbtFromHex(signedResult.tx, utxolib.networks.bitcoin);
391
+ should.ok(signedPsbt.validateSignaturesOfInputHD(0, utxolib.bip32.fromBase58(userKeypair.xpub)));
392
+ });
393
+ it('segwit with PSBT format', async function () {
394
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
395
+ const unspent = {
396
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
397
+ value: '0.18750000',
398
+ value_int: 18750000,
399
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
400
+ n: 0,
401
+ script_pub_key: {
402
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
403
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
404
+ },
405
+ req_sigs: 1,
406
+ type: 'scripthash',
407
+ confirmations: 0,
408
+ id: 61331617,
409
+ };
410
+ _.extend(unspent, segwitAddress);
411
+ unspent.value = unspent.value_int;
412
+ unspent.tx_hash = unspent.txid;
413
+ unspent.tx_output_n = unspent.n;
414
+ unspent.script = unspent.outputScript;
415
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
416
+ const transaction = (await fakeProdWallet.createTransaction({
417
+ changeAddress: segwitAddress.address,
418
+ unspents: [unspent],
419
+ recipients: {},
420
+ noSplitChange: true,
421
+ forceChangeAtEnd: true,
422
+ feeRate: 10000,
423
+ bitgoFee: {
424
+ amount: 0,
425
+ address: '',
426
+ },
427
+ opReturns: { 'BitGo segwit test': 1000 },
428
+ usePsbt: true, // Explicitly request PSBT format
429
+ }));
430
+ // Verify PSBT format is returned in transactionHex
431
+ should.exist(transaction.transactionHex);
432
+ should.ok(utxolib.bitgo.isPsbt(transaction.transactionHex));
433
+ // Parse and validate the PSBT
434
+ const psbt = utxolib.bitgo.createPsbtFromHex(transaction.transactionHex, utxolib.networks.bitcoin);
435
+ psbt.data.inputs.length.should.equal(1);
436
+ // Verify input has segwit PSBT metadata
437
+ const input = psbt.data.inputs[0];
438
+ should.exist(input.witnessUtxo);
439
+ should.exist(input.witnessScript);
440
+ should.exist(input.redeemScript);
441
+ should.exist(input.bip32Derivation);
442
+ // Sign with user key - auto-detects PSBT in transactionHex
443
+ const signedResult = (await fakeProdWallet.signTransaction({
444
+ transactionHex: transaction.transactionHex,
445
+ keychain: userKeypair,
446
+ }));
447
+ should.exist(signedResult.tx);
448
+ // Parse signed PSBT and verify signature
449
+ const signedPsbt = utxolib.bitgo.createPsbtFromHex(signedResult.tx, utxolib.networks.bitcoin);
450
+ should.ok(signedPsbt.validateSignaturesOfInputHD(0, utxolib.bip32.fromBase58(userKeypair.xpub)));
451
+ });
452
+ it('BCH p2sh', async function () {
453
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
454
+ const unspent = {
455
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
456
+ value: '0.00504422',
457
+ value_int: 504422,
458
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
459
+ n: 1,
460
+ script_pub_key: {
461
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
462
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
463
+ },
464
+ req_sigs: 1,
465
+ type: 'scripthash',
466
+ confirmations: 9,
467
+ id: 61330229,
468
+ };
469
+ _.extend(unspent, p2shAddress);
470
+ unspent.value = unspent.value_int;
471
+ unspent.tx_hash = unspent.txid;
472
+ unspent.tx_output_n = unspent.n;
473
+ unspent.script = unspent.outputScript;
474
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
475
+ const transaction = (await fakeProdWallet.createTransaction({
476
+ changeAddress: p2shAddress.address,
477
+ unspents: [unspent],
478
+ recipients: {},
479
+ noSplitChange: true,
480
+ forceChangeAtEnd: true,
481
+ feeRate: 10000,
482
+ bitgoFee: {
483
+ amount: 0,
484
+ address: '',
485
+ },
486
+ opReturns: { 'BitGo p2sh test': 1000 },
487
+ usePsbt: false,
488
+ }));
489
+ transaction.transactionHex.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b80100000000ffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
490
+ // add first signature
491
+ transaction.keychain = userKeypair;
492
+ transaction.forceBCH = true;
493
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
494
+ signature1.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000b60047304402206221a97f081d87e02e3b14988a64861811a6a8de4f11f74f5aaea45981cf612e022077a08a5bd7d781e79838afbb126af2e48802fefad660afdbd8805f5e598ed5884100004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
495
+ // add second signature
496
+ transaction.transactionHex = signature1.tx;
497
+ transaction.keychain = backupKeypair;
498
+ transaction.fullLocalSigning = true;
499
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
500
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/a8ccb928169032d6e1f37bf81dfd9ab6d90362a4f84e577397fa690aa711550c
501
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
502
+ // changed, changing the output amounts and thus the tx hex.
503
+ signature2.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000fdfe000047304402206221a97f081d87e02e3b14988a64861811a6a8de4f11f74f5aaea45981cf612e022077a08a5bd7d781e79838afbb126af2e48802fefad660afdbd8805f5e598ed5884148304502210082bc546293858459f3895db24c85ccf37505c56f8faf4bb8f78cf40135bc2f2b02203dc1c78d7c7ceaf6b924eca3c39b95e8a227b069a07047581273136b47ca7ac441004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
504
+ });
505
+ it('default segwit', async function () {
506
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
507
+ const unspent = {
508
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
509
+ value: '0.18750000',
510
+ value_int: 18750000,
511
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
512
+ n: 0,
513
+ script_pub_key: {
514
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
515
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
516
+ },
517
+ req_sigs: 1,
518
+ type: 'scripthash',
519
+ confirmations: 0,
520
+ id: 61331617,
521
+ };
522
+ _.extend(unspent, segwitAddress);
523
+ unspent.value = unspent.value_int;
524
+ unspent.tx_hash = unspent.txid;
525
+ unspent.tx_output_n = unspent.n;
526
+ unspent.script = unspent.outputScript;
527
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
528
+ const transaction = (await fakeProdWallet.createTransaction({
529
+ changeAddress: segwitAddress.address,
530
+ unspents: [unspent],
531
+ recipients: {},
532
+ noSplitChange: true,
533
+ forceChangeAtEnd: true,
534
+ feeRate: 10000,
535
+ bitgoFee: {
536
+ amount: 0,
537
+ address: '',
538
+ },
539
+ opReturns: { 'BitGo segwit test': 1000 },
540
+ usePsbt: false,
541
+ }));
542
+ transaction.transactionHex.should.equal('01000000011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000000ffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a8700000000');
543
+ // add first signature
544
+ transaction.keychain = userKeypair;
545
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
546
+ signature1.tx.should.equal('010000000001011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000023220020440e858228b753544b4c57e300296b55717f811053883f9be9b6a712eacd931cffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a870500483045022100bf3a8914a1bfe92661f27ca37c0d6b5c0b3c7353614c955646929f2e7eb89ffe02202d556b0ffab37c104bae67406ca16f8859cfa37c6a40f2013d89afcecd5594f3010000695221032c505fc8a1e4b56811b27366a371e61c9faf565dd2fabaff7a70eac19c32157c210251160b583bd5dc0f0d48096505131c4347ab65b4f21ed57d76c38157499c003d2102679712d62a2560917cc43fd2cc3a1b9b61f528c88bc64905bae6ee079e60609f53ae00000000');
547
+ // add second signature
548
+ transaction.transactionHex = signature1.tx;
549
+ transaction.keychain = backupKeypair;
550
+ transaction.fullLocalSigning = true;
551
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
552
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/d67266f1de905baaee750011fa4b3d88a8e3a1758d5173a659c67709488dde07
553
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
554
+ // changed, changing the output amounts and thus the tx hex.
555
+ signature2.tx.should.equal('010000000001011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000023220020440e858228b753544b4c57e300296b55717f811053883f9be9b6a712eacd931cffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a870500483045022100bf3a8914a1bfe92661f27ca37c0d6b5c0b3c7353614c955646929f2e7eb89ffe02202d556b0ffab37c104bae67406ca16f8859cfa37c6a40f2013d89afcecd5594f30147304402205cf8d2f2be6ce083d35654bdc3fa85d7e71b227d457e9245bb603b21e7b5165102203ea686226db8320e08c26bfb304048b3a9473d0e05797d3658dacb2f09a2b51c0100695221032c505fc8a1e4b56811b27366a371e61c9faf565dd2fabaff7a70eac19c32157c210251160b583bd5dc0f0d48096505131c4347ab65b4f21ed57d76c38157499c003d2102679712d62a2560917cc43fd2cc3a1b9b61f528c88bc64905bae6ee079e60609f53ae00000000');
556
+ });
557
+ it('creates an unsigned tx made of uncompressed public keys of v1 safe wallet', async function () {
558
+ const { address, redeemScript, scriptPubKey } = await (0, fixtures_1.getFixture)(`${__dirname}/fixtures/sign-transaction.json`);
559
+ const testBitgo = new bitgoAPI_1.BitGoAPI({ env: 'test', clientConstants: { constants: {} } });
560
+ const fakeTestV1SafeWallet = new Wallet(testBitgo, {
561
+ id: address,
562
+ private: { safe: { redeemScript } },
563
+ });
564
+ const unspentsToSpend = [
565
+ {
566
+ value: 100000,
567
+ redeemScript,
568
+ script: scriptPubKey,
569
+ tx_hash: 'a55d11dc8b701bd19601fbfe711a1e465fc8f128ec4474e78e1fd087e808e5fe',
570
+ tx_output_n: 0,
571
+ confirmations: 1,
572
+ },
573
+ {
574
+ value: 100000,
575
+ redeemScript,
576
+ script: scriptPubKey,
577
+ tx_hash: '48fb879cec879356045a331937023aed859f5dc5db955a1dc8a5ccf29f49d108',
578
+ tx_output_n: 0,
579
+ confirmations: 1,
580
+ },
581
+ ];
582
+ const recipients = {
583
+ '2MyGxrhLC4kRfuVjLqCVYFtC7DchhgMCiNz': 191340, // purposely set to simulate a sweep transaction
584
+ };
585
+ const scope = (0, nock_1.default)(bgUrlTest)
586
+ .post('/api/v1/billing/address')
587
+ .reply(200, { address: '2N3L9cu9WN2Df7Xvb1Y8owokuDVj5Hdyv4i' });
588
+ const result = await fakeTestV1SafeWallet.createTransaction({
589
+ recipients,
590
+ unspents: unspentsToSpend,
591
+ feeRate: 10000, // 10 sat/byte
592
+ bitgoFee: {
593
+ amount: 0,
594
+ address: '',
595
+ },
596
+ usePsbt: false,
597
+ });
598
+ scope.isDone().should.be.true();
599
+ result.estimatedSize.should.equal(866);
600
+ result.fee.should.equal(8660);
601
+ // This should equal to 1 because this is a sweep transaction but due to hardcoded addition of
602
+ // 1 change output in transactionBuilder, it is 2.
603
+ // Because of this the estimated size of the transactions is more than what it actually is in the hex.
604
+ result.txInfo.nOutputs.should.equal(2);
605
+ });
606
+ it('signs an unsigned tx made of uncompressed public keys of v1 safe wallet & verifies signatures', async function () {
607
+ const { address, redeemScript, scriptPubKey, userKeyWIF: userSigningKey, bitgoKeyWIF: bitgoSigningKey, unsignedTxHex, halfSignedTxHex, fullSignedTxHex, } = await (0, fixtures_1.getFixture)(`${__dirname}/fixtures/sign-transaction.json`);
608
+ const testBitgo = new bitgoAPI_1.BitGoAPI({ env: 'test', clientConstants: { constants: {} } });
609
+ const fakeTestV1SafeWallet = new Wallet(testBitgo, {
610
+ id: address,
611
+ private: { safe: { redeemScript } },
612
+ });
613
+ const unspentsToSpend = [
614
+ { value: 100000, redeemScript, script: scriptPubKey },
615
+ { value: 100000, redeemScript, script: scriptPubKey },
616
+ ];
617
+ const halfSignedTx = await fakeTestV1SafeWallet.signTransaction({
618
+ transactionHex: unsignedTxHex,
619
+ signingKey: userSigningKey,
620
+ unspents: unspentsToSpend,
621
+ validate: true,
622
+ });
623
+ halfSignedTx.tx.should.equal(halfSignedTxHex);
624
+ const fullSignedTx = await fakeTestV1SafeWallet.signTransaction({
625
+ transactionHex: halfSignedTxHex,
626
+ signingKey: bitgoSigningKey,
627
+ unspents: unspentsToSpend,
628
+ validate: true,
629
+ fullLocalSigning: true,
630
+ });
631
+ // Upon calling txb.build() instead after getting 2 valid signatures, we get a valid full signed tx that was broadcast
632
+ // and confirmed on testnet here: https://mempool.space/testnet/tx/bde09f1bd5e6661c28d90e4c96291853e21ba15ab42f3e4a30719decb73e791b
633
+ // It's present in the fullSignedTxHexBuildComplete property of the fixture.
634
+ fullSignedTx.tx.should.equal(fullSignedTxHex);
635
+ });
636
+ it('BCH segwit should fail', async function () {
637
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
638
+ const unspent = {
639
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
640
+ value: '0.18750000',
641
+ value_int: 18750000,
642
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
643
+ n: 0,
644
+ script_pub_key: {
645
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
646
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
647
+ },
648
+ req_sigs: 1,
649
+ type: 'scripthash',
650
+ confirmations: 0,
651
+ id: 61331617,
652
+ };
653
+ _.extend(unspent, segwitAddress);
654
+ unspent.value = unspent.value_int;
655
+ unspent.tx_hash = unspent.txid;
656
+ unspent.tx_output_n = unspent.n;
657
+ unspent.script = unspent.outputScript;
658
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
659
+ const transaction = (await fakeProdWallet.createTransaction({
660
+ changeAddress: segwitAddress.address,
661
+ unspents: [unspent],
662
+ recipients: {},
663
+ noSplitChange: true,
664
+ forceChangeAtEnd: true,
665
+ feeRate: 10000,
666
+ bitgoFee: {
667
+ amount: 0,
668
+ address: '',
669
+ },
670
+ opReturns: { 'BitGo segwit test': 1000 },
671
+ usePsbt: false,
672
+ }));
673
+ transaction.transactionHex.should.equal('01000000011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000000ffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a8700000000');
674
+ // add first signature
675
+ transaction.keychain = userKeypair;
676
+ transaction.forceBCH = true;
677
+ (() => fakeProdWallet.signTransaction(transaction)).should.throw('BCH does not support segwit inputs');
678
+ });
679
+ it('mixed p2sh & segwit', async function () {
680
+ const p2shAddress = fakeWallet.generateAddress({ path: '/0/14', segwit: false });
681
+ const segwitAddress = fakeWallet.generateAddress({ path: '/10/14', segwit: true });
682
+ const p2shUnspent = {
683
+ addresses: ['2N533fqgyPYKVD892nBRaYmFHbbTykhYSEw'],
684
+ value: '2.99996610',
685
+ value_int: 299996610,
686
+ txid: 'f654ce0a5be3f12df7fecf4ee777b6d86b5aa8c710ef6946ec121206b4f8757c',
687
+ n: 1,
688
+ script_pub_key: {
689
+ asm: 'OP_HASH160 8153e7a35508088b6cf599226792c7de2dbff252 OP_EQUAL',
690
+ hex: 'a9148153e7a35508088b6cf599226792c7de2dbff25287',
691
+ },
692
+ req_sigs: 1,
693
+ type: 'scripthash',
694
+ confirmations: 0,
695
+ id: 61331263,
696
+ };
697
+ const segwitUnspent = {
698
+ addresses: ['2NBtpXcDruf3zRutmF4AbCMFNQHXsGNP6kT'],
699
+ value: '1.50000000',
700
+ value_int: 150000000,
701
+ txid: 'a4409c3f042fae67b890ac3df40ef0db03539c67331fd7e9260511893b4f9f24',
702
+ n: 0,
703
+ script_pub_key: {
704
+ asm: 'OP_HASH160 cc8e7cbf481389d3183a590acfa6aa66eb97c8e1 OP_EQUAL',
705
+ hex: 'a914cc8e7cbf481389d3183a590acfa6aa66eb97c8e187',
706
+ },
707
+ req_sigs: 1,
708
+ type: 'scripthash',
709
+ confirmations: 0,
710
+ id: 61330882,
711
+ };
712
+ const addresses = [p2shAddress, segwitAddress];
713
+ const unspents = [p2shUnspent, segwitUnspent].map((unspent, index) => {
714
+ const address = addresses[index];
715
+ _.extend(unspent, address);
716
+ unspent.value = unspent.value_int;
717
+ unspent.tx_hash = unspent.txid;
718
+ unspent.tx_output_n = unspent.n;
719
+ unspent.script = unspent.outputScript;
720
+ return unspent;
721
+ });
722
+ const transaction = (await fakeWallet.createTransaction({
723
+ changeAddress: p2shAddress.address,
724
+ unspents: unspents,
725
+ recipients: {},
726
+ noSplitChange: true,
727
+ forceChangeAtEnd: true,
728
+ feeRate: 10000,
729
+ opReturns: { 'BitGo mixed p2sh & segwit test': 400000000 },
730
+ bitgoFee: {
731
+ amount: 81760,
732
+ address: '2ND7jQR5itjGTbh3DKgbpZWSY9ungDrwcwb',
733
+ },
734
+ usePsbt: false,
735
+ }));
736
+ transaction.transactionHex.should.equal('01000000027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f60100000000ffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a40000000000ffffffff030084d71700000000206a1e426974476f206d6978656420703273682026207365677769742074657374b08ff9020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700000000');
737
+ // add first signature
738
+ transaction.keychain = userKeypair;
739
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
740
+ signature1.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000b700483045022100ffc45d93cbaf4c1c850e21f277c5b311d3e3957f1338955cb165d72a768a054c022052020593b36781eea00a9f8dcbeb76608f920c7a933a9088318ab2f70c11e1d90100004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff030084d71700000000206a1e426974476f206d6978656420703273682026207365677769742074657374b08ff9020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700050047304402205898bee711467c09a5e22e1dcb1a11fce1a0d6ea129d911f813f87c7d45e067b02202f69fb118bbf0b072ed26d72cf8073e7acd66c205419a4a00f86a7ba0f6e3dd6010000695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
741
+ // add second signature
742
+ transaction.transactionHex = signature1.tx;
743
+ transaction.keychain = backupKeypair;
744
+ transaction.fullLocalSigning = true;
745
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
746
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/e2f696bcba91a376c36bb525df8c367938f6e2fd6344c90587bf12802091124c
747
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
748
+ // changed, changing the output amounts and thus the tx hex.
749
+ signature2.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000fdff0000483045022100ffc45d93cbaf4c1c850e21f277c5b311d3e3957f1338955cb165d72a768a054c022052020593b36781eea00a9f8dcbeb76608f920c7a933a9088318ab2f70c11e1d9014830450221008254d100401a3a831ed019e1662dbd90b96c6c4072b81ce640d152bc29295c10022013f86c5af5716234999a7bd6e94fc8f428f7697cc3138b3649d0ec4dd8681bc701004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff030084d71700000000206a1e426974476f206d6978656420703273682026207365677769742074657374b08ff9020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700050047304402205898bee711467c09a5e22e1dcb1a11fce1a0d6ea129d911f813f87c7d45e067b02202f69fb118bbf0b072ed26d72cf8073e7acd66c205419a4a00f86a7ba0f6e3dd60147304402207713d671b45989688e2665c2b11ab7e5ea8d57eb14f9da233c095dabe441308d022069521b5aeb071b07a70a7197a0c2bbc40a23ae63a04160cf3627250c4ba4c40f0100695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
750
+ });
751
+ it('should send to bech32 recipient', async function () {
752
+ const p2shAddress = fakeWallet.generateAddress({ path: '/0/14', segwit: false });
753
+ const segwitAddress = fakeWallet.generateAddress({ path: '/10/14', segwit: true });
754
+ const p2shUnspent = {
755
+ addresses: ['2N533fqgyPYKVD892nBRaYmFHbbTykhYSEw'],
756
+ value: '2.99996610',
757
+ value_int: 299996610,
758
+ txid: 'f654ce0a5be3f12df7fecf4ee777b6d86b5aa8c710ef6946ec121206b4f8757c',
759
+ n: 1,
760
+ script_pub_key: {
761
+ asm: 'OP_HASH160 8153e7a35508088b6cf599226792c7de2dbff252 OP_EQUAL',
762
+ hex: 'a9148153e7a35508088b6cf599226792c7de2dbff25287',
763
+ },
764
+ req_sigs: 1,
765
+ type: 'scripthash',
766
+ confirmations: 0,
767
+ id: 61331263,
768
+ };
769
+ const segwitUnspent = {
770
+ addresses: ['2NBtpXcDruf3zRutmF4AbCMFNQHXsGNP6kT'],
771
+ value: '1.50000000',
772
+ value_int: 150000000,
773
+ txid: 'a4409c3f042fae67b890ac3df40ef0db03539c67331fd7e9260511893b4f9f24',
774
+ n: 0,
775
+ script_pub_key: {
776
+ asm: 'OP_HASH160 cc8e7cbf481389d3183a590acfa6aa66eb97c8e1 OP_EQUAL',
777
+ hex: 'a914cc8e7cbf481389d3183a590acfa6aa66eb97c8e187',
778
+ },
779
+ req_sigs: 1,
780
+ type: 'scripthash',
781
+ confirmations: 0,
782
+ id: 61330882,
783
+ };
784
+ const addresses = [p2shAddress, segwitAddress];
785
+ const unspents = [p2shUnspent, segwitUnspent].map((unspent, index) => {
786
+ const address = addresses[index];
787
+ _.extend(unspent, address);
788
+ unspent.value = unspent.value_int;
789
+ unspent.tx_hash = unspent.txid;
790
+ unspent.tx_output_n = unspent.n;
791
+ unspent.script = unspent.outputScript;
792
+ return unspent;
793
+ });
794
+ const transaction = (await fakeWallet.createTransaction({
795
+ changeAddress: p2shAddress.address,
796
+ unspents: unspents,
797
+ recipients: { tb1qguzyk4w6kaqtpsczs5aj0w8r7598jq36egm8e98wqph3rwmex68seslgsg: 300000 },
798
+ noSplitChange: true,
799
+ forceChangeAtEnd: true,
800
+ feeRate: 10000,
801
+ opReturns: { 'BitGo mixed p2sh & segwit test': 400000000 },
802
+ bitgoFee: {
803
+ amount: 81760,
804
+ address: '2ND7jQR5itjGTbh3DKgbpZWSY9ungDrwcwb',
805
+ },
806
+ usePsbt: false,
807
+ }));
808
+ transaction.transactionHex.should.equal('01000000027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f60100000000ffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a40000000000ffffffff04e09304000000000022002047044b55dab740b0c302853b27b8e3f50a79023aca367c94ee006f11bb79368f0084d71700000000206a1e426974476f206d69786564207032736820262073656777697420746573747cfaf4020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700000000');
809
+ // add first signature
810
+ transaction.keychain = userKeypair;
811
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
812
+ signature1.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000b7004830450221008809377634e667d6e19f38a138a55b2b6370312af76a5ca3b776df61fc719617022021d90347b9085ab71a76c8400f984e322c15451ecc673dd37de30887436d37b40100004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff04e09304000000000022002047044b55dab740b0c302853b27b8e3f50a79023aca367c94ee006f11bb79368f0084d71700000000206a1e426974476f206d69786564207032736820262073656777697420746573747cfaf4020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba9870005004830450221008b95ac83e44c727b79ffbf4571171925d06f883a05c122b3b33c055f0bffa70102207b5ee3412ea8a5cec4a5c386f1b464ab68d531c6c697077bc462c05eb44a2832010000695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
813
+ // add second signature
814
+ transaction.transactionHex = signature1.tx;
815
+ transaction.keychain = backupKeypair;
816
+ transaction.fullLocalSigning = true;
817
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
818
+ console.log('signature1 ' + JSON.stringify(signature2));
819
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/e2f696bcba91a376c36bb525df8c367938f6e2fd6344c90587bf12802091124c
820
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
821
+ // changed, changing the output amounts and thus the tx hex.
822
+ signature2.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000fdfe00004830450221008809377634e667d6e19f38a138a55b2b6370312af76a5ca3b776df61fc719617022021d90347b9085ab71a76c8400f984e322c15451ecc673dd37de30887436d37b40147304402205a58e602042b8e8a5da509d19ce31050147dd0ffcfbe2bb337c23d4c88f4cc41022075bfa455d1f74e30fbd9c786cd4811a1defe54310f235b4193ce4ffa0e8309a101004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff04e09304000000000022002047044b55dab740b0c302853b27b8e3f50a79023aca367c94ee006f11bb79368f0084d71700000000206a1e426974476f206d69786564207032736820262073656777697420746573747cfaf4020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba9870005004830450221008b95ac83e44c727b79ffbf4571171925d06f883a05c122b3b33c055f0bffa70102207b5ee3412ea8a5cec4a5c386f1b464ab68d531c6c697077bc462c05eb44a283201473044022053690234582a6911a28cae9f534c980b7d7918749a7413c1c59327debf16ff0b022056175f5c27a363416b2ce4791aefc3d55545cacbd0527202e869e1127fc2f24d0100695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
823
+ });
824
+ });
825
+ describe('Send Many', function () {
826
+ it('responds with proper fee and fee rate', async function () {
827
+ const params = {
828
+ recipients: [
829
+ {
830
+ address: '2MutpXVYs8Lyk74pVDn3eAG7xnK4Wc2kjTQ',
831
+ amount: 300000,
832
+ },
833
+ ],
834
+ };
835
+ const unspents = [
836
+ {
837
+ value: 8170,
838
+ },
839
+ {
840
+ value: 800000,
841
+ },
842
+ ];
843
+ const createAndSignResponse = {
844
+ bitgoFee: 0,
845
+ travelInfos: [],
846
+ unspents,
847
+ tx: 'halfsignedhex',
848
+ };
849
+ sinon.stub(fakeWallet, 'createAndSignTransaction').returns(Promise.resolve(createAndSignResponse));
850
+ const getSendTxResponse = () => ({
851
+ status: 'accepted',
852
+ tx: '0100000000010228b5c3e2789d4770fc397ec79fa7255f86235297c5a04def678b481b8b09e81b0100000023220020b3bbe067960be39501f365b8999d53f2a8285d8d9836f61fad020e6a4a9e26fdffffffff1510e90411a86c49f2a52546a32a03febde2bc604741f0e85dc47adec33f515900000000fdfd0000483045022100a44bbf97b155c57703862be69d2b20c4b2ab9e94f402595880bf74402ccc87e202200a4aaf98f939b65c98ca08eb96074c222ecb1fc37e359b1d67a05f1c56dedfc001473044022003f3989a14284f132bbb550118c20256d4ea737704123a29955acc1d03ea6eb7022017223da7edcf73076d89875aa33360aa6a12141807f683c6c1b9a5a0d3ff6019014c695221025789857cc8be110ff4cbf354b52dd0e7e9326c6bfe0aee6c30c1ee69660c3dc02102f58f1b1516d05814ae688ca701856695e27050e3e16d3a2351284d7af84498882102385c7bcec3f38c13e87b558aebf2f20a8928e7ecbe11e7c3a47792bc8e33fe8853aeffffffff02e09304000000000017a9141d0c791cec3af1f37808d42f04593095d6fdea268705bc07000000000017a914d8c720f646c7c56c5467248e47c72dc0b2d30bbc87040047304402201eaa1359fffd3bdec5b48268bd2f15193a299c22b1970356f390883473324651022074186232f02245af9c0977031448c2c99e7b7e2b05b2ba4b32c3227d8ca1494e01483045022100bd61b37051c28533ea0b00dda75b1c4f1dee1b683bb7351b2d8dd720f6dfbe1102203acc4cf9d2dd44b294aa25812e99e7d8eb3730e4ff6f889d3cdcd525195750b8016952210219d093c18c27cb547737b4a49dddac9c3412b10e9f880eb30053c3eba81928542103747118892cac1b4da11526fc4ebeebe168dae0907cefb1a1812541cd46b07602210339f73b6750f8f91efd484b5aa2974321a6cc2776d5bd78b9cfb5fe18e3b2d66253ae005a9e1600',
853
+ hash: 'f8df43c2c650b3bb11277aee4531db99a715fa3b9dfd3d45a8d171342c1bf780',
854
+ instant: false,
855
+ });
856
+ const expectedResult = Object.assign({
857
+ fee: 1285,
858
+ feeRate: 2519.607843137255,
859
+ }, getSendTxResponse());
860
+ sinon.stub(fakeWallet, 'sendTransaction').resolves(getSendTxResponse());
861
+ const result = (await fakeWallet.sendMany(params));
862
+ result.tx.should.equal(expectedResult.tx);
863
+ result.fee.should.equal(expectedResult.fee);
864
+ result.feeRate.should.equal(expectedResult.feeRate);
865
+ });
866
+ });
867
+ describe('Accelerate Transaction (server mocked)', function accelerateTxMockedDescribe() {
868
+ let wallet;
869
+ let bgUrl;
870
+ let explorerUrl;
871
+ let minChangeSize;
872
+ let parentTxId = '6a74b74df4991d93c32d751336c85b5f2d1ee544a2dfbae2e5f4beb4f914e5e0';
873
+ const outputIdx = 0;
874
+ const outputAddress = '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4';
875
+ const unrelatedTxId = '08f5e0b4acb5ab8245229dfe161ce4ca0da1ec983e7a34b09e72f56979a467df';
876
+ const walletId = '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4';
877
+ /**
878
+ * Helper function to get the parent transaction ID from a transaction input
879
+ *
880
+ * This function converts `hash` (which is a Buffer object) to a usable txid string.
881
+ * The issue is that the bytes are stored in reverse order in the buffer, so
882
+ * the simple approach of just comparing the hex strings doesn't work.
883
+ * Instead, the Buffer is copied to a new Buffer object, the new Buffer
884
+ * object is reversed in-place, and then the new Buffer is converted to a
885
+ * hex string. After this, the result is a hex string which is the parent txid
886
+ *
887
+ * @param hash a bitcoinjs-lib transaction object's input hash
888
+ */
889
+ function inputParentTxId({ hash }) {
890
+ return Buffer.from(hash).reverse().toString('hex');
891
+ }
892
+ before(function accelerateTxMockedBefore() {
893
+ nock_1.default.pendingMocks().should.be.empty();
894
+ bitgo = new bitgoAPI_1.BitGoAPI({ env: 'mock', clientConstants: { constants: {} } });
895
+ // bitgo.initializeTestVars();
896
+ bitgo.setValidate(false);
897
+ wallet = new Wallet(bitgo, { id: walletId, private: { keychains: [userKeypair, backupKeypair, bitgoKey] } });
898
+ wallet.bitgo = bitgo;
899
+ bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
900
+ explorerUrl = sdk_core_1.common.Environments[bitgo.getEnv()].btcExplorerBaseUrl;
901
+ // try to get the min change size from the server, otherwise default to 0.1 BTC
902
+ // TODO: minChangeSize is not currently a constant defined on the client and should be added
903
+ minChangeSize = 1e7;
904
+ });
905
+ after(function accelerateTxMockedAfter() {
906
+ // make sure all nocks are cleared or consumed after the tests are complete
907
+ nock_1.default.pendingMocks().should.be.empty();
908
+ });
909
+ it('arguments', async () => {
910
+ await wallet.accelerateTransaction({ feeRate: 123 }).should.be.rejectedWith(/^Missing parameter: transactionID$/);
911
+ await wallet
912
+ .accelerateTransaction({ transactionID: 123, feeRate: 123 })
913
+ .should.be.rejectedWith(/^Expecting parameter string: transactionID but found number$/);
914
+ await wallet
915
+ .accelerateTransaction({ transactionID: '123' })
916
+ .should.be.rejectedWith(/^Missing parameter: feeRate$/);
917
+ const feeRatesParams = ['123', 0, -10, -Infinity, Infinity, NaN];
918
+ for (const feeRate of feeRatesParams) {
919
+ await wallet
920
+ .accelerateTransaction({ transactionID: '123', feeRate })
921
+ .should.be.rejectedWith(/^Expecting positive finite number for parameter: feeRate$/);
922
+ }
923
+ });
924
+ describe('bad input', function badInputDescribe() {
925
+ after(() => {
926
+ // make sure all nocks are cleared or consumed after the tests are complete
927
+ nock_1.default.pendingMocks().should.be.empty();
928
+ });
929
+ it('non existent transaction ID', async () => {
930
+ (0, nock_1.default)(bgUrl)
931
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
932
+ .reply(404, 'transaction not found on this wallet');
933
+ await wallet
934
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 123 })
935
+ .should.be.rejectedWith(/^404\ntransaction not found on this wallet$/);
936
+ });
937
+ it('confirmed transaction', async () => {
938
+ (0, nock_1.default)(bgUrl).get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`).reply(200, {
939
+ confirmations: 6,
940
+ });
941
+ await wallet
942
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
943
+ .should.be.rejectedWith(/^Transaction [0-9a-f]+ is already confirmed and cannot be accelerated$/);
944
+ });
945
+ it('no outputs to wallet', async () => {
946
+ (0, nock_1.default)(bgUrl)
947
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
948
+ .reply(200, {
949
+ outputs: [
950
+ {
951
+ account: outputAddress,
952
+ value: 1890000,
953
+ vout: 0,
954
+ chain: 0,
955
+ },
956
+ ],
957
+ confirmations: 0,
958
+ });
959
+ await wallet
960
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
961
+ .should.be.rejectedWith(/^Transaction [0-9a-f]+ contains no outputs to this wallet, and thus cannot be accelerated$/);
962
+ });
963
+ /*
964
+ * This test covers the case where a failure occurs during the process of
965
+ * converting an output from the parent transaction into an unspent which
966
+ * can be used to chain the child tx to the parent.
967
+ *
968
+ * This should never happen, but it is possible (for example, in the case
969
+ * of an attempted double spend of the output from the parent, or a race
970
+ * between finding the parent output, and retrieving the corresponding unspent).
971
+ */
972
+ it('cannot find correct unspent to use', async () => {
973
+ (0, nock_1.default)(bgUrl)
974
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
975
+ .reply(200, {
976
+ outputs: [
977
+ {
978
+ account: outputAddress,
979
+ value: 50 * 1e4,
980
+ vout: outputIdx,
981
+ isMine: true,
982
+ chain: 0,
983
+ },
984
+ ],
985
+ confirmations: 0,
986
+ hex: parentTxId,
987
+ fee: 10,
988
+ });
989
+ (0, nock_1.default)(bgUrl).get(`/api/v1/wallet/${wallet.id()}/unspents`).query(true).reply(200, {
990
+ count: 0,
991
+ unspents: [],
992
+ });
993
+ await wallet
994
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
995
+ .should.be.rejectedWith(/^Could not find unspent output from parent tx to use as child input$/);
996
+ });
997
+ it('Detects when an incorrect tx hex is returned by the external service', async () => {
998
+ (0, nock_1.default)(bgUrl)
999
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1000
+ .reply(200, {
1001
+ outputs: [
1002
+ {
1003
+ account: outputAddress,
1004
+ value: 10,
1005
+ vout: outputIdx,
1006
+ isMine: true,
1007
+ chain: 0,
1008
+ },
1009
+ ],
1010
+ confirmations: 0,
1011
+ hex: fixtures[parentTxId],
1012
+ fee: 10,
1013
+ });
1014
+ (0, nock_1.default)(bgUrl)
1015
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1016
+ .query(true)
1017
+ .reply(200, {
1018
+ count: 1,
1019
+ unspents: [
1020
+ {
1021
+ tx_hash: parentTxId,
1022
+ tx_output_n: outputIdx,
1023
+ },
1024
+ ],
1025
+ });
1026
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[unrelatedTxId]);
1027
+ await wallet
1028
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1029
+ .should.be.rejectedWith(/^Decoded transaction id is [0-9a-f]+, which does not match given txid [0-9a-f]+$/);
1030
+ });
1031
+ it('cannot cover child fee with one parent output and one wallet unspent', async () => {
1032
+ (0, nock_1.default)(bgUrl)
1033
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1034
+ .reply(200, {
1035
+ outputs: [
1036
+ {
1037
+ account: outputAddress,
1038
+ value: 10,
1039
+ vout: outputIdx,
1040
+ isMine: true,
1041
+ chain: 0,
1042
+ },
1043
+ ],
1044
+ confirmations: 0,
1045
+ hex: fixtures[parentTxId],
1046
+ fee: 10,
1047
+ });
1048
+ (0, nock_1.default)(bgUrl)
1049
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1050
+ .query(true)
1051
+ .reply(200, {
1052
+ count: 1,
1053
+ unspents: [
1054
+ {
1055
+ tx_hash: parentTxId,
1056
+ tx_output_n: outputIdx,
1057
+ },
1058
+ ],
1059
+ });
1060
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1061
+ (0, nock_1.default)(bgUrl).get(`/api/v1/wallet/${wallet.id()}/unspents`).query(true).reply(200, {
1062
+ count: 0,
1063
+ unspents: [],
1064
+ });
1065
+ await wallet
1066
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1067
+ .should.be.rejectedWith(/^Insufficient confirmed unspents available to cover the child fee$/);
1068
+ });
1069
+ it('cannot lower fee rate', async () => {
1070
+ (0, nock_1.default)(bgUrl)
1071
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1072
+ .reply(200, {
1073
+ outputs: [
1074
+ {
1075
+ account: outputAddress,
1076
+ value: 10,
1077
+ vout: outputIdx,
1078
+ isMine: true,
1079
+ chain: 11,
1080
+ },
1081
+ ],
1082
+ confirmations: 0,
1083
+ hex: fixtures[parentTxId],
1084
+ fee: 10000, // large fee, and thus fee rate, for parent
1085
+ });
1086
+ (0, nock_1.default)(bgUrl)
1087
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1088
+ .query(true)
1089
+ .reply(200, {
1090
+ count: 1,
1091
+ unspents: [
1092
+ {
1093
+ tx_hash: parentTxId,
1094
+ tx_output_n: outputIdx,
1095
+ },
1096
+ ],
1097
+ });
1098
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1099
+ await wallet
1100
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1101
+ .should.be.rejectedWith(/^Cannot lower fee rate! \(Parent tx fee rate is \d+\.?\d* sat\/kB, and requested fee rate was \d+\.?\d* sat\/kB\)$/);
1102
+ });
1103
+ it('cannot break maximum fee limit for combined transaction', async () => {
1104
+ (0, nock_1.default)(bgUrl)
1105
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1106
+ .reply(200, {
1107
+ outputs: [
1108
+ {
1109
+ account: outputAddress,
1110
+ value: 3e7,
1111
+ vout: outputIdx,
1112
+ isMine: true,
1113
+ chain: 11,
1114
+ },
1115
+ ],
1116
+ confirmations: 0,
1117
+ hex: fixtures[parentTxId],
1118
+ fee: 1000,
1119
+ });
1120
+ (0, nock_1.default)(bgUrl)
1121
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1122
+ .query(true)
1123
+ .reply(200, {
1124
+ count: 1,
1125
+ unspents: [
1126
+ {
1127
+ tx_hash: parentTxId,
1128
+ tx_output_n: outputIdx,
1129
+ },
1130
+ ],
1131
+ });
1132
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1133
+ await wallet
1134
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2e6 })
1135
+ .should.be.rejectedWith(/^Transaction cannot be accelerated\. Combined fee rate of \d+\.?\d* sat\/kB exceeds maximum fee rate of \d+\.?\d* sat\/kB$/);
1136
+ });
1137
+ });
1138
+ describe('successful tx acceleration', function successfulTxDescribe() {
1139
+ const feeRate = 20000;
1140
+ beforeEach(() => {
1141
+ (0, nock_1.default)(bgUrl).post(`/api/v1/wallet/${wallet.id()}/address/1`).reply(200, {
1142
+ address: '2NCYjG8Q56yr8tx9jazNoYnGKxjgB2MQSfY',
1143
+ });
1144
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, {
1145
+ address: '2NFbvo2HK4eXZm1aqDcSDGGqD64FPt7T6d8',
1146
+ });
1147
+ (0, nock_1.default)(bgUrl).get('/api/v1/tx/fee').query(true).reply(200, {
1148
+ feePerKb: 0,
1149
+ });
1150
+ (0, nock_1.default)(bgUrl)
1151
+ .post(`/api/v1/keychain/${userKeypair.xpub}`, {})
1152
+ .reply(200, {
1153
+ encryptedXprv: bitgo.encrypt({ input: userKeypair.xprv, password: TestBitGo.TEST_WALLET1_PASSCODE }),
1154
+ path: userKeypair.path + userKeypair.walletSubPath,
1155
+ });
1156
+ });
1157
+ it('accelerates a stuck tx without additional unspents', async () => {
1158
+ parentTxId = '75cfc5a7b214c4b73c92c7b02608cde70b226767a9576f84c04407e43fd385bd';
1159
+ (0, nock_1.default)(bgUrl)
1160
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1161
+ .reply(200, {
1162
+ fee: 434,
1163
+ outputs: [
1164
+ {
1165
+ vout: 0,
1166
+ value: 10348500,
1167
+ isMine: true,
1168
+ chain: 1,
1169
+ },
1170
+ {
1171
+ vout: 1,
1172
+ value: 10000,
1173
+ isMine: true,
1174
+ chain: 11,
1175
+ },
1176
+ ],
1177
+ });
1178
+ (0, nock_1.default)(bgUrl)
1179
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1180
+ .query(true)
1181
+ .reply(200, {
1182
+ unspents: [
1183
+ {
1184
+ tx_hash: parentTxId,
1185
+ tx_output_n: 0,
1186
+ value: 10348500,
1187
+ redeemScript: '0020f7b58d455351b7b8ddd7c8986d98244f6a95f0746720091537323b967800f744',
1188
+ chainPath: '/11/160',
1189
+ witnessScript: '5221027f0b45bb4155ea532e3b4312fe0be80166f297d1e0753d2d4a9118c073ad6514210310aa9d68c98831625f329b7826b6c3e3b53e16736b1994b8902442bdcd6653d121026e0ca414f2488b0ab572b99e0ae5442911ab4e0821b2709d885175a527fd552b53ae',
1190
+ },
1191
+ ],
1192
+ });
1193
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1194
+ (0, nock_1.default)(bgUrl)
1195
+ .post('/api/v1/tx/send', (body) => {
1196
+ return !body.ignoreMaxFeeRate;
1197
+ })
1198
+ .reply(200, function (_, body) {
1199
+ return {
1200
+ transaction: body.tx,
1201
+ };
1202
+ });
1203
+ const childTx = await wallet.accelerateTransaction({
1204
+ transactionID: parentTxId,
1205
+ feeRate,
1206
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1207
+ });
1208
+ should.exist(childTx);
1209
+ childTx.should.have.property('status', 'accepted');
1210
+ childTx.should.have.property('tx');
1211
+ // assert the following:
1212
+ // 0) The child tx has exactly one input
1213
+ // 1) The parent tx output is an input
1214
+ // 2) The child tx has exactly one output
1215
+ // 3) The child tx output meets the minimum change threshold
1216
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1217
+ decodedChild.ins.length.should.equal(1);
1218
+ decodedChild.outs.length.should.equal(1);
1219
+ const childInput = decodedChild.ins[0];
1220
+ childInput.should.have.property('index', 0);
1221
+ childInput.should.have.property('hash');
1222
+ const inputTxId = inputParentTxId(childInput);
1223
+ inputTxId.should.equal(parentTxId);
1224
+ const childOutput = decodedChild.outs[0];
1225
+ childOutput.should.have.property('value');
1226
+ childOutput.value.should.be.above(minChangeSize);
1227
+ });
1228
+ it('accelerates a stuck tx with one additional segwit unspent', async () => {
1229
+ parentTxId = '8815f202c8654b6c8b295749545c711878cd845a14cb1ea982394d0c14945c33';
1230
+ const additionalUnspentTxId = '07d6ee57b024ce2b6108f67847454a0a79a4fcfb98ab255553a2993a1a170b87';
1231
+ (0, nock_1.default)(bgUrl)
1232
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1233
+ .reply(200, {
1234
+ fee: 1336,
1235
+ outputs: [
1236
+ {
1237
+ vout: 0,
1238
+ value: 10000,
1239
+ isMine: true,
1240
+ chain: 11,
1241
+ },
1242
+ {
1243
+ vout: 1,
1244
+ value: 8664,
1245
+ isMine: true,
1246
+ chain: 1,
1247
+ },
1248
+ ],
1249
+ confirmations: 0,
1250
+ });
1251
+ (0, nock_1.default)(bgUrl)
1252
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1253
+ .query(true)
1254
+ .reply(200, {
1255
+ unspents: [
1256
+ {
1257
+ tx_hash: parentTxId,
1258
+ tx_output_n: 0,
1259
+ value: 10000,
1260
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1261
+ chainPath: '/0/0',
1262
+ },
1263
+ ],
1264
+ });
1265
+ (0, nock_1.default)(bgUrl)
1266
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1267
+ .query(true)
1268
+ .reply(200, {
1269
+ unspents: [
1270
+ {
1271
+ tx_hash: additionalUnspentTxId,
1272
+ tx_output_n: 0,
1273
+ value: 19935526,
1274
+ redeemScript: '0020d34ef6dd34ef2a4fbea67c541c1c796749a60afe4a97fee8ec7ded188bd749da',
1275
+ chainPath: '/11/155',
1276
+ witnessScript: '522102219d2aa8417633f0bce3911374a1604c1b64161f83a3c2ee409c27c42355f08e2102c9734920dc4da06c289fe69171dfcd75e3b9b4f190d0cbc3d5d0ff3f5fdeeaae2103ccd68d7fa8dc0d02dd45dad165557a48582eda4435fae7377b3c31e08ad065c953ae',
1277
+ },
1278
+ ],
1279
+ });
1280
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1281
+ (0, nock_1.default)(bgUrl)
1282
+ .post('/api/v1/tx/send', (body) => {
1283
+ return !body.ignoreMaxFeeRate;
1284
+ })
1285
+ .reply(200, function (_, body) {
1286
+ return {
1287
+ transaction: body.tx,
1288
+ };
1289
+ });
1290
+ const childTx = await wallet.accelerateTransaction({
1291
+ transactionID: parentTxId,
1292
+ feeRate,
1293
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1294
+ });
1295
+ should.exist(childTx);
1296
+ childTx.should.have.property('status', 'accepted');
1297
+ childTx.should.have.property('tx');
1298
+ // assert the following:
1299
+ // 0) The child tx has exactly two inputs
1300
+ // 1) The parent tx output is an input
1301
+ // 2) The additional unspent output is an input
1302
+ // 3) The child tx has exactly one output
1303
+ // 4) The child tx output meets the minimum change threshold
1304
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1305
+ decodedChild.ins.length.should.equal(2);
1306
+ decodedChild.outs.length.should.equal(1);
1307
+ let inputFromParent = undefined;
1308
+ let additionalInput = undefined;
1309
+ _.forEach(decodedChild.ins, (input) => {
1310
+ input.should.have.property('hash');
1311
+ input.should.have.property('index');
1312
+ const inputTxId = inputParentTxId(input);
1313
+ if (inputTxId === parentTxId) {
1314
+ inputFromParent = input;
1315
+ }
1316
+ else {
1317
+ additionalInput = input;
1318
+ }
1319
+ });
1320
+ should.exist(inputFromParent);
1321
+ const inputFromParentHash = inputParentTxId(inputFromParent);
1322
+ inputFromParentHash.should.equal(parentTxId);
1323
+ inputFromParent.index.should.equal(0);
1324
+ should.exist(additionalInput);
1325
+ const additionalInputHash = inputParentTxId(additionalInput);
1326
+ additionalInputHash.should.equal(additionalUnspentTxId);
1327
+ additionalInput.index.should.equal(0);
1328
+ const childOutput = decodedChild.outs[0];
1329
+ childOutput.should.have.property('value');
1330
+ childOutput.value.should.be.above(minChangeSize);
1331
+ });
1332
+ it('accelerates a stuck tx with one additional P2SH unspent', async () => {
1333
+ parentTxId = '8815f202c8654b6c8b295749545c711878cd845a14cb1ea982394d0c14945c33';
1334
+ const additionalUnspentTxId = 'e190310f2f3f71aa8846f1161cbce1533c24a857dd24e4501b131feb400aad58';
1335
+ (0, nock_1.default)(bgUrl)
1336
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1337
+ .reply(200, {
1338
+ fee: 1336,
1339
+ outputs: [
1340
+ {
1341
+ vout: 0,
1342
+ value: 10000,
1343
+ isMine: true,
1344
+ chain: 11,
1345
+ },
1346
+ {
1347
+ vout: 1,
1348
+ value: 8664,
1349
+ isMine: true,
1350
+ chain: 1,
1351
+ },
1352
+ ],
1353
+ confirmations: 0,
1354
+ });
1355
+ (0, nock_1.default)(bgUrl)
1356
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1357
+ .query(true)
1358
+ .reply(200, {
1359
+ unspents: [
1360
+ {
1361
+ tx_hash: parentTxId,
1362
+ tx_output_n: 0,
1363
+ value: 10000,
1364
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1365
+ chainPath: '/0/0',
1366
+ },
1367
+ ],
1368
+ });
1369
+ (0, nock_1.default)(bgUrl)
1370
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1371
+ .query(true)
1372
+ .reply(200, {
1373
+ unspents: [
1374
+ {
1375
+ tx_hash: additionalUnspentTxId,
1376
+ tx_output_n: 1,
1377
+ value: 20000000,
1378
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1379
+ chainPath: '/0/0',
1380
+ },
1381
+ ],
1382
+ });
1383
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1384
+ (0, nock_1.default)(bgUrl)
1385
+ .post('/api/v1/tx/send', (body) => {
1386
+ return !body.ignoreMaxFeeRate;
1387
+ })
1388
+ .reply(200, function (_, body) {
1389
+ return {
1390
+ transaction: body.tx,
1391
+ };
1392
+ });
1393
+ const childTx = await wallet.accelerateTransaction({
1394
+ transactionID: parentTxId,
1395
+ feeRate,
1396
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1397
+ });
1398
+ should.exist(childTx);
1399
+ childTx.should.have.property('status', 'accepted');
1400
+ childTx.should.have.property('tx');
1401
+ // assert the following:
1402
+ // 0) The child tx has exactly two inputs
1403
+ // 1) The parent tx output is an input
1404
+ // 2) The additional unspent output is an input
1405
+ // 3) The child tx has exactly one output
1406
+ // 4) The child tx output meets the minimum change threshold
1407
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1408
+ decodedChild.ins.length.should.equal(2);
1409
+ decodedChild.outs.length.should.equal(1);
1410
+ let inputFromParent = undefined;
1411
+ let additionalInput = undefined;
1412
+ _.forEach(decodedChild.ins, (input) => {
1413
+ input.should.have.property('hash');
1414
+ input.should.have.property('index');
1415
+ const inputHash = inputParentTxId(input);
1416
+ if (inputHash === parentTxId) {
1417
+ inputFromParent = input;
1418
+ }
1419
+ else {
1420
+ additionalInput = input;
1421
+ }
1422
+ });
1423
+ should.exist(inputFromParent);
1424
+ const inputFromParentHash = inputParentTxId(inputFromParent);
1425
+ inputFromParentHash.should.equal(parentTxId);
1426
+ inputFromParent.index.should.equal(0);
1427
+ should.exist(additionalInput);
1428
+ const additionalInputHash = inputParentTxId(additionalInput);
1429
+ additionalInputHash.should.equal(additionalUnspentTxId);
1430
+ additionalInput.index.should.equal(1);
1431
+ const childOutput = decodedChild.outs[0];
1432
+ childOutput.should.have.property('value');
1433
+ childOutput.value.should.be.above(minChangeSize);
1434
+ });
1435
+ it('accelerates a stuck tx with two additional unspents (segwit and P2SH)', async () => {
1436
+ parentTxId = '8815f202c8654b6c8b295749545c711878cd845a14cb1ea982394d0c14945c33';
1437
+ (0, nock_1.default)(bgUrl)
1438
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1439
+ .reply(200, {
1440
+ fee: 1336,
1441
+ outputs: [
1442
+ {
1443
+ vout: 0,
1444
+ value: 10000,
1445
+ isMine: true,
1446
+ chain: 11,
1447
+ },
1448
+ {
1449
+ vout: 1,
1450
+ value: 8664,
1451
+ isMine: true,
1452
+ chain: 1,
1453
+ },
1454
+ ],
1455
+ confirmations: 0,
1456
+ });
1457
+ (0, nock_1.default)(bgUrl)
1458
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1459
+ .query(true)
1460
+ .reply(200, {
1461
+ unspents: [
1462
+ {
1463
+ tx_hash: parentTxId,
1464
+ tx_output_n: 0,
1465
+ value: 10000,
1466
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1467
+ chainPath: '/0/0',
1468
+ },
1469
+ ],
1470
+ });
1471
+ (0, nock_1.default)(bgUrl)
1472
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1473
+ .query(true)
1474
+ .reply(200, {
1475
+ unspents: [
1476
+ {
1477
+ tx_hash: 'e190310f2f3f71aa8846f1161cbce1533c24a857dd24e4501b131feb400aad58',
1478
+ tx_output_n: 1,
1479
+ value: 800000,
1480
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1481
+ chainPath: '/0/0',
1482
+ },
1483
+ {
1484
+ tx_hash: '07d6ee57b024ce2b6108f67847454a0a79a4fcfb98ab255553a2993a1a170b87',
1485
+ tx_output_n: 0,
1486
+ value: 20006284,
1487
+ redeemScript: '0020d34ef6dd34ef2a4fbea67c541c1c796749a60afe4a97fee8ec7ded188bd749da',
1488
+ chainPath: '/11/155',
1489
+ witnessScript: '522102219d2aa8417633f0bce3911374a1604c1b64161f83a3c2ee409c27c42355f08e2102c9734920dc4da06c289fe69171dfcd75e3b9b4f190d0cbc3d5d0ff3f5fdeeaae2103ccd68d7fa8dc0d02dd45dad165557a48582eda4435fae7377b3c31e08ad065c953ae',
1490
+ },
1491
+ ],
1492
+ });
1493
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1494
+ (0, nock_1.default)(bgUrl)
1495
+ .post('/api/v1/tx/send', (body) => {
1496
+ return !body.ignoreMaxFeeRate;
1497
+ })
1498
+ .reply(200, function (_, body) {
1499
+ return {
1500
+ transaction: body.tx,
1501
+ };
1502
+ });
1503
+ const childTx = await wallet.accelerateTransaction({
1504
+ transactionID: parentTxId,
1505
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1506
+ feeRate,
1507
+ });
1508
+ should.exist(childTx);
1509
+ childTx.should.have.property('status', 'accepted');
1510
+ childTx.should.have.property('tx');
1511
+ // assert the following:
1512
+ // 0) The child tx has exactly three inputs
1513
+ // 1) The parent tx output is an input
1514
+ // 2) The child tx has exactly one output
1515
+ // 3) The child tx output meets the minimum change threshold
1516
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1517
+ decodedChild.ins.length.should.equal(3);
1518
+ decodedChild.outs.length.should.equal(1);
1519
+ let inputFromParent = undefined;
1520
+ const additionalInputs = [];
1521
+ _.forEach(decodedChild.ins, (input) => {
1522
+ input.should.have.property('hash');
1523
+ input.should.have.property('index');
1524
+ const inputHash = inputParentTxId(input);
1525
+ if (inputHash === parentTxId) {
1526
+ inputFromParent = input;
1527
+ }
1528
+ else {
1529
+ additionalInputs.push(input);
1530
+ }
1531
+ });
1532
+ should.exist(inputFromParent);
1533
+ const inputFromParentHash = inputParentTxId(inputFromParent);
1534
+ inputFromParentHash.should.equal(parentTxId);
1535
+ inputFromParent.index.should.equal(0);
1536
+ additionalInputs.length.should.equal(2);
1537
+ const childOutput = decodedChild.outs[0];
1538
+ childOutput.should.have.property('value');
1539
+ childOutput.value.should.be.above(minChangeSize);
1540
+ });
1541
+ it('correctly uses the ignoreMaxFeeRate parameter only when necessary', async () => {
1542
+ parentTxId = '75cfc5a7b214c4b73c92c7b02608cde70b226767a9576f84c04407e43fd385bd';
1543
+ (0, nock_1.default)(bgUrl)
1544
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1545
+ .reply(200, {
1546
+ fee: 434,
1547
+ outputs: [
1548
+ {
1549
+ vout: 0,
1550
+ value: 10348500,
1551
+ isMine: true,
1552
+ chain: 0,
1553
+ },
1554
+ {
1555
+ vout: 1,
1556
+ value: 10000,
1557
+ isMine: true,
1558
+ chain: 11,
1559
+ },
1560
+ ],
1561
+ });
1562
+ (0, nock_1.default)(bgUrl)
1563
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1564
+ .query(true)
1565
+ .reply(200, {
1566
+ unspents: [
1567
+ {
1568
+ tx_hash: parentTxId,
1569
+ tx_output_n: 0,
1570
+ value: 10348500,
1571
+ redeemScript: '0020f7b58d455351b7b8ddd7c8986d98244f6a95f0746720091537323b967800f744',
1572
+ chainPath: '/11/160',
1573
+ witnessScript: '5221027f0b45bb4155ea532e3b4312fe0be80166f297d1e0753d2d4a9118c073ad6514210310aa9d68c98831625f329b7826b6c3e3b53e16736b1994b8902442bdcd6653d121026e0ca414f2488b0ab572b99e0ae5442911ab4e0821b2709d885175a527fd552b53ae',
1574
+ },
1575
+ ],
1576
+ });
1577
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1578
+ (0, nock_1.default)(bgUrl)
1579
+ .post('/api/v1/tx/send', (body) => {
1580
+ // ignore max fee rate must be set for this test
1581
+ return body.ignoreMaxFeeRate;
1582
+ })
1583
+ .reply(200);
1584
+ // monkey patch the bitgo getConstants() function
1585
+ const oldGetConstants = bitgo.__proto__.getConstants;
1586
+ bitgo.__proto__.getConstants = () => ({
1587
+ // child fee rate in this test is 31378 sat/kb
1588
+ // so set the max fee rate just below that limit,
1589
+ // but above the combined fee rate of 20000
1590
+ maxFeeRate: 30000,
1591
+ });
1592
+ await wallet.accelerateTransaction({
1593
+ transactionID: parentTxId,
1594
+ feeRate,
1595
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1596
+ });
1597
+ nock_1.default.pendingMocks().should.be.empty();
1598
+ bitgo.__proto__.getConstants = oldGetConstants;
1599
+ });
1600
+ });
1601
+ });
1602
+ describe('getBitGoFee', function () {
1603
+ let bgUrl;
1604
+ let wallet;
1605
+ before(function () {
1606
+ nock_1.default.pendingMocks().should.be.empty();
1607
+ const prodBitgo = new bitgoAPI_1.BitGoAPI({ env: 'prod', clientConstants: { constants: {} } });
1608
+ bgUrl = sdk_core_1.common.Environments[prodBitgo.getEnv()].uri;
1609
+ wallet = new Wallet(prodBitgo, {
1610
+ id: '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4',
1611
+ private: { keychains: [userKeypair, backupKeypair, bitgoKey] },
1612
+ });
1613
+ });
1614
+ afterEach(function () {
1615
+ nock_1.default.cleanAll();
1616
+ });
1617
+ it('sends amount and instant without recipients when recipients array is empty', async function () {
1618
+ const scope = (0, nock_1.default)(bgUrl)
1619
+ .get(`/api/v1/wallet/${wallet.id()}/billing/fee`)
1620
+ .query({ amount: '100000', instant: 'false' })
1621
+ .reply(200, { fee: 1000 });
1622
+ const result = await wallet.getBitGoFee({ amount: 100000, instant: false });
1623
+ result.fee.should.equal(1000);
1624
+ scope.isDone().should.be.true();
1625
+ });
1626
+ it('sends recipients[] query params when recipients are provided', async function () {
1627
+ const addr1 = '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy';
1628
+ const addr2 = '3FZbgi29cpjq2GjdwV8eyHuJJnkLtktZc5';
1629
+ const scope = (0, nock_1.default)(bgUrl)
1630
+ .get(`/api/v1/wallet/${wallet.id()}/billing/fee`)
1631
+ .query((query) => {
1632
+ const recipientsParam = query['recipients[]'];
1633
+ const recipientsList = Array.isArray(recipientsParam) ? recipientsParam : [recipientsParam];
1634
+ return query.amount === '100000' && recipientsList.includes(addr1) && recipientsList.includes(addr2);
1635
+ })
1636
+ .reply(200, { fee: 0 });
1637
+ const result = await wallet.getBitGoFee({ amount: 100000, recipients: [addr1, addr2] });
1638
+ result.fee.should.equal(0);
1639
+ scope.isDone().should.be.true();
1640
+ });
1641
+ it('omits recipients[] when recipients array is empty', async function () {
1642
+ const scope = (0, nock_1.default)(bgUrl)
1643
+ .get(`/api/v1/wallet/${wallet.id()}/billing/fee`)
1644
+ .query((query) => query.amount === '200000' && !('recipients[]' in query))
1645
+ .reply(200, { fee: 500 });
1646
+ const result = await wallet.getBitGoFee({ amount: 200000, recipients: [] });
1647
+ result.fee.should.equal(500);
1648
+ scope.isDone().should.be.true();
1649
+ });
1650
+ it('throws when amount is not a number', function () {
1651
+ (() => wallet.getBitGoFee({ amount: 'bad' })).should.throw('invalid amount argument');
1652
+ });
1653
+ it('throws when instant is not a boolean', function () {
1654
+ (() => wallet.getBitGoFee({ amount: 100, instant: 'yes' })).should.throw('invalid instant argument');
1655
+ });
1656
+ });
1657
+ });
1658
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbGV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3YxL3dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsRUFBRTtBQUNGLG1CQUFtQjtBQUNuQixFQUFFO0FBQ0Ysb0RBQW9EO0FBQ3BELEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUYseUNBQXdDO0FBRXhDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBQ2pELG9EQUFpRDtBQUNqRCwwQ0FBNEI7QUFDNUIsbURBQThDO0FBQzlDLDhEQUFnRDtBQUNoRCwrQ0FBaUM7QUFDakMsZ0RBQXdCO0FBQ3hCLDZDQUErQjtBQUUvQiw0REFBdUQ7QUFFdkQsY0FBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7QUFFekIsTUFBTSxTQUFTLEdBQUc7SUFDaEIscUJBQXFCLEVBQUUsMEJBQTBCO0NBQ2xELENBQUM7QUFDRixRQUFRLENBQUMsMEJBQTBCLEVBQUU7SUFDbkMsTUFBTSxRQUFRLEdBQUcsSUFBQSwyQkFBVyxHQUFFLENBQUM7SUFFL0IsSUFBSSxLQUFLLEdBQUcsSUFBSSxtQkFBUSxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzlFLDhCQUE4QjtJQUU5QixNQUFNLFdBQVcsR0FBRztRQUNsQixJQUFJLEVBQUUsaUhBQWlIO1FBQ3ZILElBQUksRUFBRSxpSEFBaUg7UUFDdkgsTUFBTSxFQUFFLG9FQUFvRTtRQUM1RSxNQUFNLEVBQUUsa0VBQWtFO1FBQzFFLElBQUksRUFBRSxHQUFHO1FBQ1QsYUFBYSxFQUFFLE1BQU07S0FDdEIsQ0FBQztJQUNGLE1BQU0sYUFBYSxHQUFHO1FBQ3BCLElBQUksRUFBRSxpSEFBaUg7UUFDdkgsSUFBSSxFQUFFLGlIQUFpSDtRQUN2SCxN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LENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRTtZQUN6QyxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ3ZHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vXG4vLyBUZXN0cyBmb3IgV2FsbGV0XG4vL1xuLy8gQ29weXJpZ2h0IDIwMTQsIEJpdEdvLCBJbmMuICBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy9cblxuaW1wb3J0IHsgZ2V0Rml4dHVyZSB9IGZyb20gJy4vZml4dHVyZXMnO1xuXG5jb25zdCBXYWxsZXQgPSByZXF1aXJlKCcuLi8uLi8uLi9zcmMvdjEvd2FsbGV0Jyk7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJy4uLy4uLy4uL3NyYy9iaXRnb0FQSSc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBjb21tb24gfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5cbmltcG9ydCB7IGdldEZpeHR1cmVzIH0gZnJvbSAnLi9maXh0dXJlcy9hY2NlbGVyYXRlLXR4Jztcblxubm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuXG5jb25zdCBUZXN0Qml0R28gPSB7XG4gIFRFU1RfV0FMTEVUMV9QQVNTQ09ERTogJ2lWV2VBVGpxTFMxakpTaHJQcEVUdGkwYicsXG59O1xuZGVzY3JpYmUoJ1dhbGxldCBQcm90b3R5cGUgTWV0aG9kcycsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgZml4dHVyZXMgPSBnZXRGaXh0dXJlcygpO1xuXG4gIGxldCBiaXRnbyA9IG5ldyBCaXRHb0FQSSh7IGVudjogJ3Rlc3QnLCBjbGllbnRDb25zdGFudHM6IHsgY29uc3RhbnRzOiB7fSB9IH0pO1xuICAvLyBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcblxuICBjb25zdCB1c2VyS2V5cGFpciA9IHtcbiAgICB4cHJ2OiAneHBydjlzMjFaclFIMTQzSzJmSjkxUzRCUnN1cGNZckU2bW1ZOTZmY1g1SGtob1Rycndtd2pkMTZDbjg3Y1dpbkpqQnlyZnBvamp4N2V6c0pMeDdUQUtMVDhtOGhNNUtheDlZY294bkJlSlozdDJrJyxcbiAgICB4cHViOiAneHB1YjY2MU15TXdBcVJiY0Y5TmM3VGJCbzFyWkFhZ2lXRVZQV0tiREtUaE5HOHpxams3NkhBS0xrYVNiVG42ZEsyZFFQZnVEN3hqaWN4Q1pWV3ZqNjdmUDVuUTlXN1FVUm1vTVZBWDhtNmpac0dwJyxcbiAgICByYXdQdWI6ICcwMmMxMDNhYzc0NDgxODc0YjVlZjBmMzg1ZDEyNzI1ZTRmMTRhZWRjOWUwMGJjODE0Y2U5NmY0N2Y2MmNlN2FkZjInLFxuICAgIHJhd1BydjogJzkzNmM1YWYzZjhhZjgxZjc1Y2RhZDFiMDhmMjllN2Q5YzAxZTU5OGUyZGIyZDdiZTE4YjllNWE4NjQ2ZTg3YzYnLFxuICAgIHBhdGg6ICdtJyxcbiAgICB3YWxsZXRTdWJQYXRoOiAnLzAvMCcsXG4gIH07XG4gIGNvbnN0IGJhY2t1cEtleXBhaXIgPSB7XG4gICAgeHBydjogJ3hwcnY5czIxWnJRSDE0M0s0N3NFa0xreWtnWW1xMXhGNVpXclBZaFVaY21CcFBGTVFvanZHVW1FY3I1akZYWUdmcjhDcEZkcFR2aFE3TDlOTjJyTHRzQkZqU2l4M0JBandKY0JqNlUzRDVoeFRQYycsXG4gICAgeHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHYndock5IejdwVldQM25qVjJFaGttZDVOMUFvTmluTEhjNTRwMjVWQWVRRDZxMm9UUzN1dURNRG5mblhudGhiUzl1ZkM4SlZZcE5uV1U1Um4zcFlhTnVMQ055d2t3MScsXG4gICAgcmF3UHViOiAnMDNiYmNiNzM5OTc5NzcwNjhkOWUzNjY2NmJiZDVjZDM3NTc5YWNhZThlMmJkNWNlOWQwYTZlNWMxNTBhNDIzYmMzJyxcbiAgICByYXdQcnY6ICc3N2ExNWYxNDc5NmY0MDAxZDEwOTJhZTg0Zjc2NmJkODY5ZTliZWU2YmZmYWU2NTQ3ZGVmNTA0NWI5NmZhOTQzJyxcbiAgICBwYXRoOiAnbScsXG4gICAgd2FsbGV0U3ViUGF0aDogJy8wLzAnLFxuICB9O1xuICBjb25zdCBiaXRnb0tleSA9IHtcbiAgICB4cHViOiAneHB1YjY2MU15TXdBcVJiY0dRY1ZGaXdjcnRjN2Mzdm9wc1g5NmpzSlVZUGNGTVJFY1JUcUFxc3FidjJaUnlDSkFQTG01Tk1IQ3k4NUUzWndwVDRFQVV3OVdHVTd2TWhHNno4M2hEZUtYQlduNkxmJyxcbiAgICBwYXRoOiAnbScsXG4gICAgd2FsbGV0U3ViUGF0aDogJy8wLzAnLFxuICB9O1xuXG4gIGNvbnN0IGZha2VXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB7XG4gICAgaWQ6ICcyTkNvU2ZISDZMczRDZFRTNVFhaGdDOWs3eDlSZlhlU3dZNCcsXG4gICAgcHJpdmF0ZTogeyBrZXljaGFpbnM6IFt1c2VyS2V5cGFpciwgYmFja3VwS2V5cGFpciwgYml0Z29LZXldIH0sXG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZW5lcmF0ZSBBZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGJlZm9yZSgoKSA9PiBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpKTtcblxuICAgIGl0KCdnZW5lcmF0ZSBmaXJzdCBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaWRBZGRyZXNzID0gZmFrZVdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzAvMCcsIHNlZ3dpdDogZmFsc2UgfSk7XG4gICAgICBpZEFkZHJlc3MuYWRkcmVzcy5zaG91bGQuZXF1YWwoZmFrZVdhbGxldC5pZCgpKTtcbiAgICAgIGlkQWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBpZEFkZHJlc3MuaW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgICAgaWRBZGRyZXNzLmNoYWluUGF0aC5zaG91bGQuZXF1YWwoJy8wLzAnKTtcbiAgICAgIGlkQWRkcmVzcy5wYXRoLnNob3VsZC5lcXVhbCgnLzAvMCcpO1xuICAgICAgaWRBZGRyZXNzLm91dHB1dFNjcmlwdC5zaG91bGQuZXF1YWwoJ2E5MTRkNjgyNDc2ZTliZDU0NDU0YTg4NWY5ZGZmMWU2MDRlOTljZWY0M2RjODcnKTtcbiAgICAgIGlkQWRkcmVzcy5yZWRlZW1TY3JpcHQuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnNTIyMTAyY2QzYzhlNjAwNmE0NjI3NzA1MDIxZDFkMDE2ZDA5N2MyOTQ0ZDk4MTAwYTQ3YmYyZGE2N2E1ZmUxNWFlZWIzNDIxMDJlZTFmYTllODEyZTc3OTM1NmFhM2MzMWViZjMxN2QwY2ZmZWJhYjkyODY0Y2ZlMzhiYWIyMjNlMDgyMGY5OGJjMjEwMjZiYTA1NzUyYmFhNmVhZmQ1YzU2NTlkYTYyYjdmMGFjNTFmZDI4ODZiNjVjMjQxZDBhZmVmMWM0ZmRmYTFjYmM1M2FlJ1xuICAgICAgKTtcbiAgICAgIGlkQWRkcmVzcy53YWxsZXQuc2hvdWxkLmVxdWFsKGZha2VXYWxsZXQuaWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGUgc2Vjb25kIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzEnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgcDJzaEFkZHJlc3MuYWRkcmVzcy5zaG91bGQuZXF1YWwoJzJONXk1UkxWcWRaaTdxcDVQbXpNZFBSNll2UXpVcUJRRldLJyk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBwMnNoQWRkcmVzcy5pbmRleC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpblBhdGguc2hvdWxkLmVxdWFsKCcvMC8xJyk7XG4gICAgICBwMnNoQWRkcmVzcy5wYXRoLnNob3VsZC5lcXVhbCgnLzAvMScpO1xuICAgICAgcDJzaEFkZHJlc3Mub3V0cHV0U2NyaXB0LnNob3VsZC5lcXVhbCgnYTkxNDhiOGJkM2RhNjhlZjBmMjQ2NTUyMzE0NmJkMmRlMzNjODZiOWM4NzE4NycpO1xuICAgICAgcDJzaEFkZHJlc3MucmVkZWVtU2NyaXB0LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzUyMjEwMjcwOWVkYjZhMjE5OGQzNjRjNDg1YTc2Yjk4MWQxMjA2NWVhYmRlOGFhMmQ4NWJkN2U3YTAzNWY3ZWNiMzU3OWIyMTAyYTcyNGVmZWQ0OTljMDVmZGI0ZGExZTEzOTcwMDk1MWZhZTAwYzAwNmIzMjgzODg4YmRmZDFiNDY5NzkyOTIyNDIxMDJiMzJhYmU0NGQ2MTk4NmZmNTdiODM1ZTNiZDE2MjkzZDkzZjMwM2QwZDhmYjA0NTRlMmM5Y2NlZGE1YzQ5Mjk4NTNhZSdcbiAgICAgICk7XG4gICAgICBwMnNoQWRkcmVzcy53YWxsZXQuc2hvdWxkLmVxdWFsKGZha2VXYWxsZXQuaWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGUgY2hhbmdlIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8xLzAnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgcDJzaEFkZHJlc3MuYWRkcmVzcy5zaG91bGQuZXF1YWwoJzJORmo5SnJwWmM1TXlZbkNvdXlSRXR6Tlk0ZW95S1dEZmdQJyk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBwMnNoQWRkcmVzcy5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpblBhdGguc2hvdWxkLmVxdWFsKCcvMS8wJyk7XG4gICAgICBwMnNoQWRkcmVzcy5wYXRoLnNob3VsZC5lcXVhbCgnLzEvMCcpO1xuICAgICAgcDJzaEFkZHJlc3Mub3V0cHV0U2NyaXB0LnNob3VsZC5lcXVhbCgnYTkxNGY2OWE4MWZhZDc1ZWE2NWFkMTY2ZGE3NjUxNTI5MTY3OWE0ZjFhZDg4NycpO1xuICAgICAgcDJzaEFkZHJlc3MucmVkZWVtU2NyaXB0LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzUyMjEwMjBiNGM0Zjg5MWE1NTIwZjVhMGI2ODE4ZDhkNTM5MTk1NTJhMGQ0ZDgwNmI1ZmEwNWM5NzcwODA3OWQ4MzczN2UyMTAyYzVjYzQ5YmYwMzMxZWIwYjA4OTBhN2U3ZDg3ZjdlOWUwZGVhNTE1NDM4MjgwZGM3NjgzNGMyMWQxOThlZmUwODIxMDM3MGU1MmNmNzQxZWJmNDUxMzc0OWQwMjg4MzlkNjk2ODkxZWI3ODliYTdhNTg1OTJjZmJjODU3Y2RjMGE5ZGU3NTNhZSdcbiAgICAgICk7XG4gICAgICBwMnNoQWRkcmVzcy53YWxsZXQuc2hvdWxkLmVxdWFsKGZha2VXYWxsZXQuaWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGUgc2Vnd2l0IGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWd3aXRBZGRyZXNzID0gZmFrZVdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzEwLzAnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBzZWd3aXRBZGRyZXNzLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcyTjVFVmVnUlBXbm1lZDJQcHFEZ2daUHc3RGNORGd1Ull2OCcpO1xuICAgICAgc2Vnd2l0QWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMTApO1xuICAgICAgc2Vnd2l0QWRkcmVzcy5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBzZWd3aXRBZGRyZXNzLmNoYWluUGF0aC5zaG91bGQuZXF1YWwoJy8xMC8wJyk7XG4gICAgICBzZWd3aXRBZGRyZXNzLnBhdGguc2hvdWxkLmVxdWFsKCcvMTAvMCcpO1xuICAgICAgc2Vnd2l0QWRkcmVzcy5vdXRwdXRTY3JpcHQuc2hvdWxkLmVxdWFsKCdhOTE0ODM3ZTJhZGNiNmY2Mzg2ZmVhM2M1ZDQwMzE2YjI4MmNjZjM5MTIxZDg3Jyk7XG4gICAgICBzZWd3aXRBZGRyZXNzLnJlZGVlbVNjcmlwdC5zaG91bGQuZXF1YWwoJzAwMjBhNjJhZmVlMWQyMTFjNWFkYjk3MzlmODFlZDRlMzYzMzBlNmNkYTY1MWM3YmRkMzE0ZTMyY2NjNDY1ZWMyMjAzJyk7XG4gICAgICBzZWd3aXRBZGRyZXNzLndpdG5lc3NTY3JpcHQuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnNTIyMTAyN2IzMDUwNTc3N2E0ZWQ4OTQ3YjA2OWZjYjAxMTZlMjg3OTk1ZDk3Mjc4ZDg0ZGE0ZGI2YzYxMzI3MDY0OWQzZDIxMDM0YzMwZTUxZjFlNjE0Y2FkNjY3ODE1YzkxZDA0MTQwNGMxODIyNWQwYjJmNzllMmMwYmNiNjNmZDI2MDQzMTZiMjEwM2I2NWRkZmMwNjE1OWI2OTE2OTMzOTA3NjFlNzVhMGI4Y2M3YTY1YjZmZjMwNWQwOTRmM2FkOTcyZjE3OTUzZmU1M2FlJ1xuICAgICAgKTtcbiAgICAgIHNlZ3dpdEFkZHJlc3Mud2FsbGV0LnNob3VsZC5lcXVhbChmYWtlV2FsbGV0LmlkKCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ3JlYXRlIFRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBiZ1VybCwgYmdVcmxUZXN0O1xuICAgIGxldCBmYWtlUHJvZFdhbGxldDtcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgICAgY29uc3QgcHJvZEJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAncHJvZCcsIGNsaWVudENvbnN0YW50czogeyBjb25zdGFudHM6IHt9IH0gfSk7XG4gICAgICAvLyBwcm9kQml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbcHJvZEJpdGdvLmdldEVudigpXS51cmk7XG4gICAgICBmYWtlUHJvZFdhbGxldCA9IG5ldyBXYWxsZXQocHJvZEJpdGdvLCB7XG4gICAgICAgIGlkOiAnMk5Db1NmSEg2THM0Q2RUUzVRYWhnQzlrN3g5UmZYZVN3WTQnLFxuICAgICAgICBwcml2YXRlOiB7IGtleWNoYWluczogW3VzZXJLZXlwYWlyLCBiYWNrdXBLZXlwYWlyLCBiaXRnb0tleV0gfSxcbiAgICAgIH0pO1xuICAgICAgYmdVcmxUZXN0ID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2V4dHJhIHVuc3BlbnQgZmV0Y2ggcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmlsbGluZ0FkZHJlc3MgPSAnM0o5OHQxV3BFWjczQ05tUXZpZWNybnlpV3JucVJoV05MeSc7XG4gICAgICBjb25zdCBjdXN0b21VbnNwZW50c0ZldGNoUGFyYW1zID0geyB0ZXN0OiAxMjMgfTtcbiAgICAgIGNvbnN0IHNlbmRBbW91bnQgPSAxZTU7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6IGJpbGxpbmdBZGRyZXNzIH0pO1xuXG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7ZmFrZVByb2RXYWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAucXVlcnkoXG4gICAgICAgICAgXy5tZXJnZShjdXN0b21VbnNwZW50c0ZldGNoUGFyYW1zLCB7XG4gICAgICAgICAgICBzZWd3aXQ6IHRydWUsXG4gICAgICAgICAgICB0YXJnZXQ6IHNlbmRBbW91bnQsXG4gICAgICAgICAgICBtaW5TaXplOiAwLFxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICAgLnJlcGx5KDIwMCwgeyB1bnNwZW50czogW10gfSk7XG5cbiAgICAgIGF3YWl0IGZha2VQcm9kV2FsbGV0XG4gICAgICAgIC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdW5zcGVudHNGZXRjaFBhcmFtczogY3VzdG9tVW5zcGVudHNGZXRjaFBhcmFtcyxcbiAgICAgICAgICByZWNpcGllbnRzOiB7IFtiaWxsaW5nQWRkcmVzc106IHNlbmRBbW91bnQgfSxcbiAgICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJzAgdW5zcGVudHMgYXZhaWxhYmxlIGZvciB0cmFuc2FjdGlvbiBjcmVhdGlvbicpO1xuXG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlZmF1bHQgcDJzaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHAyc2hBZGRyZXNzID0gZmFrZVByb2RXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzEzJywgc2Vnd2l0OiBmYWxzZSB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnQ6IGFueSA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJOQ0VEbW1LTk5ucUt2bld3N3BFM1JMenVGZTVhSEhWeTFYJ10sXG4gICAgICAgIHZhbHVlOiAnMC4wMDUwNDQyMicsXG4gICAgICAgIHZhbHVlX2ludDogNTA0NDIyLFxuICAgICAgICB0eGlkOiAnYjgxNmRlZDg5YzNkOGQ1MDIxYjAxMDk3ZjRhMzEyOWE2YTY4YTVjYjdjODg2ZTk3OTQ1ZjQyMDVjYmE1ZGU0NCcsXG4gICAgICAgIG46IDEsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCBkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogOSxcbiAgICAgICAgaWQ6IDYxMzMwMjI5LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHAyc2hBZGRyZXNzKTtcbiAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgIHVuc3BlbnQudHhfaGFzaCA9IHVuc3BlbnQudHhpZDtcbiAgICAgIHVuc3BlbnQudHhfb3V0cHV0X24gPSB1bnNwZW50Lm47XG4gICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk1zd1Fqa3ZONm9XWWRFN0wyYnJKNWNBQU1qUG1HNTlvY28nIH0pO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgIGNoYW5nZUFkZHJlc3M6IHAyc2hBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgIHVuc3BlbnRzOiBbdW5zcGVudF0sXG4gICAgICAgIHJlY2lwaWVudHM6IHt9LFxuICAgICAgICBub1NwbGl0Q2hhbmdlOiB0cnVlLFxuICAgICAgICBmb3JjZUNoYW5nZUF0RW5kOiB0cnVlLFxuICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgYml0Z29GZWU6IHtcbiAgICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgIH0sXG4gICAgICAgIG9wUmV0dXJuczogeyAnQml0R28gcDJzaCB0ZXN0JzogMTAwMCB9LFxuICAgICAgICB1c2VQc2J0OiBmYWxzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAxNDRkZWE1Y2IwNTQyNWY5NDk3NmU4ODdjY2JhNTY4NmE5YTEyYTNmNDk3MTBiMDIxNTA4ZDNkOWNkOGRlMTZiODAxMDAwMDAwMDBmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDExNmEwZjQyNjk3NDQ3NmYyMDcwMzI3MzY4MjA3NDY1NzM3NDIyYTEwNzAwMDAwMDAwMDAxN2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcwMDAwMDAwMCdcbiAgICAgICk7XG5cbiAgICAgIC8vIGFkZCBmaXJzdCBzaWduYXR1cmVcbiAgICAgIHRyYW5zYWN0aW9uLmtleWNoYWluID0gdXNlcktleXBhaXI7XG4gICAgICBjb25zdCBzaWduYXR1cmUxID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih0cmFuc2FjdGlvbikpIGFzIGFueTtcbiAgICAgIHNpZ25hdHVyZTEudHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMTQ0ZGVhNWNiMDU0MjVmOTQ5NzZlODg3Y2NiYTU2ODZhOWExMmEzZjQ5NzEwYjAyMTUwOGQzZDljZDhkZTE2YjgwMTAwMDAwMGI2MDA0NzMwNDQwMjIwMjFmYTczZDVmZTYxYWM4OTQyY2Q3MGZmNDUwN2M1NzQ2NzdjZTc0N2RlNWJjNDZjM2RkMmUzOGVjMjQ0OGZjZTAyMjA0NzkwNmQyYzAxNTQzMzdhYjk2MDQxZThmYjU4YzI0M2I5YmNlNWY4ODE4ZmE5OTE2NDNjMTI2MGExODU5YWQ4MDEwMDAwNGM2OTUyMjEwMzFjZDIyN2U0MGFkNjFiNGUxMzcxMDljYjI4NDVlYjZmNWE1ODRlZDVjNjdkOWQzMTM1Y2RhYTUwNDVhODQyZWEyMTAzYTJlN2I1NGM3YjJkYTA5OTI1NTUzNTNiOGUyNmM2YWNmZjQyNDhmNDM1MWYwODc4N2JmM2UyZWZjOTRiNjU4MzIxMDI1YzJhNmNkZTMzYzJkNzNjY2YxMmVlY2Y2NGM1NGYwOGY3MjJjMmYwNzM4MjQ0OTg5NTA2OTVlOTg4M2IxNDEyNTNhZWZmZmZmZmZmMDJlODAzMDAwMDAwMDAwMDAwMTE2YTBmNDI2OTc0NDc2ZjIwNzAzMjczNjgyMDc0NjU3Mzc0MjJhMTA3MDAwMDAwMDAwMDE3YTkxNGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTE4NzAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIHNlY29uZCBzaWduYXR1cmVcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4ID0gc2lnbmF0dXJlMS50eDtcbiAgICAgIHRyYW5zYWN0aW9uLmtleWNoYWluID0gYmFja3VwS2V5cGFpcjtcbiAgICAgIHRyYW5zYWN0aW9uLmZ1bGxMb2NhbFNpZ25pbmcgPSB0cnVlO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICAvLyBUaGlzIHRyYW5zYWN0aW9uIGhhcyBhY3R1YWxseSB3b3JrZWQ6IGh0dHBzOi8vdGVzdG5ldC5zbWFydGJpdC5jb20uYXUvdHgvYThjY2I5MjgxNjkwMzJkNmUxZjM3YmY4MWRmZDlhYjZkOTAzNjJhNGY4NGU1NzczOTdmYTY5MGFhNzExNTUwY1xuICAgICAgLy8gTm90ZSB0aGF0IHRoZSB0eCBoZXggYmVsb3cgbm8gbG9uZ2VyIGNvcnJlc3BvbmRzIHRvIHRoZSBhYm92ZSB0cmFuc2FjdGlvbiBiZWNhdXNlIG91ciBmZWUgZXN0aW1hdGlvbiBoYXNcbiAgICAgIC8vIGNoYW5nZWQsIGNoYW5naW5nIHRoZSBvdXRwdXQgYW1vdW50cyBhbmQgdGh1cyB0aGUgdHggaGV4LlxuICAgICAgc2lnbmF0dXJlMi50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAxNDRkZWE1Y2IwNTQyNWY5NDk3NmU4ODdjY2JhNTY4NmE5YTEyYTNmNDk3MTBiMDIxNTA4ZDNkOWNkOGRlMTZiODAxMDAwMDAwZmRmZDAwMDA0NzMwNDQwMjIwMjFmYTczZDVmZTYxYWM4OTQyY2Q3MGZmNDUwN2M1NzQ2NzdjZTc0N2RlNWJjNDZjM2RkMmUzOGVjMjQ0OGZjZTAyMjA0NzkwNmQyYzAxNTQzMzdhYjk2MDQxZThmYjU4YzI0M2I5YmNlNWY4ODE4ZmE5OTE2NDNjMTI2MGExODU5YWQ4MDE0NzMwNDQwMjIwMmFlMDFmMDFiNWFlMGMzZmE3ZDY3YWM3M2RiODE5MzJjYjVhY2ExMGRiMTZhOTkwNjNmZWY0NWUzZjEzOThjZDAyMjA1NTAwMWJhN2UxNjNjYjM1MDkxMGZjNzMyMWVjZDdlYjYzNTliMzIxZDRjMDQ4ODc0ODRkOWM3Mjg0Yjc4YzQ3MDEwMDRjNjk1MjIxMDMxY2QyMjdlNDBhZDYxYjRlMTM3MTA5Y2IyODQ1ZWI2ZjVhNTg0ZWQ1YzY3ZDlkMzEzNWNkYWE1MDQ1YTg0MmVhMjEwM2EyZTdiNTRjN2IyZGEwOTkyNTU1MzUzYjhlMjZjNmFjZmY0MjQ4ZjQzNTFmMDg3ODdiZjNlMmVmYzk0YjY1ODMyMTAyNWMyYTZjZGUzM2MyZDczY2NmMTJlZWNmNjRjNTRmMDhmNzIyYzJmMDczODI0NDk4OTUwNjk1ZTk4ODNiMTQxMjUzYWVmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDExNmEwZjQyNjk3NDQ3NmYyMDcwMzI3MzY4MjA3NDY1NzM3NDIyYTEwNzAwMDAwMDAwMDAxN2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcwMDAwMDAwMCdcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgncDJzaCBQU0JUIHByb2R1Y2VzIHNhbWUgdW5zaWduZWQgdHggYXMgbGVnYWN5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcDJzaEFkZHJlc3MgPSBmYWtlUHJvZFdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzAvMTMnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgY29uc3QgdW5zcGVudDogYW55ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk5DRURtbUtOTm5xS3ZuV3c3cEUzUkx6dUZlNWFISFZ5MVgnXSxcbiAgICAgICAgdmFsdWU6ICcwLjAwNTA0NDIyJyxcbiAgICAgICAgdmFsdWVfaW50OiA1MDQ0MjIsXG4gICAgICAgIHR4aWQ6ICdiODE2ZGVkODljM2Q4ZDUwMjFiMDEwOTdmNGEzMTI5YTZhNjhhNWNiN2M4ODZlOTc5NDVmNDIwNWNiYTVkZTQ0JyxcbiAgICAgICAgbjogMSxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTEgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiA5LFxuICAgICAgICBpZDogNjEzMzAyMjksXG4gICAgICB9O1xuICAgICAgXy5leHRlbmQodW5zcGVudCwgcDJzaEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBwMnNoQWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHAyc2ggdGVzdCc6IDEwMDAgfSxcbiAgICAgIH07XG5cbiAgICAgIC8vIENyZWF0ZSBsZWdhY3kgdHJhbnNhY3Rpb25cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG4gICAgICBjb25zdCBsZWdhY3lUeCA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7IC4uLnR4UGFyYW1zLCB1c2VQc2J0OiBmYWxzZSB9KSkgYXMgYW55O1xuXG4gICAgICAvLyBDcmVhdGUgUFNCVCB0cmFuc2FjdGlvbiAoZXhwbGljaXRseSlcbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG4gICAgICBjb25zdCBwc2J0VHggPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oeyAuLi50eFBhcmFtcywgdXNlUHNidDogdHJ1ZSB9KSkgYXMgYW55O1xuXG4gICAgICAvLyBFeHRyYWN0IHVuc2lnbmVkIHR4IGZyb20gUFNCVCBhbmQgY29tcGFyZVxuICAgICAgY29uc3QgcHNidCA9IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgocHNidFR4LnRyYW5zYWN0aW9uSGV4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgY29uc3QgdW5zaWduZWRUeEZyb21Qc2J0ID0gcHNidC5nZXRVbnNpZ25lZFR4KCkudG9IZXgoKTtcblxuICAgICAgLy8gVGhlIHVuc2lnbmVkIHRyYW5zYWN0aW9uIGhleCBzaG91bGQgYmUgaWRlbnRpY2FsXG4gICAgICBsZWdhY3lUeC50cmFuc2FjdGlvbkhleC5zaG91bGQuZXF1YWwodW5zaWduZWRUeEZyb21Qc2J0KTtcblxuICAgICAgLy8gRmVlcyBzaG91bGQgYWxzbyBtYXRjaFxuICAgICAgbGVnYWN5VHguZmVlLnNob3VsZC5lcXVhbChwc2J0VHguZmVlKTtcblxuICAgICAgLy8gQ2xlYW4gdXAgbm9jayBtb2NrcyB0byBhdm9pZCBpbnRlcmZlcmVuY2Ugd2l0aCBvdGhlciB0ZXN0c1xuICAgICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NlZ3dpdCBQU0JUIHByb2R1Y2VzIHNhbWUgdW5zaWduZWQgdHggYXMgbGVnYWN5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2Vnd2l0QWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMTAvMTMnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTXhLa0g4eUIzUzlZV21UUVJidm1ib3JZUXlRbkg1cGV0UCddLFxuICAgICAgICB2YWx1ZTogJzAuMTg3NTAwMDAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDE4NzUwMDAwLFxuICAgICAgICB0eGlkOiAnN2QyODI4NzhhODVkYWVlNWQ0NmUwNDM4MjdkYWVkNTc1OTZkNzVkMWFhNmUwNGZkMGMwOWEzNmY5MTMwODgxZicsXG4gICAgICAgIG46IDAsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCAzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMxNjE3LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHNlZ3dpdEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBzZWd3aXRBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgIHVuc3BlbnRzOiBbdW5zcGVudF0sXG4gICAgICAgIHJlY2lwaWVudHM6IHt9LFxuICAgICAgICBub1NwbGl0Q2hhbmdlOiB0cnVlLFxuICAgICAgICBmb3JjZUNoYW5nZUF0RW5kOiB0cnVlLFxuICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgYml0Z29GZWU6IHtcbiAgICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgIH0sXG4gICAgICAgIG9wUmV0dXJuczogeyAnQml0R28gc2Vnd2l0IHRlc3QnOiAxMDAwIH0sXG4gICAgICB9O1xuXG4gICAgICAvLyBDcmVhdGUgbGVnYWN5IHRyYW5zYWN0aW9uXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk1zd1Fqa3ZONm9XWWRFN0wyYnJKNWNBQU1qUG1HNTlvY28nIH0pO1xuICAgICAgY29uc3QgbGVnYWN5VHggPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oeyAuLi50eFBhcmFtcywgdXNlUHNidDogZmFsc2UgfSkpIGFzIGFueTtcblxuICAgICAgLy8gQ3JlYXRlIFBTQlQgdHJhbnNhY3Rpb24gKGV4cGxpY2l0bHkpXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk1zd1Fqa3ZONm9XWWRFN0wyYnJKNWNBQU1qUG1HNTlvY28nIH0pO1xuICAgICAgY29uc3QgcHNidFR4ID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHsgLi4udHhQYXJhbXMsIHVzZVBzYnQ6IHRydWUgfSkpIGFzIGFueTtcblxuICAgICAgLy8gRXh0cmFjdCB1bnNpZ25lZCB0eCBmcm9tIFBTQlQgYW5kIGNvbXBhcmVcbiAgICAgIGNvbnN0IHBzYnQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVBzYnRGcm9tSGV4KHBzYnRUeC50cmFuc2FjdGlvbkhleCwgdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHhGcm9tUHNidCA9IHBzYnQuZ2V0VW5zaWduZWRUeCgpLnRvSGV4KCk7XG5cbiAgICAgIC8vIFRoZSB1bnNpZ25lZCB0cmFuc2FjdGlvbiBoZXggc2hvdWxkIGJlIGlkZW50aWNhbFxuICAgICAgbGVnYWN5VHgudHJhbnNhY3Rpb25IZXguc2hvdWxkLmVxdWFsKHVuc2lnbmVkVHhGcm9tUHNidCk7XG5cbiAgICAgIC8vIEZlZXMgc2hvdWxkIGFsc28gbWF0Y2hcbiAgICAgIGxlZ2FjeVR4LmZlZS5zaG91bGQuZXF1YWwocHNidFR4LmZlZSk7XG5cbiAgICAgIC8vIENsZWFuIHVwIG5vY2sgbW9ja3MgdG8gYXZvaWQgaW50ZXJmZXJlbmNlIHdpdGggb3RoZXIgdGVzdHNcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICB9KTtcblxuICAgIGl0KCdwMnNoIHdpdGggUFNCVCBmb3JtYXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMC8xMycsIHNlZ3dpdDogZmFsc2UgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTkNFRG1tS05ObnFLdm5XdzdwRTNSTHp1RmU1YUhIVnkxWCddLFxuICAgICAgICB2YWx1ZTogJzAuMDA1MDQ0MjInLFxuICAgICAgICB2YWx1ZV9pbnQ6IDUwNDQyMixcbiAgICAgICAgdHhpZDogJ2I4MTZkZWQ4OWMzZDhkNTAyMWIwMTA5N2Y0YTMxMjlhNmE2OGE1Y2I3Yzg4NmU5Nzk0NWY0MjA1Y2JhNWRlNDQnLFxuICAgICAgICBuOiAxLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDksXG4gICAgICAgIGlkOiA2MTMzMDIyOSxcbiAgICAgIH07XG4gICAgICBfLmV4dGVuZCh1bnNwZW50LCBwMnNoQWRkcmVzcyk7XG4gICAgICB1bnNwZW50LnZhbHVlID0gdW5zcGVudC52YWx1ZV9pbnQ7XG4gICAgICB1bnNwZW50LnR4X2hhc2ggPSB1bnNwZW50LnR4aWQ7XG4gICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgdW5zcGVudC5zY3JpcHQgPSB1bnNwZW50Lm91dHB1dFNjcmlwdDtcblxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBwMnNoQWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHAyc2ggdGVzdCc6IDEwMDAgfSxcbiAgICAgICAgdXNlUHNidDogdHJ1ZSwgLy8gRXhwbGljaXRseSByZXF1ZXN0IFBTQlQgZm9ybWF0XG4gICAgICB9KSkgYXMgYW55O1xuXG4gICAgICAvLyBWZXJpZnkgUFNCVCBmb3JtYXQgaXMgcmV0dXJuZWQgaW4gdHJhbnNhY3Rpb25IZXhcbiAgICAgIHNob3VsZC5leGlzdCh0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCk7XG4gICAgICBzaG91bGQub2sodXR4b2xpYi5iaXRnby5pc1BzYnQodHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgpKTtcbiAgICAgIHNob3VsZC5ub3QuZXhpc3QodHJhbnNhY3Rpb24udW5zcGVudHMpO1xuXG4gICAgICAvLyBQYXJzZSBhbmQgdmFsaWRhdGUgdGhlIFBTQlRcbiAgICAgIGNvbnN0IHBzYnQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVBzYnRGcm9tSGV4KHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgcHNidC5kYXRhLmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgcHNidC5kYXRhLm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTsgLy8gT1BfUkVUVVJOICsgY2hhbmdlXG5cbiAgICAgIC8vIFZlcmlmeSBpbnB1dCBoYXMgcmVxdWlyZWQgUFNCVCBtZXRhZGF0YVxuICAgICAgY29uc3QgaW5wdXQgPSBwc2J0LmRhdGEuaW5wdXRzWzBdO1xuICAgICAgc2hvdWxkLmV4aXN0KGlucHV0LndpdG5lc3NVdHhvKTtcbiAgICAgIHNob3VsZC5leGlzdChpbnB1dC5yZWRlZW1TY3JpcHQpO1xuICAgICAgc2hvdWxkLmV4aXN0KGlucHV0LmJpcDMyRGVyaXZhdGlvbik7XG4gICAgICBpbnB1dC5iaXAzMkRlcml2YXRpb24hLmxlbmd0aC5zaG91bGQuZXF1YWwoMyk7IC8vIHVzZXIsIGJhY2t1cCwgYml0Z29cblxuICAgICAgLy8gVmVyaWZ5IGdsb2JhbFhwdWJzIGFyZSBzZXRcbiAgICAgIHNob3VsZC5leGlzdChwc2J0LmRhdGEuZ2xvYmFsTWFwLmdsb2JhbFhwdWIpO1xuICAgICAgcHNidC5kYXRhLmdsb2JhbE1hcC5nbG9iYWxYcHViIS5sZW5ndGguc2hvdWxkLmVxdWFsKDMpO1xuXG4gICAgICAvLyBTaWduIHdpdGggdXNlciBrZXkgLSBhdXRvLWRldGVjdHMgUFNCVCBpbiB0cmFuc2FjdGlvbkhleFxuICAgICAgY29uc3Qgc2lnbmVkUmVzdWx0ID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHRyYW5zYWN0aW9uSGV4OiB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCxcbiAgICAgICAga2V5Y2hhaW46IHVzZXJLZXlwYWlyLFxuICAgICAgfSkpIGFzIGFueTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHNpZ25lZFJlc3VsdC50eCk7XG5cbiAgICAgIC8vIFBhcnNlIHNpZ25lZCBQU0JUIGFuZCB2ZXJpZnkgc2lnbmF0dXJlXG4gICAgICBjb25zdCBzaWduZWRQc2J0ID0gdXR4b2xpYi5iaXRnby5jcmVhdGVQc2J0RnJvbUhleChzaWduZWRSZXN1bHQudHgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICBzaG91bGQub2soc2lnbmVkUHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZklucHV0SEQoMCwgdXR4b2xpYi5iaXAzMi5mcm9tQmFzZTU4KHVzZXJLZXlwYWlyLnhwdWIpKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2Vnd2l0IHdpdGggUFNCVCBmb3JtYXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWd3aXRBZGRyZXNzID0gZmFrZVByb2RXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8xMC8xMycsIHNlZ3dpdDogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnQ6IGFueSA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJNeEtrSDh5QjNTOVlXbVRRUmJ2bWJvcllReVFuSDVwZXRQJ10sXG4gICAgICAgIHZhbHVlOiAnMC4xODc1MDAwMCcsXG4gICAgICAgIHZhbHVlX2ludDogMTg3NTAwMDAsXG4gICAgICAgIHR4aWQ6ICc3ZDI4Mjg3OGE4NWRhZWU1ZDQ2ZTA0MzgyN2RhZWQ1NzU5NmQ3NWQxYWE2ZTA0ZmQwYzA5YTM2ZjkxMzA4ODFmJyxcbiAgICAgICAgbjogMCxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIDM3YjM5M2ZjZTYyN2EwZWM2MzRlYjU0M2RkYTFlNjA4ZTJkMWM3OGEgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTQzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICBpZDogNjEzMzE2MTcsXG4gICAgICB9O1xuICAgICAgXy5leHRlbmQodW5zcGVudCwgc2Vnd2l0QWRkcmVzcyk7XG4gICAgICB1bnNwZW50LnZhbHVlID0gdW5zcGVudC52YWx1ZV9pbnQ7XG4gICAgICB1bnNwZW50LnR4X2hhc2ggPSB1bnNwZW50LnR4aWQ7XG4gICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgdW5zcGVudC5zY3JpcHQgPSB1bnNwZW50Lm91dHB1dFNjcmlwdDtcblxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBzZWd3aXRBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgIHVuc3BlbnRzOiBbdW5zcGVudF0sXG4gICAgICAgIHJlY2lwaWVudHM6IHt9LFxuICAgICAgICBub1NwbGl0Q2hhbmdlOiB0cnVlLFxuICAgICAgICBmb3JjZUNoYW5nZUF0RW5kOiB0cnVlLFxuICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgYml0Z29GZWU6IHtcbiAgICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgIH0sXG4gICAgICAgIG9wUmV0dXJuczogeyAnQml0R28gc2Vnd2l0IHRlc3QnOiAxMDAwIH0sXG4gICAgICAgIHVzZVBzYnQ6IHRydWUsIC8vIEV4cGxpY2l0bHkgcmVxdWVzdCBQU0JUIGZvcm1hdFxuICAgICAgfSkpIGFzIGFueTtcblxuICAgICAgLy8gVmVyaWZ5IFBTQlQgZm9ybWF0IGlzIHJldHVybmVkIGluIHRyYW5zYWN0aW9uSGV4XG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgpO1xuICAgICAgc2hvdWxkLm9rKHV0eG9saWIuYml0Z28uaXNQc2J0KHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4KSk7XG5cbiAgICAgIC8vIFBhcnNlIGFuZCB2YWxpZGF0ZSB0aGUgUFNCVFxuICAgICAgY29uc3QgcHNidCA9IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgodHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICBwc2J0LmRhdGEuaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgIC8vIFZlcmlmeSBpbnB1dCBoYXMgc2Vnd2l0IFBTQlQgbWV0YWRhdGFcbiAgICAgIGNvbnN0IGlucHV0ID0gcHNidC5kYXRhLmlucHV0c1swXTtcbiAgICAgIHNob3VsZC5leGlzdChpbnB1dC53aXRuZXNzVXR4byk7XG4gICAgICBzaG91bGQuZXhpc3QoaW5wdXQud2l0bmVzc1NjcmlwdCk7XG4gICAgICBzaG91bGQuZXhpc3QoaW5wdXQucmVkZWVtU2NyaXB0KTtcbiAgICAgIHNob3VsZC5leGlzdChpbnB1dC5iaXAzMkRlcml2YXRpb24pO1xuXG4gICAgICAvLyBTaWduIHdpdGggdXNlciBrZXkgLSBhdXRvLWRldGVjdHMgUFNCVCBpbiB0cmFuc2FjdGlvbkhleFxuICAgICAgY29uc3Qgc2lnbmVkUmVzdWx0ID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHRyYW5zYWN0aW9uSGV4OiB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCxcbiAgICAgICAga2V5Y2hhaW46IHVzZXJLZXlwYWlyLFxuICAgICAgfSkpIGFzIGFueTtcblxuICAgICAgc2hvdWxkLmV4aXN0KHNpZ25lZFJlc3VsdC50eCk7XG5cbiAgICAgIC8vIFBhcnNlIHNpZ25lZCBQU0JUIGFuZCB2ZXJpZnkgc2lnbmF0dXJlXG4gICAgICBjb25zdCBzaWduZWRQc2J0ID0gdXR4b2xpYi5iaXRnby5jcmVhdGVQc2J0RnJvbUhleChzaWduZWRSZXN1bHQudHgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICBzaG91bGQub2soc2lnbmVkUHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZklucHV0SEQoMCwgdXR4b2xpYi5iaXAzMi5mcm9tQmFzZTU4KHVzZXJLZXlwYWlyLnhwdWIpKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnQkNIIHAyc2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMC8xMycsIHNlZ3dpdDogZmFsc2UgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTkNFRG1tS05ObnFLdm5XdzdwRTNSTHp1RmU1YUhIVnkxWCddLFxuICAgICAgICB2YWx1ZTogJzAuMDA1MDQ0MjInLFxuICAgICAgICB2YWx1ZV9pbnQ6IDUwNDQyMixcbiAgICAgICAgdHhpZDogJ2I4MTZkZWQ4OWMzZDhkNTAyMWIwMTA5N2Y0YTMxMjlhNmE2OGE1Y2I3Yzg4NmU5Nzk0NWY0MjA1Y2JhNWRlNDQnLFxuICAgICAgICBuOiAxLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDksXG4gICAgICAgIGlkOiA2MTMzMDIyOSxcbiAgICAgIH07XG4gICAgICBfLmV4dGVuZCh1bnNwZW50LCBwMnNoQWRkcmVzcyk7XG4gICAgICB1bnNwZW50LnZhbHVlID0gdW5zcGVudC52YWx1ZV9pbnQ7XG4gICAgICB1bnNwZW50LnR4X2hhc2ggPSB1bnNwZW50LnR4aWQ7XG4gICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgdW5zcGVudC5zY3JpcHQgPSB1bnNwZW50Lm91dHB1dFNjcmlwdDtcblxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBwMnNoQWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHAyc2ggdGVzdCc6IDEwMDAgfSxcbiAgICAgICAgdXNlUHNidDogZmFsc2UsXG4gICAgICB9KSkgYXMgYW55O1xuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMTQ0ZGVhNWNiMDU0MjVmOTQ5NzZlODg3Y2NiYTU2ODZhOWExMmEzZjQ5NzEwYjAyMTUwOGQzZDljZDhkZTE2YjgwMTAwMDAwMDAwZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMTZhMGY0MjY5NzQ0NzZmMjA3MDMyNzM2ODIwNzQ2NTczNzQyMmExMDcwMDAwMDAwMDAwMTdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3MDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgZmlyc3Qgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IHVzZXJLZXlwYWlyO1xuICAgICAgdHJhbnNhY3Rpb24uZm9yY2VCQ0ggPSB0cnVlO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMSA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICBzaWduYXR1cmUxLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDE0NGRlYTVjYjA1NDI1Zjk0OTc2ZTg4N2NjYmE1Njg2YTlhMTJhM2Y0OTcxMGIwMjE1MDhkM2Q5Y2Q4ZGUxNmI4MDEwMDAwMDBiNjAwNDczMDQ0MDIyMDYyMjFhOTdmMDgxZDg3ZTAyZTNiMTQ5ODhhNjQ4NjE4MTFhNmE4ZGU0ZjExZjc0ZjVhYWVhNDU5ODFjZjYxMmUwMjIwNzdhMDhhNWJkN2Q3ODFlNzk4MzhhZmJiMTI2YWYyZTQ4ODAyZmVmYWQ2NjBhZmRiZDg4MDVmNWU1OThlZDU4ODQxMDAwMDRjNjk1MjIxMDMxY2QyMjdlNDBhZDYxYjRlMTM3MTA5Y2IyODQ1ZWI2ZjVhNTg0ZWQ1YzY3ZDlkMzEzNWNkYWE1MDQ1YTg0MmVhMjEwM2EyZTdiNTRjN2IyZGEwOTkyNTU1MzUzYjhlMjZjNmFjZmY0MjQ4ZjQzNTFmMDg3ODdiZjNlMmVmYzk0YjY1ODMyMTAyNWMyYTZjZGUzM2MyZDczY2NmMTJlZWNmNjRjNTRmMDhmNzIyYzJmMDczODI0NDk4OTUwNjk1ZTk4ODNiMTQxMjUzYWVmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDExNmEwZjQyNjk3NDQ3NmYyMDcwMzI3MzY4MjA3NDY1NzM3NDIyYTEwNzAwMDAwMDAwMDAxN2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcwMDAwMDAwMCdcbiAgICAgICk7XG4gICAgICAvLyBhZGQgc2Vjb25kIHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXggPSBzaWduYXR1cmUxLnR4O1xuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSBiYWNrdXBLZXlwYWlyO1xuICAgICAgdHJhbnNhY3Rpb24uZnVsbExvY2FsU2lnbmluZyA9IHRydWU7XG4gICAgICBjb25zdCBzaWduYXR1cmUyID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih0cmFuc2FjdGlvbikpIGFzIGFueTtcbiAgICAgIC8vIHRoaXMgdHJhbnNhY3Rpb24gaGFzIGFjdHVhbGx5IHdvcmtlZDogaHR0cHM6Ly90ZXN0bmV0LnNtYXJ0Yml0LmNvbS5hdS90eC9hOGNjYjkyODE2OTAzMmQ2ZTFmMzdiZjgxZGZkOWFiNmQ5MDM2MmE0Zjg0ZTU3NzM5N2ZhNjkwYWE3MTE1NTBjXG4gICAgICAvLyBOb3RlIHRoYXQgdGhlIHR4IGhleCBiZWxvdyBubyBsb25nZXIgY29ycmVzcG9uZHMgdG8gdGhlIGFib3ZlIHRyYW5zYWN0aW9uIGJlY2F1c2Ugb3VyIGZlZSBlc3RpbWF0aW9uIGhhc1xuICAgICAgLy8gY2hhbmdlZCwgY2hhbmdpbmcgdGhlIG91dHB1dCBhbW91bnRzIGFuZCB0aHVzIHRoZSB0eCBoZXguXG4gICAgICBzaWduYXR1cmUyLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDE0NGRlYTVjYjA1NDI1Zjk0OTc2ZTg4N2NjYmE1Njg2YTlhMTJhM2Y0OTcxMGIwMjE1MDhkM2Q5Y2Q4ZGUxNmI4MDEwMDAwMDBmZGZlMDAwMDQ3MzA0NDAyMjA2MjIxYTk3ZjA4MWQ4N2UwMmUzYjE0OTg4YTY0ODYxODExYTZhOGRlNGYxMWY3NGY1YWFlYTQ1OTgxY2Y2MTJlMDIyMDc3YTA4YTViZDdkNzgxZTc5ODM4YWZiYjEyNmFmMmU0ODgwMmZlZmFkNjYwYWZkYmQ4ODA1ZjVlNTk4ZWQ1ODg0MTQ4MzA0NTAyMjEwMDgyYmM1NDYyOTM4NTg0NTlmMzg5NWRiMjRjODVjY2YzNzUwNWM1NmY4ZmFmNGJiOGY3OGNmNDAxMzViYzJmMmIwMjIwM2RjMWM3OGQ3YzdjZWFmNmI5MjRlY2EzYzM5Yjk1ZThhMjI3YjA2OWEwNzA0NzU4MTI3MzEzNmI0N2NhN2FjNDQxMDA0YzY5NTIyMTAzMWNkMjI3ZTQwYWQ2MWI0ZTEzNzEwOWNiMjg0NWViNmY1YTU4NGVkNWM2N2Q5ZDMxMzVjZGFhNTA0NWE4NDJlYTIxMDNhMmU3YjU0YzdiMmRhMDk5MjU1NTM1M2I4ZTI2YzZhY2ZmNDI0OGY0MzUxZjA4Nzg3YmYzZTJlZmM5NGI2NTgzMjEwMjVjMmE2Y2RlMzNjMmQ3M2NjZjEyZWVjZjY0YzU0ZjA4ZjcyMmMyZjA3MzgyNDQ5ODk1MDY5NWU5ODgzYjE0MTI1M2FlZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMTZhMGY0MjY5NzQ0NzZmMjA3MDMyNzM2ODIwNzQ2NTczNzQyMmExMDcwMDAwMDAwMDAwMTdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3MDAwMDAwMDAnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlZmF1bHQgc2Vnd2l0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2Vnd2l0QWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMTAvMTMnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTXhLa0g4eUIzUzlZV21UUVJidm1ib3JZUXlRbkg1cGV0UCddLFxuICAgICAgICB2YWx1ZTogJzAuMTg3NTAwMDAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDE4NzUwMDAwLFxuICAgICAgICB0eGlkOiAnN2QyODI4NzhhODVkYWVlNWQ0NmUwNDM4MjdkYWVkNTc1OTZkNzVkMWFhNmUwNGZkMGMwOWEzNmY5MTMwODgxZicsXG4gICAgICAgIG46IDAsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCAzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMxNjE3LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHNlZ3dpdEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogc2Vnd2l0QWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHNlZ3dpdCB0ZXN0JzogMTAwMCB9LFxuICAgICAgICB1c2VQc2J0OiBmYWxzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAxMWY4ODMwOTE2ZmEzMDkwY2ZkMDQ2ZWFhZDE3NTZkNTk1N2VkZGEyNzM4MDQ2ZWQ0ZTVhZTVkYTg3ODI4Mjg3ZDAwMDAwMDAwMDBmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDEzNmExMTQyNjk3NDQ3NmYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzQwZTBmMWUwMTAwMDAwMDAwMTdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3MDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgZmlyc3Qgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IHVzZXJLZXlwYWlyO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMSA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICBzaWduYXR1cmUxLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDAwMTAxMWY4ODMwOTE2ZmEzMDkwY2ZkMDQ2ZWFhZDE3NTZkNTk1N2VkZGEyNzM4MDQ2ZWQ0ZTVhZTVkYTg3ODI4Mjg3ZDAwMDAwMDAwMjMyMjAwMjA0NDBlODU4MjI4Yjc1MzU0NGI0YzU3ZTMwMDI5NmI1NTcxN2Y4MTEwNTM4ODNmOWJlOWI2YTcxMmVhY2Q5MzFjZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMzZhMTE0MjY5NzQ0NzZmMjA3MzY1Njc3NzY5NzQyMDc0NjU3Mzc0MGUwZjFlMDEwMDAwMDAwMDE3YTkxNDM3YjM5M2ZjZTYyN2EwZWM2MzRlYjU0M2RkYTFlNjA4ZTJkMWM3OGE4NzA1MDA0ODMwNDUwMjIxMDBiZjNhODkxNGExYmZlOTI2NjFmMjdjYTM3YzBkNmI1YzBiM2M3MzUzNjE0Yzk1NTY0NjkyOWYyZTdlYjg5ZmZlMDIyMDJkNTU2YjBmZmFiMzdjMTA0YmFlNjc0MDZjYTE2Zjg4NTljZmEzN2M2YTQwZjIwMTNkODlhZmNlY2Q1NTk0ZjMwMTAwMDA2OTUyMjEwMzJjNTA1ZmM4YTFlNGI1NjgxMWIyNzM2NmEzNzFlNjFjOWZhZjU2NWRkMmZhYmFmZjdhNzBlYWMxOWMzMjE1N2MyMTAyNTExNjBiNTgzYmQ1ZGMwZjBkNDgwOTY1MDUxMzFjNDM0N2FiNjViNGYyMWVkNTdkNzZjMzgxNTc0OTljMDAzZDIxMDI2Nzk3MTJkNjJhMjU2MDkxN2NjNDNmZDJjYzNhMWI5YjYxZjUyOGM4OGJjNjQ5MDViYWU2ZWUwNzllNjA2MDlmNTNhZTAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIHNlY29uZCBzaWduYXR1cmVcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4ID0gc2lnbmF0dXJlMS50eDtcbiAgICAgIHRyYW5zYWN0aW9uLmtleWNoYWluID0gYmFja3VwS2V5cGFpcjtcbiAgICAgIHRyYW5zYWN0aW9uLmZ1bGxMb2NhbFNpZ25pbmcgPSB0cnVlO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICAvLyB0aGlzIHRyYW5zYWN0aW9uIGhhcyBhY3R1YWxseSB3b3JrZWQ6IGh0dHBzOi8vdGVzdG5ldC5zbWFydGJpdC5jb20uYXUvdHgvZDY3MjY2ZjFkZTkwNWJhYWVlNzUwMDExZmE0YjNkODhhOGUzYTE3NThkNTE3M2E2NTljNjc3MDk0ODhkZGUwN1xuICAgICAgLy8gTm90ZSB0aGF0IHRoZSB0eCBoZXggYmVsb3cgbm8gbG9uZ2VyIGNvcnJlc3BvbmRzIHRvIHRoZSBhYm92ZSB0cmFuc2FjdGlvbiBiZWNhdXNlIG91ciBmZWUgZXN0aW1hdGlvbiBoYXNcbiAgICAgIC8vIGNoYW5nZWQsIGNoYW5naW5nIHRoZSBvdXRwdXQgYW1vdW50cyBhbmQgdGh1cyB0aGUgdHggaGV4LlxuICAgICAgc2lnbmF0dXJlMi50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAwMDEwMTFmODgzMDkxNmZhMzA5MGNmZDA0NmVhYWQxNzU2ZDU5NTdlZGRhMjczODA0NmVkNGU1YWU1ZGE4NzgyODI4N2QwMDAwMDAwMDIzMjIwMDIwNDQwZTg1ODIyOGI3NTM1NDRiNGM1N2UzMDAyOTZiNTU3MTdmODExMDUzODgzZjliZTliNmE3MTJlYWNkOTMxY2ZmZmZmZmZmMDJlODAzMDAwMDAwMDAwMDAwMTM2YTExNDI2OTc0NDc2ZjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NDBlMGYxZTAxMDAwMDAwMDAxN2E5MTQzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhODcwNTAwNDgzMDQ1MDIyMTAwYmYzYTg5MTRhMWJmZTkyNjYxZjI3Y2EzN2MwZDZiNWMwYjNjNzM1MzYxNGM5NTU2NDY5MjlmMmU3ZWI4OWZmZTAyMjAyZDU1NmIwZmZhYjM3YzEwNGJhZTY3NDA2Y2ExNmY4ODU5Y2ZhMzdjNmE0MGYyMDEzZDg5YWZjZWNkNTU5NGYzMDE0NzMwNDQwMjIwNWNmOGQyZjJiZTZjZTA4M2QzNTY1NGJkYzNmYTg1ZDdlNzFiMjI3ZDQ1N2U5MjQ1YmI2MDNiMjFlN2I1MTY1MTAyMjAzZWE2ODYyMjZkYjgzMjBlMDhjMjZiZmIzMDQwNDhiM2E5NDczZDBlMDU3OTdkMzY1OGRhY2IyZjA5YTJiNTFjMDEwMDY5NTIyMTAzMmM1MDVmYzhhMWU0YjU2ODExYjI3MzY2YTM3MWU2MWM5ZmFmNTY1ZGQyZmFiYWZmN2E3MGVhYzE5YzMyMTU3YzIxMDI1MTE2MGI1ODNiZDVkYzBmMGQ0ODA5NjUwNTEzMWM0MzQ3YWI2NWI0ZjIxZWQ1N2Q3NmMzODE1NzQ5OWMwMDNkMjEwMjY3OTcxMmQ2MmEyNTYwOTE3Y2M0M2ZkMmNjM2ExYjliNjFmNTI4Yzg4YmM2NDkwNWJhZTZlZTA3OWU2MDYwOWY1M2FlMDAwMDAwMDAnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2NyZWF0ZXMgYW4gdW5zaWduZWQgdHggbWFkZSBvZiB1bmNvbXByZXNzZWQgcHVibGljIGtleXMgb2YgdjEgc2FmZSB3YWxsZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB7IGFkZHJlc3MsIHJlZGVlbVNjcmlwdCwgc2NyaXB0UHViS2V5IH0gPSBhd2FpdCBnZXRGaXh0dXJlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgICAgICAgYCR7X19kaXJuYW1lfS9maXh0dXJlcy9zaWduLXRyYW5zYWN0aW9uLmpzb25gXG4gICAgICApO1xuICAgICAgY29uc3QgdGVzdEJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAndGVzdCcsIGNsaWVudENvbnN0YW50czogeyBjb25zdGFudHM6IHt9IH0gfSk7XG4gICAgICBjb25zdCBmYWtlVGVzdFYxU2FmZVdhbGxldCA9IG5ldyBXYWxsZXQodGVzdEJpdGdvLCB7XG4gICAgICAgIGlkOiBhZGRyZXNzLFxuICAgICAgICBwcml2YXRlOiB7IHNhZmU6IHsgcmVkZWVtU2NyaXB0IH0gfSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdW5zcGVudHNUb1NwZW5kID0gW1xuICAgICAgICB7XG4gICAgICAgICAgdmFsdWU6IDEwMDAwMCxcbiAgICAgICAgICByZWRlZW1TY3JpcHQsXG4gICAgICAgICAgc2NyaXB0OiBzY3JpcHRQdWJLZXksXG4gICAgICAgICAgdHhfaGFzaDogJ2E1NWQxMWRjOGI3MDFiZDE5NjAxZmJmZTcxMWExZTQ2NWZjOGYxMjhlYzQ0NzRlNzhlMWZkMDg3ZTgwOGU1ZmUnLFxuICAgICAgICAgIHR4X291dHB1dF9uOiAwLFxuICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDEsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogMTAwMDAwLFxuICAgICAgICAgIHJlZGVlbVNjcmlwdCxcbiAgICAgICAgICBzY3JpcHQ6IHNjcmlwdFB1YktleSxcbiAgICAgICAgICB0eF9oYXNoOiAnNDhmYjg3OWNlYzg3OTM1NjA0NWEzMzE5MzcwMjNhZWQ4NTlmNWRjNWRiOTU1YTFkYzhhNWNjZjI5ZjQ5ZDEwOCcsXG4gICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgY29uZmlybWF0aW9uczogMSxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCByZWNpcGllbnRzID0ge1xuICAgICAgICAnMk15R3hyaExDNGtSZnVWakxxQ1ZZRnRDN0RjaGhnTUNpTnonOiAxOTEzNDAsIC8vIHB1cnBvc2VseSBzZXQgdG8gc2ltdWxhdGUgYSBzd2VlcCB0cmFuc2FjdGlvblxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKGJnVXJsVGVzdClcbiAgICAgICAgLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJylcbiAgICAgICAgLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk4zTDljdTlXTjJEZjdYdmIxWThvd29rdURWajVIZHl2NGknIH0pO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmYWtlVGVzdFYxU2FmZVdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgIHJlY2lwaWVudHMsXG4gICAgICAgIHVuc3BlbnRzOiB1bnNwZW50c1RvU3BlbmQsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLCAvLyAxMCBzYXQvYnl0ZVxuICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgICBhZGRyZXNzOiAnJyxcbiAgICAgICAgfSxcbiAgICAgICAgdXNlUHNidDogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgc2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcblxuICAgICAgcmVzdWx0LmVzdGltYXRlZFNpemUuc2hvdWxkLmVxdWFsKDg2Nik7XG4gICAgICByZXN1bHQuZmVlLnNob3VsZC5lcXVhbCg4NjYwKTtcbiAgICAgIC8vIFRoaXMgc2hvdWxkIGVxdWFsIHRvIDEgYmVjYXVzZSB0aGlzIGlzIGEgc3dlZXAgdHJhbnNhY3Rpb24gYnV0IGR1ZSB0byBoYXJkY29kZWQgYWRkaXRpb24gb2ZcbiAgICAgIC8vIDEgY2hhbmdlIG91dHB1dCBpbiB0cmFuc2FjdGlvbkJ1aWxkZXIsIGl0IGlzIDIuXG4gICAgICAvLyBCZWNhdXNlIG9mIHRoaXMgdGhlIGVzdGltYXRlZCBzaXplIG9mIHRoZSB0cmFuc2FjdGlvbnMgaXMgbW9yZSB0aGFuIHdoYXQgaXQgYWN0dWFsbHkgaXMgaW4gdGhlIGhleC5cbiAgICAgIHJlc3VsdC50eEluZm8ubk91dHB1dHMuc2hvdWxkLmVxdWFsKDIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NpZ25zIGFuIHVuc2lnbmVkIHR4IG1hZGUgb2YgdW5jb21wcmVzc2VkIHB1YmxpYyBrZXlzIG9mIHYxIHNhZmUgd2FsbGV0ICYgdmVyaWZpZXMgc2lnbmF0dXJlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgcmVkZWVtU2NyaXB0LFxuICAgICAgICBzY3JpcHRQdWJLZXksXG4gICAgICAgIHVzZXJLZXlXSUY6IHVzZXJTaWduaW5nS2V5LFxuICAgICAgICBiaXRnb0tleVdJRjogYml0Z29TaWduaW5nS2V5LFxuICAgICAgICB1bnNpZ25lZFR4SGV4LFxuICAgICAgICBoYWxmU2lnbmVkVHhIZXgsXG4gICAgICAgIGZ1bGxTaWduZWRUeEhleCxcbiAgICAgIH0gPSBhd2FpdCBnZXRGaXh0dXJlPFJlY29yZDxzdHJpbmcsIHVua25vd24+PihgJHtfX2Rpcm5hbWV9L2ZpeHR1cmVzL3NpZ24tdHJhbnNhY3Rpb24uanNvbmApO1xuICAgICAgY29uc3QgdGVzdEJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAndGVzdCcsIGNsaWVudENvbnN0YW50czogeyBjb25zdGFudHM6IHt9IH0gfSk7XG4gICAgICBjb25zdCBmYWtlVGVzdFYxU2FmZVdhbGxldCA9IG5ldyBXYWxsZXQodGVzdEJpdGdvLCB7XG4gICAgICAgIGlkOiBhZGRyZXNzLFxuICAgICAgICBwcml2YXRlOiB7IHNhZmU6IHsgcmVkZWVtU2NyaXB0IH0gfSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdW5zcGVudHNUb1NwZW5kID0gW1xuICAgICAgICB7IHZhbHVlOiAxMDAwMDAsIHJlZGVlbVNjcmlwdCwgc2NyaXB0OiBzY3JpcHRQdWJLZXkgfSxcbiAgICAgICAgeyB2YWx1ZTogMTAwMDAwLCByZWRlZW1TY3JpcHQsIHNjcmlwdDogc2NyaXB0UHViS2V5IH0sXG4gICAgICBdO1xuICAgICAgY29uc3QgaGFsZlNpZ25lZFR4ID0gYXdhaXQgZmFrZVRlc3RWMVNhZmVXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHJhbnNhY3Rpb25IZXg6IHVuc2lnbmVkVHhIZXgsXG4gICAgICAgIHNpZ25pbmdLZXk6IHVzZXJTaWduaW5nS2V5LFxuICAgICAgICB1bnNwZW50czogdW5zcGVudHNUb1NwZW5kLFxuICAgICAgICB2YWxpZGF0ZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgaGFsZlNpZ25lZFR4LnR4LnNob3VsZC5lcXVhbChoYWxmU2lnbmVkVHhIZXgpO1xuXG4gICAgICBjb25zdCBmdWxsU2lnbmVkVHggPSBhd2FpdCBmYWtlVGVzdFYxU2FmZVdhbGxldC5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0cmFuc2FjdGlvbkhleDogaGFsZlNpZ25lZFR4SGV4LFxuICAgICAgICBzaWduaW5nS2V5OiBiaXRnb1NpZ25pbmdLZXksXG4gICAgICAgIHVuc3BlbnRzOiB1bnNwZW50c1RvU3BlbmQsXG4gICAgICAgIHZhbGlkYXRlOiB0cnVlLFxuICAgICAgICBmdWxsTG9jYWxTaWduaW5nOiB0cnVlLFxuICAgICAgfSk7XG4gICAgICAvLyBVcG9uIGNhbGxpbmcgdHhiLmJ1aWxkKCkgaW5zdGVhZCBhZnRlciBnZXR0aW5nIDIgdmFsaWQgc2lnbmF0dXJlcywgd2UgZ2V0IGEgdmFsaWQgZnVsbCBzaWduZWQgdHggdGhhdCB3YXMgYnJvYWRjYXN0XG4gICAgICAvLyBhbmQgY29uZmlybWVkIG9uIHRlc3RuZXQgaGVyZTogaHR0cHM6Ly9tZW1wb29sLnNwYWNlL3Rlc3RuZXQvdHgvYmRlMDlmMWJkNWU2NjYxYzI4ZDkwZTRjOTYyOTE4NTNlMjFiYTE1YWI0MmYzZTRhMzA3MTlkZWNiNzNlNzkxYlxuICAgICAgLy8gSXQncyBwcmVzZW50IGluIHRoZSBmdWxsU2lnbmVkVHhIZXhCdWlsZENvbXBsZXRlIHByb3BlcnR5IG9mIHRoZSBmaXh0dXJlLlxuICAgICAgZnVsbFNpZ25lZFR4LnR4LnNob3VsZC5lcXVhbChmdWxsU2lnbmVkVHhIZXgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ0JDSCBzZWd3aXQgc2hvdWxkIGZhaWwnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWd3aXRBZGRyZXNzID0gZmFrZVByb2RXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8xMC8xMycsIHNlZ3dpdDogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnQ6IGFueSA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJNeEtrSDh5QjNTOVlXbVRRUmJ2bWJvcllReVFuSDVwZXRQJ10sXG4gICAgICAgIHZhbHVlOiAnMC4xODc1MDAwMCcsXG4gICAgICAgIHZhbHVlX2ludDogMTg3NTAwMDAsXG4gICAgICAgIHR4aWQ6ICc3ZDI4Mjg3OGE4NWRhZWU1ZDQ2ZTA0MzgyN2RhZWQ1NzU5NmQ3NWQxYWE2ZTA0ZmQwYzA5YTM2ZjkxMzA4ODFmJyxcbiAgICAgICAgbjogMCxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIDM3YjM5M2ZjZTYyN2EwZWM2MzRlYjU0M2RkYTFlNjA4ZTJkMWM3OGEgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTQzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICBpZDogNjEzMzE2MTcsXG4gICAgICB9O1xuICAgICAgXy5leHRlbmQodW5zcGVudCwgc2Vnd2l0QWRkcmVzcyk7XG4gICAgICB1bnNwZW50LnZhbHVlID0gdW5zcGVudC52YWx1ZV9pbnQ7XG4gICAgICB1bnNwZW50LnR4X2hhc2ggPSB1bnNwZW50LnR4aWQ7XG4gICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgdW5zcGVudC5zY3JpcHQgPSB1bnNwZW50Lm91dHB1dFNjcmlwdDtcblxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBzZWd3aXRBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgIHVuc3BlbnRzOiBbdW5zcGVudF0sXG4gICAgICAgIHJlY2lwaWVudHM6IHt9LFxuICAgICAgICBub1NwbGl0Q2hhbmdlOiB0cnVlLFxuICAgICAgICBmb3JjZUNoYW5nZUF0RW5kOiB0cnVlLFxuICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgYml0Z29GZWU6IHtcbiAgICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgIH0sXG4gICAgICAgIG9wUmV0dXJuczogeyAnQml0R28gc2Vnd2l0IHRlc3QnOiAxMDAwIH0sXG4gICAgICAgIHVzZVBzYnQ6IGZhbHNlLFxuICAgICAgfSkpIGFzIGFueTtcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDExZjg4MzA5MTZmYTMwOTBjZmQwNDZlYWFkMTc1NmQ1OTU3ZWRkYTI3MzgwNDZlZDRlNWFlNWRhODc4MjgyODdkMDAwMDAwMDAwMGZmZmZmZmZmMDJlODAzMDAwMDAwMDAwMDAwMTM2YTExNDI2OTc0NDc2ZjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NDBlMGYxZTAxMDAwMDAwMDAxN2E5MTQzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhODcwMDAwMDAwMCdcbiAgICAgICk7XG5cbiAgICAgIC8vIGFkZCBmaXJzdCBzaWduYXR1cmVcbiAgICAgIHRyYW5zYWN0aW9uLmtleWNoYWluID0gdXNlcktleXBhaXI7XG4gICAgICB0cmFuc2FjdGlvbi5mb3JjZUJDSCA9IHRydWU7XG4gICAgICAoKCkgPT4gZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkuc2hvdWxkLnRocm93KCdCQ0ggZG9lcyBub3Qgc3VwcG9ydCBzZWd3aXQgaW5wdXRzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnbWl4ZWQgcDJzaCAmIHNlZ3dpdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHAyc2hBZGRyZXNzID0gZmFrZVdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzAvMTQnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgY29uc3Qgc2Vnd2l0QWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8xMC8xNCcsIHNlZ3dpdDogdHJ1ZSB9KTtcbiAgICAgIGNvbnN0IHAyc2hVbnNwZW50ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk41MzNmcWd5UFlLVkQ4OTJuQlJhWW1GSGJiVHlraFlTRXcnXSxcbiAgICAgICAgdmFsdWU6ICcyLjk5OTk2NjEwJyxcbiAgICAgICAgdmFsdWVfaW50OiAyOTk5OTY2MTAsXG4gICAgICAgIHR4aWQ6ICdmNjU0Y2UwYTViZTNmMTJkZjdmZWNmNGVlNzc3YjZkODZiNWFhOGM3MTBlZjY5NDZlYzEyMTIwNmI0Zjg3NTdjJyxcbiAgICAgICAgbjogMSxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIDgxNTNlN2EzNTUwODA4OGI2Y2Y1OTkyMjY3OTJjN2RlMmRiZmYyNTIgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTQ4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICBpZDogNjEzMzEyNjMsXG4gICAgICB9O1xuICAgICAgY29uc3Qgc2Vnd2l0VW5zcGVudCA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJOQnRwWGNEcnVmM3pSdXRtRjRBYkNNRk5RSFhzR05QNmtUJ10sXG4gICAgICAgIHZhbHVlOiAnMS41MDAwMDAwMCcsXG4gICAgICAgIHZhbHVlX2ludDogMTUwMDAwMDAwLFxuICAgICAgICB0eGlkOiAnYTQ0MDljM2YwNDJmYWU2N2I4OTBhYzNkZjQwZWYwZGIwMzUzOWM2NzMzMWZkN2U5MjYwNTExODkzYjRmOWYyNCcsXG4gICAgICAgIG46IDAsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCBjYzhlN2NiZjQ4MTM4OWQzMTgzYTU5MGFjZmE2YWE2NmViOTdjOGUxIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0Y2M4ZTdjYmY0ODEzODlkMzE4M2E1OTBhY2ZhNmFhNjZlYjk3YzhlMTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMwODgyLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGFkZHJlc3NlcyA9IFtwMnNoQWRkcmVzcywgc2Vnd2l0QWRkcmVzc107XG4gICAgICBjb25zdCB1bnNwZW50cyA9IFtwMnNoVW5zcGVudCwgc2Vnd2l0VW5zcGVudF0ubWFwKCh1bnNwZW50OiBhbnksIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IGFkZHJlc3MgPSBhZGRyZXNzZXNbaW5kZXhdO1xuICAgICAgICBfLmV4dGVuZCh1bnNwZW50LCBhZGRyZXNzKTtcbiAgICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgICB1bnNwZW50LnR4X2hhc2ggPSB1bnNwZW50LnR4aWQ7XG4gICAgICAgIHVuc3BlbnQudHhfb3V0cHV0X24gPSB1bnNwZW50Lm47XG4gICAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG4gICAgICAgIHJldHVybiB1bnNwZW50O1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGZha2VXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBwMnNoQWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogdW5zcGVudHMsXG4gICAgICAgIHJlY2lwaWVudHM6IHt9LFxuICAgICAgICBub1NwbGl0Q2hhbmdlOiB0cnVlLFxuICAgICAgICBmb3JjZUNoYW5nZUF0RW5kOiB0cnVlLFxuICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgb3BSZXR1cm5zOiB7ICdCaXRHbyBtaXhlZCBwMnNoICYgc2Vnd2l0IHRlc3QnOiA0MDAwMDAwMDAgfSxcbiAgICAgICAgYml0Z29GZWU6IHtcbiAgICAgICAgICBhbW91bnQ6IDgxNzYwLFxuICAgICAgICAgIGFkZHJlc3M6ICcyTkQ3alFSNWl0akdUYmgzREtnYnBaV1NZOXVuZ0Ryd2N3YicsXG4gICAgICAgIH0sXG4gICAgICAgIHVzZVBzYnQ6IGZhbHNlLFxuICAgICAgfSkpIGFzIGFueTtcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDI3Yzc1ZjhiNDA2MTIxMmVjNDY2OWVmMTBjN2E4NWE2YmQ4YjY3N2U3NGVjZmZlZjcyZGYxZTM1YjBhY2U1NGY2MDEwMDAwMDAwMGZmZmZmZmZmMjQ5ZjRmM2I4OTExMDUyNmU5ZDcxZjMzNjc5YzUzMDNkYmYwMGVmNDNkYWM5MGI4NjdhZTJmMDQzZjljNDBhNDAwMDAwMDAwMDBmZmZmZmZmZjAzMDA4NGQ3MTcwMDAwMDAwMDIwNmExZTQyNjk3NDQ3NmYyMDZkNjk3ODY1NjQyMDcwMzI3MzY4MjAyNjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NGIwOGZmOTAyMDAwMDAwMDAxN2E5MTQ4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyODc2MDNmMDEwMDAwMDAwMDAwMTdhOTE0ZDlmN2JlNDc5NzVjMDM2Zjk0MjI4YjBiZmQ3MDcwMTkxMjc1OGJhOTg3MDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgZmlyc3Qgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IHVzZXJLZXlwYWlyO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMSA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICBzaWduYXR1cmUxLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDAwMTAyN2M3NWY4YjQwNjEyMTJlYzQ2NjllZjEwYzdhODVhNmJkOGI2NzdlNzRlY2ZmZWY3MmRmMWUzNWIwYWNlNTRmNjAxMDAwMDAwYjcwMDQ4MzA0NTAyMjEwMGZmYzQ1ZDkzY2JhZjRjMWM4NTBlMjFmMjc3YzViMzExZDNlMzk1N2YxMzM4OTU1Y2IxNjVkNzJhNzY4YTA1NGMwMjIwNTIwMjA1OTNiMzY3ODFlZWEwMGE5ZjhkY2JlYjc2NjA4ZjkyMGM3YTkzM2E5MDg4MzE4YWIyZjcwYzExZTFkOTAxMDAwMDRjNjk1MjIxMDNkYTk1YjI4YTEzYWEyZDRiYjQ5MGQ3MDYyOGUyZTVkOTEyNDYxZDM3NWZlZjM4MWFhZGQ4OWRjMTI1NjIyMDc1MjEwMzEyMTI4N2E1MTBjNWYzMmU4YmE3MmQyNDc5ZTkwZWI1MmJhNDRhNDY3MTczZGYzMzlmZWIwZmYyMTVmMTAwZTMyMTAyOTc3Y2RmYmVlNzYwNjZhZTczOWRiNzJkNTUzNzFhZDQ5ZGM2NzEyZmI4ZjJmM2Y2OWJiMWE0YzI0MjJiMGIxYTUzYWVmZmZmZmZmZjI0OWY0ZjNiODkxMTA1MjZlOWQ3MWYzMzY3OWM1MzAzZGJmMDBlZjQzZGFjOTBiODY3YWUyZjA0M2Y5YzQwYTQwMDAwMDAwMDIzMjIwMDIwOGI5MWFhMDNlYjBmN2YzMWUzOTE3MDg4MDg0MTY4YmE1MjgyYTkxNWU3Y2RlMGE1YTkzNGI3ZWEwMmViMDU3YmZmZmZmZmZmMDMwMDg0ZDcxNzAwMDAwMDAwMjA2YTFlNDI2OTc0NDc2ZjIwNmQ2OTc4NjU2NDIwNzAzMjczNjgyMDI2MjA3MzY1Njc3NzY5NzQyMDc0NjU3Mzc0YjA4ZmY5MDIwMDAwMDAwMDE3YTkxNDgxNTNlN2EzNTUwODA4OGI2Y2Y1OTkyMjY3OTJjN2RlMmRiZmYyNTI4NzYwM2YwMTAwMDAwMDAwMDAxN2E5MTRkOWY3YmU0Nzk3NWMwMzZmOTQyMjhiMGJmZDcwNzAxOTEyNzU4YmE5ODcwMDA1MDA0NzMwNDQwMjIwNTg5OGJlZTcxMTQ2N2MwOWE1ZTIyZTFkY2IxYTExZmNlMWEwZDZlYTEyOWQ5MTFmODEzZjg3YzdkNDVlMDY3YjAyMjAyZjY5ZmIxMThiYmYwYjA3MmVkMjZkNzJjZjgwNzNlN2FjZDY2YzIwNTQxOWE0YTAwZjg2YTdiYTBmNmUzZGQ2MDEwMDAwNjk1MjIxMDMwNzgwMTg2YzBiZTVkZjBkMmQ2MmNmNTRjYzJmM2QyYzA5OTExZTM3N2FhOTViNWZlODc1ZmEzNTJhZWQwYTU5MjEwM2YzMjM3ZWRkMmQ4NzAxMGU4ZmU5ZjQzZjM0ZThjNjNkZTYzODQyODNkZTkwOTc5NWQ2MmFmNGRkYjRkNTc5NTQyMTAyYWQwM2RlNTUwNGVmOTQ3ZTRlNmVlMmZhNmIxNWQxNTBkNTUzYzIxMjc1ZjQ5ZjJjZTIzNTlkOWZkZWRiOWFkZTUzYWUwMDAwMDAwMCdcbiAgICAgICk7XG5cbiAgICAgIC8vIGFkZCBzZWNvbmQgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCA9IHNpZ25hdHVyZTEudHg7XG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IGJhY2t1cEtleXBhaXI7XG4gICAgICB0cmFuc2FjdGlvbi5mdWxsTG9jYWxTaWduaW5nID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTIgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgLy8gdGhpcyB0cmFuc2FjdGlvbiBoYXMgYWN0dWFsbHkgd29ya2VkOiBodHRwczovL3Rlc3RuZXQuc21hcnRiaXQuY29tLmF1L3R4L2UyZjY5NmJjYmE5MWEzNzZjMzZiYjUyNWRmOGMzNjc5MzhmNmUyZmQ2MzQ0YzkwNTg3YmYxMjgwMjA5MTEyNGNcbiAgICAgIC8vIE5vdGUgdGhhdCB0aGUgdHggaGV4IGJlbG93IG5vIGxvbmdlciBjb3JyZXNwb25kcyB0byB0aGUgYWJvdmUgdHJhbnNhY3Rpb24gYmVjYXVzZSBvdXIgZmVlIGVzdGltYXRpb24gaGFzXG4gICAgICAvLyBjaGFuZ2VkLCBjaGFuZ2luZyB0aGUgb3V0cHV0IGFtb3VudHMgYW5kIHRodXMgdGhlIHR4IGhleC5cbiAgICAgIHNpZ25hdHVyZTIudHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMDAxMDI3Yzc1ZjhiNDA2MTIxMmVjNDY2OWVmMTBjN2E4NWE2YmQ4YjY3N2U3NGVjZmZlZjcyZGYxZTM1YjBhY2U1NGY2MDEwMDAwMDBmZGZmMDAwMDQ4MzA0NTAyMjEwMGZmYzQ1ZDkzY2JhZjRjMWM4NTBlMjFmMjc3YzViMzExZDNlMzk1N2YxMzM4OTU1Y2IxNjVkNzJhNzY4YTA1NGMwMjIwNTIwMjA1OTNiMzY3ODFlZWEwMGE5ZjhkY2JlYjc2NjA4ZjkyMGM3YTkzM2E5MDg4MzE4YWIyZjcwYzExZTFkOTAxNDgzMDQ1MDIyMTAwODI1NGQxMDA0MDFhM2E4MzFlZDAxOWUxNjYyZGJkOTBiOTZjNmM0MDcyYjgxY2U2NDBkMTUyYmMyOTI5NWMxMDAyMjAxM2Y4NmM1YWY1NzE2MjM0OTk5YTdiZDZlOTRmYzhmNDI4Zjc2OTdjYzMxMzhiMzY0OWQwZWM0ZGQ4NjgxYmM3MDEwMDRjNjk1MjIxMDNkYTk1YjI4YTEzYWEyZDRiYjQ5MGQ3MDYyOGUyZTVkOTEyNDYxZDM3NWZlZjM4MWFhZGQ4OWRjMTI1NjIyMDc1MjEwMzEyMTI4N2E1MTBjNWYzMmU4YmE3MmQyNDc5ZTkwZWI1MmJhNDRhNDY3MTczZGYzMzlmZWIwZmYyMTVmMTAwZTMyMTAyOTc3Y2RmYmVlNzYwNjZhZTczOWRiNzJkNTUzNzFhZDQ5ZGM2NzEyZmI4ZjJmM2Y2OWJiMWE0YzI0MjJiMGIxYTUzYWVmZmZmZmZmZjI0OWY0ZjNiODkxMTA1MjZlOWQ3MWYzMzY3OWM1MzAzZGJmMDBlZjQzZGFjOTBiODY3YWUyZjA0M2Y5YzQwYTQwMDAwMDAwMDIzMjIwMDIwOGI5MWFhMDNlYjBmN2YzMWUzOTE3MDg4MDg0MTY4YmE1MjgyYTkxNWU3Y2RlMGE1YTkzNGI3ZWEwMmViMDU3YmZmZmZmZmZmMDMwMDg0ZDcxNzAwMDAwMDAwMjA2YTFlNDI2OTc0NDc2ZjIwNmQ2OTc4NjU2NDIwNzAzMjczNjgyMDI2MjA3MzY1Njc3NzY5NzQyMDc0NjU3Mzc0YjA4ZmY5MDIwMDAwMDAwMDE3YTkxNDgxNTNlN2EzNTUwODA4OGI2Y2Y1OTkyMjY3OTJjN2RlMmRiZmYyNTI4NzYwM2YwMTAwMDAwMDAwMDAxN2E5MTRkOWY3YmU0Nzk3NWMwMzZmOTQyMjhiMGJmZDcwNzAxOTEyNzU4YmE5ODcwMDA1MDA0NzMwNDQwMjIwNTg5OGJlZTcxMTQ2N2MwOWE1ZTIyZTFkY2IxYTExZmNlMWEwZDZlYTEyOWQ5MTFmODEzZjg3YzdkNDVlMDY3YjAyMjAyZjY5ZmIxMThiYmYwYjA3MmVkMjZkNzJjZjgwNzNlN2FjZDY2YzIwNTQxOWE0YTAwZjg2YTdiYTBmNmUzZGQ2MDE0NzMwNDQwMjIwNzcxM2Q2NzFiNDU5ODk2ODhlMjY2NWMyYjExYWI3ZTVlYThkNTdlYjE0ZjlkYTIzM2MwOTVkYWJlNDQxMzA4ZDAyMjA2OTUyMWI1YWViMDcxYjA3YTcwYTcxOTdhMGMyYmJjNDBhMjNhZTYzYTA0MTYwY2YzNjI3MjUwYzRiYTRjNDBmMDEwMDY5NTIyMTAzMDc4MDE4NmMwYmU1ZGYwZDJkNjJjZjU0Y2MyZjNkMmMwOTkxMWUzNzdhYTk1YjVmZTg3NWZhMzUyYWVkMGE1OTIxMDNmMzIzN2VkZDJkODcwMTBlOGZlOWY0M2YzNGU4YzYzZGU2Mzg0MjgzZGU5MDk3OTVkNjJhZjRkZGI0ZDU3OTU0MjEwMmFkMDNkZTU1MDRlZjk0N2U0ZTZlZTJmYTZiMTVkMTUwZDU1M2MyMTI3NWY0OWYyY2UyMzU5ZDlmZGVkYjlhZGU1M2FlMDAwMDAwMDAnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZW5kIHRvIGJlY2gzMiByZWNpcGllbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzE0Jywgc2Vnd2l0OiBmYWxzZSB9KTtcbiAgICAgIGNvbnN0IHNlZ3dpdEFkZHJlc3MgPSBmYWtlV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMTAvMTQnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBjb25zdCBwMnNoVW5zcGVudCA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJONTMzZnFneVBZS1ZEODkybkJSYVltRkhiYlR5a2hZU0V3J10sXG4gICAgICAgIHZhbHVlOiAnMi45OTk5NjYxMCcsXG4gICAgICAgIHZhbHVlX2ludDogMjk5OTk2NjEwLFxuICAgICAgICB0eGlkOiAnZjY1NGNlMGE1YmUzZjEyZGY3ZmVjZjRlZTc3N2I2ZDg2YjVhYThjNzEwZWY2OTQ2ZWMxMjEyMDZiNGY4NzU3YycsXG4gICAgICAgIG46IDEsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCA4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0ODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1Mjg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMxMjYzLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHNlZ3dpdFVuc3BlbnQgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTkJ0cFhjRHJ1ZjN6UnV0bUY0QWJDTUZOUUhYc0dOUDZrVCddLFxuICAgICAgICB2YWx1ZTogJzEuNTAwMDAwMDAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDE1MDAwMDAwMCxcbiAgICAgICAgdHhpZDogJ2E0NDA5YzNmMDQyZmFlNjdiODkwYWMzZGY0MGVmMGRiMDM1MzljNjczMzFmZDdlOTI2MDUxMTg5M2I0ZjlmMjQnLFxuICAgICAgICBuOiAwLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgY2M4ZTdjYmY0ODEzODlkMzE4M2E1OTBhY2ZhNmFhNjZlYjk3YzhlMSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNGNjOGU3Y2JmNDgxMzg5ZDMxODNhNTkwYWNmYTZhYTY2ZWI5N2M4ZTE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgIGlkOiA2MTMzMDg4MixcbiAgICAgIH07XG4gICAgICBjb25zdCBhZGRyZXNzZXMgPSBbcDJzaEFkZHJlc3MsIHNlZ3dpdEFkZHJlc3NdO1xuICAgICAgY29uc3QgdW5zcGVudHMgPSBbcDJzaFVuc3BlbnQsIHNlZ3dpdFVuc3BlbnRdLm1hcCgodW5zcGVudDogYW55LCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gYWRkcmVzc2VzW2luZGV4XTtcbiAgICAgICAgXy5leHRlbmQodW5zcGVudCwgYWRkcmVzcyk7XG4gICAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuICAgICAgICByZXR1cm4gdW5zcGVudDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBmYWtlV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogcDJzaEFkZHJlc3MuYWRkcmVzcyxcbiAgICAgICAgdW5zcGVudHM6IHVuc3BlbnRzLFxuICAgICAgICByZWNpcGllbnRzOiB7IHRiMXFndXp5azR3NmthcXRwc2N6czVhajB3OHI3NTk4anEzNmVnbThlOTh3cXBoM3J3bWV4NjhzZXNsZ3NnOiAzMDAwMDAgfSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIG9wUmV0dXJuczogeyAnQml0R28gbWl4ZWQgcDJzaCAmIHNlZ3dpdCB0ZXN0JzogNDAwMDAwMDAwIH0sXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiA4MTc2MCxcbiAgICAgICAgICBhZGRyZXNzOiAnMk5EN2pRUjVpdGpHVGJoM0RLZ2JwWldTWTl1bmdEcndjd2InLFxuICAgICAgICB9LFxuICAgICAgICB1c2VQc2J0OiBmYWxzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAyN2M3NWY4YjQwNjEyMTJlYzQ2NjllZjEwYzdhODVhNmJkOGI2NzdlNzRlY2ZmZWY3MmRmMWUzNWIwYWNlNTRmNjAxMDAwMDAwMDBmZmZmZmZmZjI0OWY0ZjNiODkxMTA1MjZlOWQ3MWYzMzY3OWM1MzAzZGJmMDBlZjQzZGFjOTBiODY3YWUyZjA0M2Y5YzQwYTQwMDAwMDAwMDAwZmZmZmZmZmYwNGUwOTMwNDAwMDAwMDAwMDAyMjAwMjA0NzA0NGI1NWRhYjc0MGIwYzMwMjg1M2IyN2I4ZTNmNTBhNzkwMjNhY2EzNjdjOTRlZTAwNmYxMWJiNzkzNjhmMDA4NGQ3MTcwMDAwMDAwMDIwNmExZTQyNjk3NDQ3NmYyMDZkNjk3ODY1NjQyMDcwMzI3MzY4MjAyNjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NDdjZmFmNDAyMDAwMDAwMDAxN2E5MTQ4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyODc2MDNmMDEwMDAwMDAwMDAwMTdhOTE0ZDlmN2JlNDc5NzVjMDM2Zjk0MjI4YjBiZmQ3MDcwMTkxMjc1OGJhOTg3MDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgZmlyc3Qgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IHVzZXJLZXlwYWlyO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMSA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICBzaWduYXR1cmUxLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDAwMTAyN2M3NWY4YjQwNjEyMTJlYzQ2NjllZjEwYzdhODVhNmJkOGI2NzdlNzRlY2ZmZWY3MmRmMWUzNWIwYWNlNTRmNjAxMDAwMDAwYjcwMDQ4MzA0NTAyMjEwMDg4MDkzNzc2MzRlNjY3ZDZlMTlmMzhhMTM4YTU1YjJiNjM3MDMxMmFmNzZhNWNhM2I3NzZkZjYxZmM3MTk2MTcwMjIwMjFkOTAzNDdiOTA4NWFiNzFhNzZjODQwMGY5ODRlMzIyYzE1NDUxZWNjNjczZGQzN2RlMzA4ODc0MzZkMzdiNDAxMDAwMDRjNjk1MjIxMDNkYTk1YjI4YTEzYWEyZDRiYjQ5MGQ3MDYyOGUyZTVkOTEyNDYxZDM3NWZlZjM4MWFhZGQ4OWRjMTI1NjIyMDc1MjEwMzEyMTI4N2E1MTBjNWYzMmU4YmE3MmQyNDc5ZTkwZWI1MmJhNDRhNDY3MTczZGYzMzlmZWIwZmYyMTVmMTAwZTMyMTAyOTc3Y2RmYmVlNzYwNjZhZTczOWRiNzJkNTUzNzFhZDQ5ZGM2NzEyZmI4ZjJmM2Y2OWJiMWE0YzI0MjJiMGIxYTUzYWVmZmZmZmZmZjI0OWY0ZjNiODkxMTA1MjZlOWQ3MWYzMzY3OWM1MzAzZGJmMDBlZjQzZGFjOTBiODY3YWUyZjA0M2Y5YzQwYTQwMDAwMDAwMDIzMjIwMDIwOGI5MWFhMDNlYjBmN2YzMWUzOTE3MDg4MDg0MTY4YmE1MjgyYTkxNWU3Y2RlMGE1YTkzNGI3ZWEwMmViMDU3YmZmZmZmZmZmMDRlMDkzMDQwMDAwMDAwMDAwMjIwMDIwNDcwNDRiNTVkYWI3NDBiMGMzMDI4NTNiMjdiOGUzZjUwYTc5MDIzYWNhMzY3Yzk0ZWUwMDZmMTFiYjc5MzY4ZjAwODRkNzE3MDAwMDAwMDAyMDZhMWU0MjY5NzQ0NzZmMjA2ZDY5Nzg2NTY0MjA3MDMyNzM2ODIwMjYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzQ3Y2ZhZjQwMjAwMDAwMDAwMTdhOTE0ODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1Mjg3NjAzZjAxMDAwMDAwMDAwMDE3YTkxNGQ5ZjdiZTQ3OTc1YzAzNmY5NDIyOGIwYmZkNzA3MDE5MTI3NThiYTk4NzAwMDUwMDQ4MzA0NTAyMjEwMDhiOTVhYzgzZTQ0YzcyN2I3OWZmYmY0NTcxMTcxOTI1ZDA2Zjg4M2EwNWMxMjJiM2IzM2MwNTVmMGJmZmE3MDEwMjIwN2I1ZWUzNDEyZWE4YTVjZWM0YTVjMzg2ZjFiNDY0YWI2OGQ1MzFjNmM2OTcwNzdiYzQ2MmMwNWViNDRhMjgzMjAxMDAwMDY5NTIyMTAzMDc4MDE4NmMwYmU1ZGYwZDJkNjJjZjU0Y2MyZjNkMmMwOTkxMWUzNzdhYTk1YjVmZTg3NWZhMzUyYWVkMGE1OTIxMDNmMzIzN2VkZDJkODcwMTBlOGZlOWY0M2YzNGU4YzYzZGU2Mzg0MjgzZGU5MDk3OTVkNjJhZjRkZGI0ZDU3OTU0MjEwMmFkMDNkZTU1MDRlZjk0N2U0ZTZlZTJmYTZiMTVkMTUwZDU1M2MyMTI3NWY0OWYyY2UyMzU5ZDlmZGVkYjlhZGU1M2FlMDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgc2Vjb25kIHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXggPSBzaWduYXR1cmUxLnR4O1xuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSBiYWNrdXBLZXlwYWlyO1xuICAgICAgdHJhbnNhY3Rpb24uZnVsbExvY2FsU2lnbmluZyA9IHRydWU7XG4gICAgICBjb25zdCBzaWduYXR1cmUyID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih0cmFuc2FjdGlvbikpIGFzIGFueTtcbiAgICAgIGNvbnNvbGUubG9nKCdzaWduYXR1cmUxICcgKyBKU09OLnN0cmluZ2lmeShzaWduYXR1cmUyKSk7XG4gICAgICAvLyB0aGlzIHRyYW5zYWN0aW9uIGhhcyBhY3R1YWxseSB3b3JrZWQ6IGh0dHBzOi8vdGVzdG5ldC5zbWFydGJpdC5jb20uYXUvdHgvZTJmNjk2YmNiYTkxYTM3NmMzNmJiNTI1ZGY4YzM2NzkzOGY2ZTJmZDYzNDRjOTA1ODdiZjEyODAyMDkxMTI0Y1xuICAgICAgLy8gTm90ZSB0aGF0IHRoZSB0eCBoZXggYmVsb3cgbm8gbG9uZ2VyIGNvcnJlc3BvbmRzIHRvIHRoZSBhYm92ZSB0cmFuc2FjdGlvbiBiZWNhdXNlIG91ciBmZWUgZXN0aW1hdGlvbiBoYXNcbiAgICAgIC8vIGNoYW5nZWQsIGNoYW5naW5nIHRoZSBvdXRwdXQgYW1vdW50cyBhbmQgdGh1cyB0aGUgdHggaGV4LlxuICAgICAgc2lnbmF0dXJlMi50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAwMDEwMjdjNzVmOGI0MDYxMjEyZWM0NjY5ZWYxMGM3YTg1YTZiZDhiNjc3ZTc0ZWNmZmVmNzJkZjFlMzViMGFjZTU0ZjYwMTAwMDAwMGZkZmUwMDAwNDgzMDQ1MDIyMTAwODgwOTM3NzYzNGU2NjdkNmUxOWYzOGExMzhhNTViMmI2MzcwMzEyYWY3NmE1Y2EzYjc3NmRmNjFmYzcxOTYxNzAyMjAyMWQ5MDM0N2I5MDg1YWI3MWE3NmM4NDAwZjk4NGUzMjJjMTU0NTFlY2M2NzNkZDM3ZGUzMDg4NzQzNmQzN2I0MDE0NzMwNDQwMjIwNWE1OGU2MDIwNDJiOGU4YTVkYTUwOWQxOWNlMzEwNTAxNDdkZDBmZmNmYmUyYmIzMzdjMjNkNGM4OGY0Y2M0MTAyMjA3NWJmYTQ1NWQxZjc0ZTMwZmJkOWM3ODZjZDQ4MTFhMWRlZmU1NDMxMGYyMzViNDE5M2NlNGZmYTBlODMwOWExMDEwMDRjNjk1MjIxMDNkYTk1YjI4YTEzYWEyZDRiYjQ5MGQ3MDYyOGUyZTVkOTEyNDYxZDM3NWZlZjM4MWFhZGQ4OWRjMTI1NjIyMDc1MjEwMzEyMTI4N2E1MTBjNWYzMmU4YmE3MmQyNDc5ZTkwZWI1MmJhNDRhNDY3MTczZGYzMzlmZWIwZmYyMTVmMTAwZTMyMTAyOTc3Y2RmYmVlNzYwNjZhZTczOWRiNzJkNTUzNzFhZDQ5ZGM2NzEyZmI4ZjJmM2Y2OWJiMWE0YzI0MjJiMGIxYTUzYWVmZmZmZmZmZjI0OWY0ZjNiODkxMTA1MjZlOWQ3MWYzMzY3OWM1MzAzZGJmMDBlZjQzZGFjOTBiODY3YWUyZjA0M2Y5YzQwYTQwMDAwMDAwMDIzMjIwMDIwOGI5MWFhMDNlYjBmN2YzMWUzOTE3MDg4MDg0MTY4YmE1MjgyYTkxNWU3Y2RlMGE1YTkzNGI3ZWEwMmViMDU3YmZmZmZmZmZmMDRlMDkzMDQwMDAwMDAwMDAwMjIwMDIwNDcwNDRiNTVkYWI3NDBiMGMzMDI4NTNiMjdiOGUzZjUwYTc5MDIzYWNhMzY3Yzk0ZWUwMDZmMTFiYjc5MzY4ZjAwODRkNzE3MDAwMDAwMDAyMDZhMWU0MjY5NzQ0NzZmMjA2ZDY5Nzg2NTY0MjA3MDMyNzM2ODIwMjYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzQ3Y2ZhZjQwMjAwMDAwMDAwMTdhOTE0ODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1Mjg3NjAzZjAxMDAwMDAwMDAwMDE3YTkxNGQ5ZjdiZTQ3OTc1YzAzNmY5NDIyOGIwYmZkNzA3MDE5MTI3NThiYTk4NzAwMDUwMDQ4MzA0NTAyMjEwMDhiOTVhYzgzZTQ0YzcyN2I3OWZmYmY0NTcxMTcxOTI1ZDA2Zjg4M2EwNWMxMjJiM2IzM2MwNTVmMGJmZmE3MDEwMjIwN2I1ZWUzNDEyZWE4YTVjZWM0YTVjMzg2ZjFiNDY0YWI2OGQ1MzFjNmM2OTcwNzdiYzQ2MmMwNWViNDRhMjgzMjAxNDczMDQ0MDIyMDUzNjkwMjM0NTgyYTY5MTFhMjhjYWU5ZjUzNGM5ODBiN2Q3OTE4NzQ5YTc0MTNjMWM1OTMyN2RlYmYxNmZmMGIwMjIwNTYxNzVmNWMyN2EzNjM0MTZiMmNlNDc5MWFlZmMzZDU1NTQ1Y2FjYmQwNTI3MjAyZTg2OWUxMTI3ZmMyZjI0ZDAxMDA2OTUyMjEwMzA3ODAxODZjMGJlNWRmMGQyZDYyY2Y1NGNjMmYzZDJjMDk5MTFlMzc3YWE5NWI1ZmU4NzVmYTM1MmFlZDBhNTkyMTAzZjMyMzdlZGQyZDg3MDEwZThmZTlmNDNmMzRlOGM2M2RlNjM4NDI4M2RlOTA5Nzk1ZDYyYWY0ZGRiNGQ1Nzk1NDIxMDJhZDAzZGU1NTA0ZWY5NDdlNGU2ZWUyZmE2YjE1ZDE1MGQ1NTNjMjEyNzVmNDlmMmNlMjM1OWQ5ZmRlZGI5YWRlNTNhZTAwMDAwMDAwJ1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1NlbmQgTWFueScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgncmVzcG9uZHMgd2l0aCBwcm9wZXIgZmVlIGFuZCBmZWUgcmF0ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICcyTXV0cFhWWXM4THlrNzRwVkRuM2VBRzd4bks0V2Mya2pUUScsXG4gICAgICAgICAgICBhbW91bnQ6IDMwMDAwMCxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHVuc3BlbnRzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgdmFsdWU6IDgxNzAsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB2YWx1ZTogODAwMDAwLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IGNyZWF0ZUFuZFNpZ25SZXNwb25zZSA9IHtcbiAgICAgICAgYml0Z29GZWU6IDAsXG4gICAgICAgIHRyYXZlbEluZm9zOiBbXSxcbiAgICAgICAgdW5zcGVudHMsXG4gICAgICAgIHR4OiAnaGFsZnNpZ25lZGhleCcsXG4gICAgICB9O1xuICAgICAgc2lub24uc3R1YihmYWtlV2FsbGV0LCAnY3JlYXRlQW5kU2lnblRyYW5zYWN0aW9uJykucmV0dXJucyhQcm9taXNlLnJlc29sdmUoY3JlYXRlQW5kU2lnblJlc3BvbnNlKSk7XG4gICAgICBjb25zdCBnZXRTZW5kVHhSZXNwb25zZSA9ICgpID0+ICh7XG4gICAgICAgIHN0YXR1czogJ2FjY2VwdGVkJyxcbiAgICAgICAgdHg6ICcwMTAwMDAwMDAwMDEwMjI4YjVjM2UyNzg5ZDQ3NzBmYzM5N2VjNzlmYTcyNTVmODYyMzUyOTdjNWEwNGRlZjY3OGI0ODFiOGIwOWU4MWIwMTAwMDAwMDIzMjIwMDIwYjNiYmUwNjc5NjBiZTM5NTAxZjM2NWI4OTk5ZDUzZjJhODI4NWQ4ZDk4MzZmNjFmYWQwMjBlNmE0YTllMjZmZGZmZmZmZmZmMTUxMGU5MDQxMWE4NmM0OWYyYTUyNTQ2YTMyYTAzZmViZGUyYmM2MDQ3NDFmMGU4NWRjNDdhZGVjMzNmNTE1OTAwMDAwMDAwZmRmZDAwMDA0ODMwNDUwMjIxMDBhNDRiYmY5N2IxNTVjNTc3MDM4NjJiZTY5ZDJiMjBjNGIyYWI5ZTk0ZjQwMjU5NTg4MGJmNzQ0MDJjY2M4N2UyMDIyMDBhNGFhZjk4ZjkzOWI2NWM5OGNhMDhlYjk2MDc0YzIyMmVjYjFmYzM3ZTM1OWIxZDY3YTA1ZjFjNTZkZWRmYzAwMTQ3MzA0NDAyMjAwM2YzOTg5YTE0Mjg0ZjEzMmJiYjU1MDExOGMyMDI1NmQ0ZWE3Mzc3MDQxMjNhMjk5NTVhY2MxZDAzZWE2ZWI3MDIyMDE3MjIzZGE3ZWRjZjczMDc2ZDg5ODc1YWEzMzM2MGFhNmExMjE0MTgwN2Y2ODNjNmMxYjlhNWEwZDNmZjYwMTkwMTRjNjk1MjIxMDI1Nzg5ODU3Y2M4YmUxMTBmZjRjYmYzNTRiNTJkZDBlN2U5MzI2YzZiZmUwYWVlNmMzMGMxZWU2OTY2MGMzZGMwMjEwMmY1OGYxYjE1MTZkMDU4MTRhZTY4OGNhNzAxODU2Njk1ZTI3MDUwZTNlMTZkM2EyMzUxMjg0ZDdhZjg0NDk4ODgyMTAyMzg1YzdiY2VjM2YzOGMxM2U4N2I1NThhZWJmMmYyMGE4OTI4ZTdlY2JlMTFlN2MzYTQ3NzkyYmM4ZTMzZmU4ODUzYWVmZmZmZmZmZjAyZTA5MzA0MDAwMDAwMDAwMDE3YTkxNDFkMGM3OTFjZWMzYWYxZjM3ODA4ZDQyZjA0NTkzMDk1ZDZmZGVhMjY4NzA1YmMwNzAwMDAwMDAwMDAxN2E5MTRkOGM3MjBmNjQ2YzdjNTZjNTQ2NzI0OGU0N2M3MmRjMGIyZDMwYmJjODcwNDAwNDczMDQ0MDIyMDFlYWExMzU5ZmZmZDNiZGVjNWI0ODI2OGJkMmYxNTE5M2EyOTljMjJiMTk3MDM1NmYzOTA4ODM0NzMzMjQ2NTEwMjIwNzQxODYyMzJmMDIyNDVhZjljMDk3NzAzMTQ0OGMyYzk5ZTdiN2UyYjA1YjJiYTRiMzJjMzIyN2Q4Y2ExNDk0ZTAxNDgzMDQ1MDIyMTAwYmQ2MWIzNzA1MWMyODUzM2VhMGIwMGRkYTc1YjFjNGYxZGVlMWI2ODNiYjczNTFiMmQ4ZGQ3MjBmNmRmYmUxMTAyMjAzYWNjNGNmOWQyZGQ0NGIyOTRhYTI1ODEyZTk5ZTdkOGViMzczMGU0ZmY2Zjg4OWQzY2RjZDUyNTE5NTc1MGI4MDE2OTUyMjEwMjE5ZDA5M2MxOGMyN2NiNTQ3NzM3YjRhNDlkZGRhYzljMzQxMmIxMGU5Zjg4MGViMzAwNTNjM2ViYTgxOTI4NTQyMTAzNzQ3MTE4ODkyY2FjMWI0ZGExMTUyNmZjNGViZWViZTE2OGRhZTA5MDdjZWZiMWExODEyNTQxY2Q0NmIwNzYwMjIxMDMzOWY3M2I2NzUwZjhmOTFlZmQ0ODRiNWFhMjk3NDMyMWE2Y2MyNzc2ZDViZDc4YjljZmI1ZmUxOGUzYjJkNjYyNTNhZTAwNWE5ZTE2MDAnLFxuICAgICAgICBoYXNoOiAnZjhkZjQzYzJjNjUwYjNiYjExMjc3YWVlNDUzMWRiOTlhNzE1ZmEzYjlkZmQzZDQ1YThkMTcxMzQyYzFiZjc4MCcsXG4gICAgICAgIGluc3RhbnQ6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBleHBlY3RlZFJlc3VsdCA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgIHtcbiAgICAgICAgICBmZWU6IDEyODUsXG4gICAgICAgICAgZmVlUmF0ZTogMjUxOS42MDc4NDMxMzcyNTUsXG4gICAgICAgIH0sXG4gICAgICAgIGdldFNlbmRUeFJlc3BvbnNlKClcbiAgICAgICk7XG4gICAgICBzaW5vbi5zdHViKGZha2VXYWxsZXQsICdzZW5kVHJhbnNhY3Rpb24nKS5yZXNvbHZlcyhnZXRTZW5kVHhSZXNwb25zZSgpKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IChhd2FpdCBmYWtlV2FsbGV0LnNlbmRNYW55KHBhcmFtcykpIGFzIGFueTtcbiAgICAgIHJlc3VsdC50eC5zaG91bGQuZXF1YWwoZXhwZWN0ZWRSZXN1bHQudHgpO1xuICAgICAgcmVzdWx0LmZlZS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRSZXN1bHQuZmVlKTtcbiAgICAgIHJlc3VsdC5mZWVSYXRlLnNob3VsZC5lcXVhbChleHBlY3RlZFJlc3VsdC5mZWVSYXRlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0FjY2VsZXJhdGUgVHJhbnNhY3Rpb24gKHNlcnZlciBtb2NrZWQpJywgZnVuY3Rpb24gYWNjZWxlcmF0ZVR4TW9ja2VkRGVzY3JpYmUoKSB7XG4gICAgbGV0IHdhbGxldDtcbiAgICBsZXQgYmdVcmw7XG4gICAgbGV0IGV4cGxvcmVyVXJsO1xuICAgIGxldCBtaW5DaGFuZ2VTaXplO1xuXG4gICAgbGV0IHBhcmVudFR4SWQgPSAnNmE3NGI3NGRmNDk5MWQ5M2MzMmQ3NTEzMzZjODViNWYyZDFlZTU0NGEyZGZiYWUyZTVmNGJlYjRmOTE0ZTVlMCc7XG4gICAgY29uc3Qgb3V0cHV0SWR4ID0gMDtcbiAgICBjb25zdCBvdXRwdXRBZGRyZXNzID0gJzJOQ29TZkhINkxzNENkVFM1UWFoZ0M5azd4OVJmWGVTd1k0JztcbiAgICBjb25zdCB1bnJlbGF0ZWRUeElkID0gJzA4ZjVlMGI0YWNiNWFiODI0NTIyOWRmZTE2MWNlNGNhMGRhMWVjOTgzZTdhMzRiMDllNzJmNTY5NzlhNDY3ZGYnO1xuICAgIGNvbnN0IHdhbGxldElkID0gJzJOQ29TZkhINkxzNENkVFM1UWFoZ0M5azd4OVJmWGVTd1k0JztcblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBnZXQgdGhlIHBhcmVudCB0cmFuc2FjdGlvbiBJRCBmcm9tIGEgdHJhbnNhY3Rpb24gaW5wdXRcbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gY29udmVydHMgYGhhc2hgICh3aGljaCBpcyBhIEJ1ZmZlciBvYmplY3QpIHRvIGEgdXNhYmxlIHR4aWQgc3RyaW5nLlxuICAgICAqIFRoZSBpc3N1ZSBpcyB0aGF0IHRoZSBieXRlcyBhcmUgc3RvcmVkIGluIHJldmVyc2Ugb3JkZXIgaW4gdGhlIGJ1ZmZlciwgc29cbiAgICAgKiB0aGUgc2ltcGxlIGFwcHJvYWNoIG9mIGp1c3QgY29tcGFyaW5nIHRoZSBoZXggc3RyaW5ncyBkb2Vzbid0IHdvcmsuXG4gICAgICogSW5zdGVhZCwgdGhlIEJ1ZmZlciBpcyBjb3BpZWQgdG8gYSBuZXcgQnVmZmVyIG9iamVjdCwgdGhlIG5ldyBCdWZmZXJcbiAgICAgKiBvYmplY3QgaXMgcmV2ZXJzZWQgaW4tcGxhY2UsIGFuZCB0aGVuIHRoZSBuZXcgQnVmZmVyIGlzIGNvbnZlcnRlZCB0byBhXG4gICAgICogaGV4IHN0cmluZy4gQWZ0ZXIgdGhpcywgdGhlIHJlc3VsdCBpcyBhIGhleCBzdHJpbmcgd2hpY2ggaXMgdGhlIHBhcmVudCB0eGlkXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaGFzaCBhIGJpdGNvaW5qcy1saWIgdHJhbnNhY3Rpb24gb2JqZWN0J3MgaW5wdXQgaGFzaFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlucHV0UGFyZW50VHhJZCh7IGhhc2ggfSk6IHN0cmluZyB7XG4gICAgICByZXR1cm4gKEJ1ZmZlci5mcm9tKGhhc2gpLnJldmVyc2UoKSBhcyBCdWZmZXIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICB9XG5cbiAgICBiZWZvcmUoZnVuY3Rpb24gYWNjZWxlcmF0ZVR4TW9ja2VkQmVmb3JlKCkge1xuICAgICAgbm9jay5wZW5kaW5nTW9ja3MoKS5zaG91bGQuYmUuZW1wdHkoKTtcblxuICAgICAgYml0Z28gPSBuZXcgQml0R29BUEkoeyBlbnY6ICdtb2NrJywgY2xpZW50Q29uc3RhbnRzOiB7IGNvbnN0YW50czoge30gfSB9KTtcbiAgICAgIC8vIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgICAgYml0Z28uc2V0VmFsaWRhdGUoZmFsc2UpO1xuICAgICAgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgeyBpZDogd2FsbGV0SWQsIHByaXZhdGU6IHsga2V5Y2hhaW5zOiBbdXNlcktleXBhaXIsIGJhY2t1cEtleXBhaXIsIGJpdGdvS2V5XSB9IH0pO1xuICAgICAgKHdhbGxldCBhcyBhbnkpLmJpdGdvID0gYml0Z287XG4gICAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLnVyaTtcbiAgICAgIGV4cGxvcmVyVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0uYnRjRXhwbG9yZXJCYXNlVXJsO1xuXG4gICAgICAvLyB0cnkgdG8gZ2V0IHRoZSBtaW4gY2hhbmdlIHNpemUgZnJvbSB0aGUgc2VydmVyLCBvdGhlcndpc2UgZGVmYXVsdCB0byAwLjEgQlRDXG4gICAgICAvLyBUT0RPOiBtaW5DaGFuZ2VTaXplIGlzIG5vdCBjdXJyZW50bHkgYSBjb25zdGFudCBkZWZpbmVkIG9uIHRoZSBjbGllbnQgYW5kIHNob3VsZCBiZSBhZGRlZFxuICAgICAgbWluQ2hhbmdlU2l6ZSA9IDFlNztcbiAgICB9KTtcblxuICAgIGFmdGVyKGZ1bmN0aW9uIGFjY2VsZXJhdGVUeE1vY2tlZEFmdGVyKCkge1xuICAgICAgLy8gbWFrZSBzdXJlIGFsbCBub2NrcyBhcmUgY2xlYXJlZCBvciBjb25zdW1lZCBhZnRlciB0aGUgdGVzdHMgYXJlIGNvbXBsZXRlXG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FyZ3VtZW50cycsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IHdhbGxldC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyBmZWVSYXRlOiAxMjMgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXk1pc3NpbmcgcGFyYW1ldGVyOiB0cmFuc2FjdGlvbklEJC8pO1xuXG4gICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IDEyMywgZmVlUmF0ZTogMTIzIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9eRXhwZWN0aW5nIHBhcmFtZXRlciBzdHJpbmc6IHRyYW5zYWN0aW9uSUQgYnV0IGZvdW5kIG51bWJlciQvKTtcblxuICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiAnMTIzJyB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXk1pc3NpbmcgcGFyYW1ldGVyOiBmZWVSYXRlJC8pO1xuXG4gICAgICBjb25zdCBmZWVSYXRlc1BhcmFtcyA9IFsnMTIzJywgMCwgLTEwLCAtSW5maW5pdHksIEluZmluaXR5LCBOYU5dO1xuICAgICAgZm9yIChjb25zdCBmZWVSYXRlIG9mIGZlZVJhdGVzUGFyYW1zKSB7XG4gICAgICAgIGF3YWl0IHdhbGxldFxuICAgICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiAnMTIzJywgZmVlUmF0ZSB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9eRXhwZWN0aW5nIHBvc2l0aXZlIGZpbml0ZSBudW1iZXIgZm9yIHBhcmFtZXRlcjogZmVlUmF0ZSQvKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdiYWQgaW5wdXQnLCBmdW5jdGlvbiBiYWRJbnB1dERlc2NyaWJlKCkge1xuICAgICAgYWZ0ZXIoKCkgPT4ge1xuICAgICAgICAvLyBtYWtlIHN1cmUgYWxsIG5vY2tzIGFyZSBjbGVhcmVkIG9yIGNvbnN1bWVkIGFmdGVyIHRoZSB0ZXN0cyBhcmUgY29tcGxldGVcbiAgICAgICAgbm9jay5wZW5kaW5nTW9ja3MoKS5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnbm9uIGV4aXN0ZW50IHRyYW5zYWN0aW9uIElEJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSg0MDQsICd0cmFuc2FjdGlvbiBub3QgZm91bmQgb24gdGhpcyB3YWxsZXQnKTtcblxuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCwgZmVlUmF0ZTogMTIzIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL140MDRcXG50cmFuc2FjdGlvbiBub3QgZm91bmQgb24gdGhpcyB3YWxsZXQkLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2NvbmZpcm1lZCB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YCkucmVwbHkoMjAwLCB7XG4gICAgICAgICAgY29uZmlybWF0aW9uczogNixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsIGZlZVJhdGU6IDIwMDAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXlRyYW5zYWN0aW9uIFswLTlhLWZdKyBpcyBhbHJlYWR5IGNvbmZpcm1lZCBhbmQgY2Fubm90IGJlIGFjY2VsZXJhdGVkJC8pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdubyBvdXRwdXRzIHRvIHdhbGxldCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhY2NvdW50OiBvdXRwdXRBZGRyZXNzLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxODkwMDAwLFxuICAgICAgICAgICAgICAgIHZvdXQ6IDAsXG4gICAgICAgICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCwgZmVlUmF0ZTogMjAwMCB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICAgL15UcmFuc2FjdGlvbiBbMC05YS1mXSsgY29udGFpbnMgbm8gb3V0cHV0cyB0byB0aGlzIHdhbGxldCwgYW5kIHRodXMgY2Fubm90IGJlIGFjY2VsZXJhdGVkJC9cbiAgICAgICAgICApO1xuICAgICAgfSk7XG5cbiAgICAgIC8qXG4gICAgICAgKiBUaGlzIHRlc3QgY292ZXJzIHRoZSBjYXNlIHdoZXJlIGEgZmFpbHVyZSBvY2N1cnMgZHVyaW5nIHRoZSBwcm9jZXNzIG9mXG4gICAgICAgKiBjb252ZXJ0aW5nIGFuIG91dHB1dCBmcm9tIHRoZSBwYXJlbnQgdHJhbnNhY3Rpb24gaW50byBhbiB1bnNwZW50IHdoaWNoXG4gICAgICAgKiBjYW4gYmUgdXNlZCB0byBjaGFpbiB0aGUgY2hpbGQgdHggdG8gdGhlIHBhcmVudC5cbiAgICAgICAqXG4gICAgICAgKiBUaGlzIHNob3VsZCBuZXZlciBoYXBwZW4sIGJ1dCBpdCBpcyBwb3NzaWJsZSAoZm9yIGV4YW1wbGUsIGluIHRoZSBjYXNlXG4gICAgICAgKiBvZiBhbiBhdHRlbXB0ZWQgZG91YmxlIHNwZW5kIG9mIHRoZSBvdXRwdXQgZnJvbSB0aGUgcGFyZW50LCBvciBhIHJhY2VcbiAgICAgICAqIGJldHdlZW4gZmluZGluZyB0aGUgcGFyZW50IG91dHB1dCwgYW5kIHJldHJpZXZpbmcgdGhlIGNvcnJlc3BvbmRpbmcgdW5zcGVudCkuXG4gICAgICAgKi9cbiAgICAgIGl0KCdjYW5ub3QgZmluZCBjb3JyZWN0IHVuc3BlbnQgdG8gdXNlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFjY291bnQ6IG91dHB1dEFkZHJlc3MsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDUwICogMWU0LFxuICAgICAgICAgICAgICAgIHZvdXQ6IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICAgIGhleDogcGFyZW50VHhJZCxcbiAgICAgICAgICAgIGZlZTogMTAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApLnF1ZXJ5KHRydWUpLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGNvdW50OiAwLFxuICAgICAgICAgIHVuc3BlbnRzOiBbXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsIGZlZVJhdGU6IDIwMDAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXkNvdWxkIG5vdCBmaW5kIHVuc3BlbnQgb3V0cHV0IGZyb20gcGFyZW50IHR4IHRvIHVzZSBhcyBjaGlsZCBpbnB1dCQvKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnRGV0ZWN0cyB3aGVuIGFuIGluY29ycmVjdCB0eCBoZXggaXMgcmV0dXJuZWQgYnkgdGhlIGV4dGVybmFsIHNlcnZpY2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWNjb3VudDogb3V0cHV0QWRkcmVzcyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAsXG4gICAgICAgICAgICAgICAgdm91dDogb3V0cHV0SWR4LFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICAgICAgaGV4OiBmaXh0dXJlc1twYXJlbnRUeElkXSxcbiAgICAgICAgICAgIGZlZTogMTAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgY291bnQ6IDEsXG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogcGFyZW50VHhJZCxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogb3V0cHV0SWR4LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGV4cGxvcmVyVXJsKS5nZXQoYC90eC8ke3BhcmVudFR4SWR9L2hleGApLnJlcGx5KDIwMCwgZml4dHVyZXNbdW5yZWxhdGVkVHhJZF0pO1xuXG4gICAgICAgIGF3YWl0IHdhbGxldFxuICAgICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLCBmZWVSYXRlOiAyMDAwIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL15EZWNvZGVkIHRyYW5zYWN0aW9uIGlkIGlzIFswLTlhLWZdKywgd2hpY2ggZG9lcyBub3QgbWF0Y2ggZ2l2ZW4gdHhpZCBbMC05YS1mXSskLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2Nhbm5vdCBjb3ZlciBjaGlsZCBmZWUgd2l0aCBvbmUgcGFyZW50IG91dHB1dCBhbmQgb25lIHdhbGxldCB1bnNwZW50JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFjY291bnQ6IG91dHB1dEFkZHJlc3MsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwLFxuICAgICAgICAgICAgICAgIHZvdXQ6IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICAgIGhleDogZml4dHVyZXNbcGFyZW50VHhJZF0sXG4gICAgICAgICAgICBmZWU6IDEwLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIGNvdW50OiAxLFxuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3BhcmVudFR4SWRdKTtcblxuICAgICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYCkucXVlcnkodHJ1ZSkucmVwbHkoMjAwLCB7XG4gICAgICAgICAgY291bnQ6IDAsXG4gICAgICAgICAgdW5zcGVudHM6IFtdLFxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCwgZmVlUmF0ZTogMjAwMCB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9eSW5zdWZmaWNpZW50IGNvbmZpcm1lZCB1bnNwZW50cyBhdmFpbGFibGUgdG8gY292ZXIgdGhlIGNoaWxkIGZlZSQvKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnY2Fubm90IGxvd2VyIGZlZSByYXRlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFjY291bnQ6IG91dHB1dEFkZHJlc3MsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwLFxuICAgICAgICAgICAgICAgIHZvdXQ6IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDExLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgICBoZXg6IGZpeHR1cmVzW3BhcmVudFR4SWRdLFxuICAgICAgICAgICAgZmVlOiAxMDAwMCwgLy8gbGFyZ2UgZmVlLCBhbmQgdGh1cyBmZWUgcmF0ZSwgZm9yIHBhcmVudFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIGNvdW50OiAxLFxuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3BhcmVudFR4SWRdKTtcblxuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCwgZmVlUmF0ZTogMjAwMCB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICAgL15DYW5ub3QgbG93ZXIgZmVlIHJhdGUhIFxcKFBhcmVudCB0eCBmZWUgcmF0ZSBpcyBcXGQrXFwuP1xcZCogc2F0XFwva0IsIGFuZCByZXF1ZXN0ZWQgZmVlIHJhdGUgd2FzIFxcZCtcXC4/XFxkKiBzYXRcXC9rQlxcKSQvXG4gICAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnY2Fubm90IGJyZWFrIG1heGltdW0gZmVlIGxpbWl0IGZvciBjb21iaW5lZCB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhY2NvdW50OiBvdXRwdXRBZGRyZXNzLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAzZTcsXG4gICAgICAgICAgICAgICAgdm91dDogb3V0cHV0SWR4LFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMTEsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICAgIGhleDogZml4dHVyZXNbcGFyZW50VHhJZF0sXG4gICAgICAgICAgICBmZWU6IDEwMDAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgY291bnQ6IDEsXG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogcGFyZW50VHhJZCxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogb3V0cHV0SWR4LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGV4cGxvcmVyVXJsKS5nZXQoYC90eC8ke3BhcmVudFR4SWR9L2hleGApLnJlcGx5KDIwMCwgZml4dHVyZXNbcGFyZW50VHhJZF0pO1xuXG4gICAgICAgIGF3YWl0IHdhbGxldFxuICAgICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLCBmZWVSYXRlOiAyZTYgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIC9eVHJhbnNhY3Rpb24gY2Fubm90IGJlIGFjY2VsZXJhdGVkXFwuIENvbWJpbmVkIGZlZSByYXRlIG9mIFxcZCtcXC4/XFxkKiBzYXRcXC9rQiBleGNlZWRzIG1heGltdW0gZmVlIHJhdGUgb2YgXFxkK1xcLj9cXGQqIHNhdFxcL2tCJC9cbiAgICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnc3VjY2Vzc2Z1bCB0eCBhY2NlbGVyYXRpb24nLCBmdW5jdGlvbiBzdWNjZXNzZnVsVHhEZXNjcmliZSgpIHtcbiAgICAgIGNvbnN0IGZlZVJhdGUgPSAyMDAwMDtcblxuICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICAgIG5vY2soYmdVcmwpLnBvc3QoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L2FkZHJlc3MvMWApLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGFkZHJlc3M6ICcyTkNZakc4UTU2eXI4dHg5amF6Tm9ZbkdLeGpnQjJNUVNmWScsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7XG4gICAgICAgICAgYWRkcmVzczogJzJORmJ2bzJISzRlWFptMWFxRGNTREdHcUQ2NEZQdDdUNmQ4JyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybCkuZ2V0KCcvYXBpL3YxL3R4L2ZlZScpLnF1ZXJ5KHRydWUpLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGZlZVBlcktiOiAwLFxuICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5wb3N0KGAvYXBpL3YxL2tleWNoYWluLyR7dXNlcktleXBhaXIueHB1Yn1gLCB7fSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBlbmNyeXB0ZWRYcHJ2OiBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6IHVzZXJLZXlwYWlyLnhwcnYsIHBhc3N3b3JkOiBUZXN0Qml0R28uVEVTVF9XQUxMRVQxX1BBU1NDT0RFIH0pLFxuICAgICAgICAgICAgcGF0aDogdXNlcktleXBhaXIucGF0aCArIHVzZXJLZXlwYWlyLndhbGxldFN1YlBhdGgsXG4gICAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2FjY2VsZXJhdGVzIGEgc3R1Y2sgdHggd2l0aG91dCBhZGRpdGlvbmFsIHVuc3BlbnRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBwYXJlbnRUeElkID0gJzc1Y2ZjNWE3YjIxNGM0YjczYzkyYzdiMDI2MDhjZGU3MGIyMjY3NjdhOTU3NmY4NGMwNDQwN2U0M2ZkMzg1YmQnO1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIGZlZTogNDM0LFxuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAzNDg1MDAsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMzQ4NTAwLFxuICAgICAgICAgICAgICAgIHJlZGVlbVNjcmlwdDogJzAwMjBmN2I1OGQ0NTUzNTFiN2I4ZGRkN2M4OTg2ZDk4MjQ0ZjZhOTVmMDc0NjcyMDA5MTUzNzMyM2I5Njc4MDBmNzQ0JyxcbiAgICAgICAgICAgICAgICBjaGFpblBhdGg6ICcvMTEvMTYwJyxcbiAgICAgICAgICAgICAgICB3aXRuZXNzU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMjdmMGI0NWJiNDE1NWVhNTMyZTNiNDMxMmZlMGJlODAxNjZmMjk3ZDFlMDc1M2QyZDRhOTExOGMwNzNhZDY1MTQyMTAzMTBhYTlkNjhjOTg4MzE2MjVmMzI5Yjc4MjZiNmMzZTNiNTNlMTY3MzZiMTk5NGI4OTAyNDQyYmRjZDY2NTNkMTIxMDI2ZTBjYTQxNGYyNDg4YjBhYjU3MmI5OWUwYWU1NDQyOTExYWI0ZTA4MjFiMjcwOWQ4ODUxNzVhNTI3ZmQ1NTJiNTNhZScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soZXhwbG9yZXJVcmwpLmdldChgL3R4LyR7cGFyZW50VHhJZH0vaGV4YCkucmVwbHkoMjAwLCBmaXh0dXJlc1twYXJlbnRUeElkXSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAucG9zdCgnL2FwaS92MS90eC9zZW5kJywgKGJvZHkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiAhYm9keS5pZ25vcmVNYXhGZWVSYXRlO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJlcGx5KDIwMCwgZnVuY3Rpb24gKF8sIGJvZHkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9uOiAoYm9keSBhcyBhbnkpLnR4LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBjaGlsZFR4ID0gYXdhaXQgd2FsbGV0LmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCxcbiAgICAgICAgICBmZWVSYXRlLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRlc3RCaXRHby5URVNUX1dBTExFVDFfUEFTU0NPREUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChjaGlsZFR4KTtcbiAgICAgICAgY2hpbGRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhdHVzJywgJ2FjY2VwdGVkJyk7XG4gICAgICAgIGNoaWxkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG5cbiAgICAgICAgLy8gYXNzZXJ0IHRoZSBmb2xsb3dpbmc6XG4gICAgICAgIC8vIDApIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSBvbmUgaW5wdXRcbiAgICAgICAgLy8gMSkgVGhlIHBhcmVudCB0eCBvdXRwdXQgaXMgYW4gaW5wdXRcbiAgICAgICAgLy8gMikgVGhlIGNoaWxkIHR4IGhhcyBleGFjdGx5IG9uZSBvdXRwdXRcbiAgICAgICAgLy8gMykgVGhlIGNoaWxkIHR4IG91dHB1dCBtZWV0cyB0aGUgbWluaW11bSBjaGFuZ2UgdGhyZXNob2xkXG4gICAgICAgIGNvbnN0IGRlY29kZWRDaGlsZCA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4KGNoaWxkVHgudHgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICAgIGRlY29kZWRDaGlsZC5pbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgZGVjb2RlZENoaWxkLm91dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICBjb25zdCBjaGlsZElucHV0ID0gZGVjb2RlZENoaWxkLmluc1swXTtcbiAgICAgICAgY2hpbGRJbnB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaW5kZXgnLCAwKTtcbiAgICAgICAgY2hpbGRJbnB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaGFzaCcpO1xuXG4gICAgICAgIGNvbnN0IGlucHV0VHhJZCA9IGlucHV0UGFyZW50VHhJZChjaGlsZElucHV0KTtcbiAgICAgICAgaW5wdXRUeElkLnNob3VsZC5lcXVhbChwYXJlbnRUeElkKTtcblxuICAgICAgICBjb25zdCBjaGlsZE91dHB1dCA9IGRlY29kZWRDaGlsZC5vdXRzWzBdO1xuICAgICAgICBjaGlsZE91dHB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndmFsdWUnKTtcbiAgICAgICAgY2hpbGRPdXRwdXQudmFsdWUuc2hvdWxkLmJlLmFib3ZlKG1pbkNoYW5nZVNpemUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdhY2NlbGVyYXRlcyBhIHN0dWNrIHR4IHdpdGggb25lIGFkZGl0aW9uYWwgc2Vnd2l0IHVuc3BlbnQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHBhcmVudFR4SWQgPSAnODgxNWYyMDJjODY1NGI2YzhiMjk1NzQ5NTQ1YzcxMTg3OGNkODQ1YTE0Y2IxZWE5ODIzOTRkMGMxNDk0NWMzMyc7XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uYWxVbnNwZW50VHhJZCA9ICcwN2Q2ZWU1N2IwMjRjZTJiNjEwOGY2Nzg0NzQ1NGEwYTc5YTRmY2ZiOThhYjI1NTU1M2EyOTkzYTFhMTcwYjg3JztcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBmZWU6IDEzMzYsXG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2b3V0OiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDAwMCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDExLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogODY2NCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDEsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogcGFyZW50VHhJZCxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgICAgcmVkZWVtU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMmNkM2M4ZTYwMDZhNDYyNzcwNTAyMWQxZDAxNmQwOTdjMjk0NGQ5ODEwMGE0N2JmMmRhNjdhNWZlMTVhZWViMzQyMTAyZWUxZmE5ZTgxMmU3NzkzNTZhYTNjMzFlYmYzMTdkMGNmZmViYWI5Mjg2NGNmZTM4YmFiMjIzZTA4MjBmOThiYzIxMDI2YmEwNTc1MmJhYTZlYWZkNWM1NjU5ZGE2MmI3ZjBhYzUxZmQyODg2YjY1YzI0MWQwYWZlZjFjNGZkZmExY2JjNTNhZScsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzAvMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiBhZGRpdGlvbmFsVW5zcGVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDE5OTM1NTI2LFxuICAgICAgICAgICAgICAgIHJlZGVlbVNjcmlwdDogJzAwMjBkMzRlZjZkZDM0ZWYyYTRmYmVhNjdjNTQxYzFjNzk2NzQ5YTYwYWZlNGE5N2ZlZThlYzdkZWQxODhiZDc0OWRhJyxcbiAgICAgICAgICAgICAgICBjaGFpblBhdGg6ICcvMTEvMTU1JyxcbiAgICAgICAgICAgICAgICB3aXRuZXNzU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMjIxOWQyYWE4NDE3NjMzZjBiY2UzOTExMzc0YTE2MDRjMWI2NDE2MWY4M2EzYzJlZTQwOWMyN2M0MjM1NWYwOGUyMTAyYzk3MzQ5MjBkYzRkYTA2YzI4OWZlNjkxNzFkZmNkNzVlM2I5YjRmMTkwZDBjYmMzZDVkMGZmM2Y1ZmRlZWFhZTIxMDNjY2Q2OGQ3ZmE4ZGMwZDAyZGQ0NWRhZDE2NTU1N2E0ODU4MmVkYTQ0MzVmYWU3Mzc3YjNjMzFlMDhhZDA2NWM5NTNhZScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soZXhwbG9yZXJVcmwpLmdldChgL3R4LyR7cGFyZW50VHhJZH0vaGV4YCkucmVwbHkoMjAwLCBmaXh0dXJlc1twYXJlbnRUeElkXSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAucG9zdCgnL2FwaS92MS90eC9zZW5kJywgKGJvZHkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiAhYm9keS5pZ25vcmVNYXhGZWVSYXRlO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJlcGx5KDIwMCwgZnVuY3Rpb24gKF8sIGJvZHkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9uOiAoYm9keSBhcyBhbnkpLnR4LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBjaGlsZFR4ID0gYXdhaXQgd2FsbGV0LmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCxcbiAgICAgICAgICBmZWVSYXRlLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRlc3RCaXRHby5URVNUX1dBTExFVDFfUEFTU0NPREUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChjaGlsZFR4KTtcbiAgICAgICAgY2hpbGRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhdHVzJywgJ2FjY2VwdGVkJyk7XG4gICAgICAgIGNoaWxkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG5cbiAgICAgICAgLy8gYXNzZXJ0IHRoZSBmb2xsb3dpbmc6XG4gICAgICAgIC8vIDApIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSB0d28gaW5wdXRzXG4gICAgICAgIC8vIDEpIFRoZSBwYXJlbnQgdHggb3V0cHV0IGlzIGFuIGlucHV0XG4gICAgICAgIC8vIDIpIFRoZSBhZGRpdGlvbmFsIHVuc3BlbnQgb3V0cHV0IGlzIGFuIGlucHV0XG4gICAgICAgIC8vIDMpIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSBvbmUgb3V0cHV0XG4gICAgICAgIC8vIDQpIFRoZSBjaGlsZCB0eCBvdXRwdXQgbWVldHMgdGhlIG1pbmltdW0gY2hhbmdlIHRocmVzaG9sZFxuICAgICAgICBjb25zdCBkZWNvZGVkQ2hpbGQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleChjaGlsZFR4LnR4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgICBkZWNvZGVkQ2hpbGQuaW5zLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICAgIGRlY29kZWRDaGlsZC5vdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgbGV0IGlucHV0RnJvbVBhcmVudDogYW55ID0gdW5kZWZpbmVkO1xuICAgICAgICBsZXQgYWRkaXRpb25hbElucHV0OiBhbnkgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgXy5mb3JFYWNoKGRlY29kZWRDaGlsZC5pbnMsIChpbnB1dCkgPT4ge1xuICAgICAgICAgIGlucHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdoYXNoJyk7XG4gICAgICAgICAgaW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2luZGV4Jyk7XG5cbiAgICAgICAgICBjb25zdCBpbnB1dFR4SWQgPSBpbnB1dFBhcmVudFR4SWQoaW5wdXQpO1xuXG4gICAgICAgICAgaWYgKGlucHV0VHhJZCA9PT0gcGFyZW50VHhJZCkge1xuICAgICAgICAgICAgaW5wdXRGcm9tUGFyZW50ID0gaW5wdXQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFkZGl0aW9uYWxJbnB1dCA9IGlucHV0O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KGlucHV0RnJvbVBhcmVudCk7XG4gICAgICAgIGNvbnN0IGlucHV0RnJvbVBhcmVudEhhc2ggPSBpbnB1dFBhcmVudFR4SWQoaW5wdXRGcm9tUGFyZW50KTtcbiAgICAgICAgaW5wdXRGcm9tUGFyZW50SGFzaC5zaG91bGQuZXF1YWwocGFyZW50VHhJZCk7XG4gICAgICAgIGlucHV0RnJvbVBhcmVudC5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KGFkZGl0aW9uYWxJbnB1dCk7XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uYWxJbnB1dEhhc2ggPSBpbnB1dFBhcmVudFR4SWQoYWRkaXRpb25hbElucHV0KTtcbiAgICAgICAgYWRkaXRpb25hbElucHV0SGFzaC5zaG91bGQuZXF1YWwoYWRkaXRpb25hbFVuc3BlbnRUeElkKTtcbiAgICAgICAgYWRkaXRpb25hbElucHV0LmluZGV4LnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgICBjb25zdCBjaGlsZE91dHB1dCA9IGRlY29kZWRDaGlsZC5vdXRzWzBdO1xuICAgICAgICBjaGlsZE91dHB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndmFsdWUnKTtcbiAgICAgICAgY2hpbGRPdXRwdXQudmFsdWUuc2hvdWxkLmJlLmFib3ZlKG1pbkNoYW5nZVNpemUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdhY2NlbGVyYXRlcyBhIHN0dWNrIHR4IHdpdGggb25lIGFkZGl0aW9uYWwgUDJTSCB1bnNwZW50JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBwYXJlbnRUeElkID0gJzg4MTVmMjAyYzg2NTRiNmM4YjI5NTc0OTU0NWM3MTE4NzhjZDg0NWExNGNiMWVhOTgyMzk0ZDBjMTQ5NDVjMzMnO1xuICAgICAgICBjb25zdCBhZGRpdGlvbmFsVW5zcGVudFR4SWQgPSAnZTE5MDMxMGYyZjNmNzFhYTg4NDZmMTE2MWNiY2UxNTMzYzI0YTg1N2RkMjRlNDUwMWIxMzFmZWI0MDBhYWQ1OCc7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgZmVlOiAxMzM2LFxuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDg2NjQsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICAgIHJlZGVlbVNjcmlwdDpcbiAgICAgICAgICAgICAgICAgICc1MjIxMDJjZDNjOGU2MDA2YTQ2Mjc3MDUwMjFkMWQwMTZkMDk3YzI5NDRkOTgxMDBhNDdiZjJkYTY3YTVmZTE1YWVlYjM0MjEwMmVlMWZhOWU4MTJlNzc5MzU2YWEzYzMxZWJmMzE3ZDBjZmZlYmFiOTI4NjRjZmUzOGJhYjIyM2UwODIwZjk4YmMyMTAyNmJhMDU3NTJiYWE2ZWFmZDVjNTY1OWRhNjJiN2YwYWM1MWZkMjg4NmI2NWMyNDFkMGFmZWYxYzRmZGZhMWNiYzUzYWUnLFxuICAgICAgICAgICAgICAgIGNoYWluUGF0aDogJy8wLzAnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogYWRkaXRpb25hbFVuc3BlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiAxLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAyMDAwMDAwMCxcbiAgICAgICAgICAgICAgICByZWRlZW1TY3JpcHQ6XG4gICAgICAgICAgICAgICAgICAnNTIyMTAyY2QzYzhlNjAwNmE0NjI3NzA1MDIxZDFkMDE2ZDA5N2MyOTQ0ZDk4MTAwYTQ3YmYyZGE2N2E1ZmUxNWFlZWIzNDIxMDJlZTFmYTllODEyZTc3OTM1NmFhM2MzMWViZjMxN2QwY2ZmZWJhYjkyODY0Y2ZlMzhiYWIyMjNlMDgyMGY5OGJjMjEwMjZiYTA1NzUyYmFhNmVhZmQ1YzU2NTlkYTYyYjdmMGFjNTFmZDI4ODZiNjVjMjQxZDBhZmVmMWM0ZmRmYTFjYmM1M2FlJyxcbiAgICAgICAgICAgICAgICBjaGFpblBhdGg6ICcvMC8wJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3BhcmVudFR4SWRdKTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YxL3R4L3NlbmQnLCAoYm9keSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICFib2R5Lmlnbm9yZU1heEZlZVJhdGU7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAucmVwbHkoMjAwLCBmdW5jdGlvbiAoXywgYm9keSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgdHJhbnNhY3Rpb246IChib2R5IGFzIGFueSkudHgsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGNoaWxkVHggPSBhd2FpdCB3YWxsZXQuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLFxuICAgICAgICAgIGZlZVJhdGUsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogVGVzdEJpdEdvLlRFU1RfV0FMTEVUMV9QQVNTQ09ERSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KGNoaWxkVHgpO1xuICAgICAgICBjaGlsZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGF0dXMnLCAnYWNjZXB0ZWQnKTtcbiAgICAgICAgY2hpbGRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHgnKTtcblxuICAgICAgICAvLyBhc3NlcnQgdGhlIGZvbGxvd2luZzpcbiAgICAgICAgLy8gMCkgVGhlIGNoaWxkIHR4IGhhcyBleGFjdGx5IHR3byBpbnB1dHNcbiAgICAgICAgLy8gMSkgVGhlIHBhcmVudCB0eCBvdXRwdXQgaXMgYW4gaW5wdXRcbiAgICAgICAgLy8gMikgVGhlIGFkZGl0aW9uYWwgdW5zcGVudCBvdXRwdXQgaXMgYW4gaW5wdXRcbiAgICAgICAgLy8gMykgVGhlIGNoaWxkIHR4IGhhcyBleGFjdGx5IG9uZSBvdXRwdXRcbiAgICAgICAgLy8gNCkgVGhlIGNoaWxkIHR4IG91dHB1dCBtZWV0cyB0aGUgbWluaW11bSBjaGFuZ2UgdGhyZXNob2xkXG4gICAgICAgIGNvbnN0IGRlY29kZWRDaGlsZCA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4KGNoaWxkVHgudHgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICAgIGRlY29kZWRDaGlsZC5pbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgICAgZGVjb2RlZENoaWxkLm91dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICBsZXQgaW5wdXRGcm9tUGFyZW50OiBhbnkgPSB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBhZGRpdGlvbmFsSW5wdXQ6IGFueSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBfLmZvckVhY2goZGVjb2RlZENoaWxkLmlucywgKGlucHV0KSA9PiB7XG4gICAgICAgICAgaW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2hhc2gnKTtcbiAgICAgICAgICBpbnB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaW5kZXgnKTtcblxuICAgICAgICAgIGNvbnN0IGlucHV0SGFzaCA9IGlucHV0UGFyZW50VHhJZChpbnB1dCk7XG5cbiAgICAgICAgICBpZiAoaW5wdXRIYXNoID09PSBwYXJlbnRUeElkKSB7XG4gICAgICAgICAgICBpbnB1dEZyb21QYXJlbnQgPSBpbnB1dDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWRkaXRpb25hbElucHV0ID0gaW5wdXQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBzaG91bGQuZXhpc3QoaW5wdXRGcm9tUGFyZW50KTtcbiAgICAgICAgY29uc3QgaW5wdXRGcm9tUGFyZW50SGFzaCA9IGlucHV0UGFyZW50VHhJZChpbnB1dEZyb21QYXJlbnQpO1xuICAgICAgICBpbnB1dEZyb21QYXJlbnRIYXNoLnNob3VsZC5lcXVhbChwYXJlbnRUeElkKTtcbiAgICAgICAgaW5wdXRGcm9tUGFyZW50LmluZGV4LnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgICBzaG91bGQuZXhpc3QoYWRkaXRpb25hbElucHV0KTtcbiAgICAgICAgY29uc3QgYWRkaXRpb25hbElucHV0SGFzaCA9IGlucHV0UGFyZW50VHhJZChhZGRpdGlvbmFsSW5wdXQpO1xuICAgICAgICBhZGRpdGlvbmFsSW5wdXRIYXNoLnNob3VsZC5lcXVhbChhZGRpdGlvbmFsVW5zcGVudFR4SWQpO1xuICAgICAgICBhZGRpdGlvbmFsSW5wdXQuaW5kZXguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAgIGNvbnN0IGNoaWxkT3V0cHV0ID0gZGVjb2RlZENoaWxkLm91dHNbMF07XG4gICAgICAgIGNoaWxkT3V0cHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd2YWx1ZScpO1xuICAgICAgICBjaGlsZE91dHB1dC52YWx1ZS5zaG91bGQuYmUuYWJvdmUobWluQ2hhbmdlU2l6ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2FjY2VsZXJhdGVzIGEgc3R1Y2sgdHggd2l0aCB0d28gYWRkaXRpb25hbCB1bnNwZW50cyAoc2Vnd2l0IGFuZCBQMlNIKScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcGFyZW50VHhJZCA9ICc4ODE1ZjIwMmM4NjU0YjZjOGIyOTU3NDk1NDVjNzExODc4Y2Q4NDVhMTRjYjFlYTk4MjM5NGQwYzE0OTQ1YzMzJztcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBmZWU6IDEzMzYsXG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2b3V0OiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDAwMCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDExLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogODY2NCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDEsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogcGFyZW50VHhJZCxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgICAgcmVkZWVtU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMmNkM2M4ZTYwMDZhNDYyNzcwNTAyMWQxZDAxNmQwOTdjMjk0NGQ5ODEwMGE0N2JmMmRhNjdhNWZlMTVhZWViMzQyMTAyZWUxZmE5ZTgxMmU3NzkzNTZhYTNjMzFlYmYzMTdkMGNmZmViYWI5Mjg2NGNmZTM4YmFiMjIzZTA4MjBmOThiYzIxMDI2YmEwNTc1MmJhYTZlYWZkNWM1NjU5ZGE2MmI3ZjBhYzUxZmQyODg2YjY1YzI0MWQwYWZlZjFjNGZkZmExY2JjNTNhZScsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzAvMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiAnZTE5MDMxMGYyZjNmNzFhYTg4NDZmMTE2MWNiY2UxNTMzYzI0YTg1N2RkMjRlNDUwMWIxMzFmZWI0MDBhYWQ1OCcsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDgwMDAwMCxcbiAgICAgICAgICAgICAgICByZWRlZW1TY3JpcHQ6XG4gICAgICAgICAgICAgICAgICAnNTIyMTAyY2QzYzhlNjAwNmE0NjI3NzA1MDIxZDFkMDE2ZDA5N2MyOTQ0ZDk4MTAwYTQ3YmYyZGE2N2E1ZmUxNWFlZWIzNDIxMDJlZTFmYTllODEyZTc3OTM1NmFhM2MzMWViZjMxN2QwY2ZmZWJhYjkyODY0Y2ZlMzhiYWIyMjNlMDgyMGY5OGJjMjEwMjZiYTA1NzUyYmFhNmVhZmQ1YzU2NTlkYTYyYjdmMGFjNTFmZDI4ODZiNjVjMjQxZDBhZmVmMWM0ZmRmYTFjYmM1M2FlJyxcbiAgICAgICAgICAgICAgICBjaGFpblBhdGg6ICcvMC8wJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6ICcwN2Q2ZWU1N2IwMjRjZTJiNjEwOGY2Nzg0NzQ1NGEwYTc5YTRmY2ZiOThhYjI1NTU1M2EyOTkzYTFhMTcwYjg3JyxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMjAwMDYyODQsXG4gICAgICAgICAgICAgICAgcmVkZWVtU2NyaXB0OiAnMDAyMGQzNGVmNmRkMzRlZjJhNGZiZWE2N2M1NDFjMWM3OTY3NDlhNjBhZmU0YTk3ZmVlOGVjN2RlZDE4OGJkNzQ5ZGEnLFxuICAgICAgICAgICAgICAgIGNoYWluUGF0aDogJy8xMS8xNTUnLFxuICAgICAgICAgICAgICAgIHdpdG5lc3NTY3JpcHQ6XG4gICAgICAgICAgICAgICAgICAnNTIyMTAyMjE5ZDJhYTg0MTc2MzNmMGJjZTM5MTEzNzRhMTYwNGMxYjY0MTYxZjgzYTNjMmVlNDA5YzI3YzQyMzU1ZjA4ZTIxMDJjOTczNDkyMGRjNGRhMDZjMjg5ZmU2OTE3MWRmY2Q3NWUzYjliNGYxOTBkMGNiYzNkNWQwZmYzZjVmZGVlYWFlMjEwM2NjZDY4ZDdmYThkYzBkMDJkZDQ1ZGFkMTY1NTU3YTQ4NTgyZWRhNDQzNWZhZTczNzdiM2MzMWUwOGFkMDY1Yzk1M2FlJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3BhcmVudFR4SWRdKTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YxL3R4L3NlbmQnLCAoYm9keSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICFib2R5Lmlnbm9yZU1heEZlZVJhdGU7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAucmVwbHkoMjAwLCBmdW5jdGlvbiAoXywgYm9keSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgdHJhbnNhY3Rpb246IChib2R5IGFzIGFueSkudHgsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGNoaWxkVHggPSBhd2FpdCB3YWxsZXQuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRlc3RCaXRHby5URVNUX1dBTExFVDFfUEFTU0NPREUsXG4gICAgICAgICAgZmVlUmF0ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KGNoaWxkVHgpO1xuICAgICAgICBjaGlsZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzdGF0dXMnLCAnYWNjZXB0ZWQnKTtcbiAgICAgICAgY2hpbGRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHgnKTtcblxuICAgICAgICAvLyBhc3NlcnQgdGhlIGZvbGxvd2luZzpcbiAgICAgICAgLy8gMCkgVGhlIGNoaWxkIHR4IGhhcyBleGFjdGx5IHRocmVlIGlucHV0c1xuICAgICAgICAvLyAxKSBUaGUgcGFyZW50IHR4IG91dHB1dCBpcyBhbiBpbnB1dFxuICAgICAgICAvLyAyKSBUaGUgY2hpbGQgdHggaGFzIGV4YWN0bHkgb25lIG91dHB1dFxuICAgICAgICAvLyAzKSBUaGUgY2hpbGQgdHggb3V0cHV0IG1lZXRzIHRoZSBtaW5pbXVtIGNoYW5nZSB0aHJlc2hvbGRcbiAgICAgICAgY29uc3QgZGVjb2RlZENoaWxkID0gdXR4b2xpYi5iaXRnby5jcmVhdGVUcmFuc2FjdGlvbkZyb21IZXgoY2hpbGRUeC50eCwgdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luKTtcbiAgICAgICAgZGVjb2RlZENoaWxkLmlucy5sZW5ndGguc2hvdWxkLmVxdWFsKDMpO1xuICAgICAgICBkZWNvZGVkQ2hpbGQub3V0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAgIGxldCBpbnB1dEZyb21QYXJlbnQ6IGFueSA9IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgYWRkaXRpb25hbElucHV0czogYW55W10gPSBbXTtcblxuICAgICAgICBfLmZvckVhY2goZGVjb2RlZENoaWxkLmlucywgKGlucHV0KSA9PiB7XG4gICAgICAgICAgaW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2hhc2gnKTtcbiAgICAgICAgICBpbnB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaW5kZXgnKTtcblxuICAgICAgICAgIGNvbnN0IGlucHV0SGFzaCA9IGlucHV0UGFyZW50VHhJZChpbnB1dCk7XG5cbiAgICAgICAgICBpZiAoaW5wdXRIYXNoID09PSBwYXJlbnRUeElkKSB7XG4gICAgICAgICAgICBpbnB1dEZyb21QYXJlbnQgPSBpbnB1dDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWRkaXRpb25hbElucHV0cy5wdXNoKGlucHV0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChpbnB1dEZyb21QYXJlbnQpO1xuICAgICAgICBjb25zdCBpbnB1dEZyb21QYXJlbnRIYXNoID0gaW5wdXRQYXJlbnRUeElkKGlucHV0RnJvbVBhcmVudCk7XG4gICAgICAgIGlucHV0RnJvbVBhcmVudEhhc2guc2hvdWxkLmVxdWFsKHBhcmVudFR4SWQpO1xuICAgICAgICBpbnB1dEZyb21QYXJlbnQuaW5kZXguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAgIGFkZGl0aW9uYWxJbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcblxuICAgICAgICBjb25zdCBjaGlsZE91dHB1dCA9IGRlY29kZWRDaGlsZC5vdXRzWzBdO1xuICAgICAgICBjaGlsZE91dHB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndmFsdWUnKTtcbiAgICAgICAgY2hpbGRPdXRwdXQudmFsdWUuc2hvdWxkLmJlLmFib3ZlKG1pbkNoYW5nZVNpemUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdjb3JyZWN0bHkgdXNlcyB0aGUgaWdub3JlTWF4RmVlUmF0ZSBwYXJhbWV0ZXIgb25seSB3aGVuIG5lY2Vzc2FyeScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcGFyZW50VHhJZCA9ICc3NWNmYzVhN2IyMTRjNGI3M2M5MmM3YjAyNjA4Y2RlNzBiMjI2NzY3YTk1NzZmODRjMDQ0MDdlNDNmZDM4NWJkJztcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBmZWU6IDQzNCxcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMzQ4NTAwLFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMTEsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiBwYXJlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDM0ODUwMCxcbiAgICAgICAgICAgICAgICByZWRlZW1TY3JpcHQ6ICcwMDIwZjdiNThkNDU1MzUxYjdiOGRkZDdjODk4NmQ5ODI0NGY2YTk1ZjA3NDY3MjAwOTE1MzczMjNiOTY3ODAwZjc0NCcsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzExLzE2MCcsXG4gICAgICAgICAgICAgICAgd2l0bmVzc1NjcmlwdDpcbiAgICAgICAgICAgICAgICAgICc1MjIxMDI3ZjBiNDViYjQxNTVlYTUzMmUzYjQzMTJmZTBiZTgwMTY2ZjI5N2QxZTA3NTNkMmQ0YTkxMThjMDczYWQ2NTE0MjEwMzEwYWE5ZDY4Yzk4ODMxNjI1ZjMyOWI3ODI2YjZjM2UzYjUzZTE2NzM2YjE5OTRiODkwMjQ0MmJkY2Q2NjUzZDEyMTAyNmUwY2E0MTRmMjQ4OGIwYWI1NzJiOTllMGFlNTQ0MjkxMWFiNGUwODIxYjI3MDlkODg1MTc1YTUyN2ZkNTUyYjUzYWUnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGV4cGxvcmVyVXJsKS5nZXQoYC90eC8ke3BhcmVudFR4SWR9L2hleGApLnJlcGx5KDIwMCwgZml4dHVyZXNbcGFyZW50VHhJZF0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjEvdHgvc2VuZCcsIChib2R5KSA9PiB7XG4gICAgICAgICAgICAvLyBpZ25vcmUgbWF4IGZlZSByYXRlIG11c3QgYmUgc2V0IGZvciB0aGlzIHRlc3RcbiAgICAgICAgICAgIHJldHVybiBib2R5Lmlnbm9yZU1heEZlZVJhdGU7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAucmVwbHkoMjAwKTtcblxuICAgICAgICAvLyBtb25rZXkgcGF0Y2ggdGhlIGJpdGdvIGdldENvbnN0YW50cygpIGZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IG9sZEdldENvbnN0YW50cyA9IChiaXRnbyBhcyBhbnkpLl9fcHJvdG9fXy5nZXRDb25zdGFudHM7XG4gICAgICAgIChiaXRnbyBhcyBhbnkpLl9fcHJvdG9fXy5nZXRDb25zdGFudHMgPSAoKSA9PiAoe1xuICAgICAgICAgIC8vIGNoaWxkIGZlZSByYXRlIGluIHRoaXMgdGVzdCBpcyAzMTM3OCBzYXQva2JcbiAgICAgICAgICAvLyBzbyBzZXQgdGhlIG1heCBmZWUgcmF0ZSBqdXN0IGJlbG93IHRoYXQgbGltaXQsXG4gICAgICAgICAgLy8gYnV0IGFib3ZlIHRoZSBjb21iaW5lZCBmZWUgcmF0ZSBvZiAyMDAwMFxuICAgICAgICAgIG1heEZlZVJhdGU6IDMwMDAwLFxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCB3YWxsZXQuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLFxuICAgICAgICAgIGZlZVJhdGUsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogVGVzdEJpdEdvLlRFU1RfV0FMTEVUMV9QQVNTQ09ERSxcbiAgICAgICAgfSk7XG4gICAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgICAgKGJpdGdvIGFzIGFueSkuX19wcm90b19fLmdldENvbnN0YW50cyA9IG9sZEdldENvbnN0YW50cztcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZ2V0Qml0R29GZWUnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGJnVXJsOiBzdHJpbmc7XG4gICAgbGV0IHdhbGxldDogYW55O1xuXG4gICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgICBjb25zdCBwcm9kQml0Z28gPSBuZXcgQml0R29BUEkoeyBlbnY6ICdwcm9kJywgY2xpZW50Q29uc3RhbnRzOiB7IGNvbnN0YW50czoge30gfSB9KTtcbiAgICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1twcm9kQml0Z28uZ2V0RW52KCldLnVyaTtcbiAgICAgIHdhbGxldCA9IG5ldyBXYWxsZXQocHJvZEJpdGdvLCB7XG4gICAgICAgIGlkOiAnMk5Db1NmSEg2THM0Q2RUUzVRYWhnQzlrN3g5UmZYZVN3WTQnLFxuICAgICAgICBwcml2YXRlOiB7IGtleWNoYWluczogW3VzZXJLZXlwYWlyLCBiYWNrdXBLZXlwYWlyLCBiaXRnb0tleV0gfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzZW5kcyBhbW91bnQgYW5kIGluc3RhbnQgd2l0aG91dCByZWNpcGllbnRzIHdoZW4gcmVjaXBpZW50cyBhcnJheSBpcyBlbXB0eScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNjb3BlID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vYmlsbGluZy9mZWVgKVxuICAgICAgICAucXVlcnkoeyBhbW91bnQ6ICcxMDAwMDAnLCBpbnN0YW50OiAnZmFsc2UnIH0pXG4gICAgICAgIC5yZXBseSgyMDAsIHsgZmVlOiAxMDAwIH0pO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3YWxsZXQuZ2V0Qml0R29GZWUoeyBhbW91bnQ6IDEwMDAwMCwgaW5zdGFudDogZmFsc2UgfSk7XG4gICAgICByZXN1bHQuZmVlLnNob3VsZC5lcXVhbCgxMDAwKTtcbiAgICAgIHNjb3BlLmlzRG9uZSgpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2VuZHMgcmVjaXBpZW50c1tdIHF1ZXJ5IHBhcmFtcyB3aGVuIHJlY2lwaWVudHMgYXJlIHByb3ZpZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRkcjEgPSAnM0o5OHQxV3BFWjczQ05tUXZpZWNybnlpV3JucVJoV05MeSc7XG4gICAgICBjb25zdCBhZGRyMiA9ICczRlpiZ2kyOWNwanEyR2pkd1Y4ZXlIdUpKbmtMdGt0WmM1JztcblxuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS9iaWxsaW5nL2ZlZWApXG4gICAgICAgIC5xdWVyeSgocXVlcnkpID0+IHtcbiAgICAgICAgICBjb25zdCByZWNpcGllbnRzUGFyYW0gPSBxdWVyeVsncmVjaXBpZW50c1tdJ107XG4gICAgICAgICAgY29uc3QgcmVjaXBpZW50c0xpc3QgPSBBcnJheS5pc0FycmF5KHJlY2lwaWVudHNQYXJhbSkgPyByZWNpcGllbnRzUGFyYW0gOiBbcmVjaXBpZW50c1BhcmFtXTtcbiAgICAgICAgICByZXR1cm4gcXVlcnkuYW1vdW50ID09PSAnMTAwMDAwJyAmJiByZWNpcGllbnRzTGlzdC5pbmNsdWRlcyhhZGRyMSkgJiYgcmVjaXBpZW50c0xpc3QuaW5jbHVkZXMoYWRkcjIpO1xuICAgICAgICB9KVxuICAgICAgICAucmVwbHkoMjAwLCB7IGZlZTogMCB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LmdldEJpdEdvRmVlKHsgYW1vdW50OiAxMDAwMDAsIHJlY2lwaWVudHM6IFthZGRyMSwgYWRkcjJdIH0pO1xuICAgICAgcmVzdWx0LmZlZS5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ29taXRzIHJlY2lwaWVudHNbXSB3aGVuIHJlY2lwaWVudHMgYXJyYXkgaXMgZW1wdHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L2JpbGxpbmcvZmVlYClcbiAgICAgICAgLnF1ZXJ5KChxdWVyeSkgPT4gcXVlcnkuYW1vdW50ID09PSAnMjAwMDAwJyAmJiAhKCdyZWNpcGllbnRzW10nIGluIHF1ZXJ5KSlcbiAgICAgICAgLnJlcGx5KDIwMCwgeyBmZWU6IDUwMCB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LmdldEJpdEdvRmVlKHsgYW1vdW50OiAyMDAwMDAsIHJlY2lwaWVudHM6IFtdIH0pO1xuICAgICAgcmVzdWx0LmZlZS5zaG91bGQuZXF1YWwoNTAwKTtcbiAgICAgIHNjb3BlLmlzRG9uZSgpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIHdoZW4gYW1vdW50IGlzIG5vdCBhIG51bWJlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICgoKSA9PiB3YWxsZXQuZ2V0Qml0R29GZWUoeyBhbW91bnQ6ICdiYWQnIH0pKS5zaG91bGQudGhyb3coJ2ludmFsaWQgYW1vdW50IGFyZ3VtZW50Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIHdoZW4gaW5zdGFudCBpcyBub3QgYSBib29sZWFuJywgZnVuY3Rpb24gKCkge1xuICAgICAgKCgpID0+IHdhbGxldC5nZXRCaXRHb0ZlZSh7IGFtb3VudDogMTAwLCBpbnN0YW50OiAneWVzJyB9KSkuc2hvdWxkLnRocm93KCdpbnZhbGlkIGluc3RhbnQgYXJndW1lbnQnKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==