@bitgo-beta/sdk-coin-eth 4.4.1-beta.202 → 4.4.1-beta.2021

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 (122) hide show
  1. package/dist/src/erc20Token.d.ts +1 -1
  2. package/dist/src/erc20Token.d.ts.map +1 -1
  3. package/dist/src/erc20Token.js +49 -28
  4. package/dist/src/erc721Token.d.ts +60 -0
  5. package/dist/src/erc721Token.d.ts.map +1 -0
  6. package/dist/src/erc721Token.js +334 -0
  7. package/dist/src/erc7984Token.d.ts +187 -0
  8. package/dist/src/erc7984Token.d.ts.map +1 -0
  9. package/dist/src/erc7984Token.js +946 -0
  10. package/dist/src/eth.d.ts +10 -8
  11. package/dist/src/eth.d.ts.map +1 -1
  12. package/dist/src/eth.js +54 -39
  13. package/dist/src/index.d.ts +3 -0
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/index.js +9 -2
  16. package/dist/src/lib/index.d.ts +1 -0
  17. package/dist/src/lib/index.d.ts.map +1 -1
  18. package/dist/src/lib/index.js +7 -2
  19. package/dist/src/lib/messages/index.d.ts +3 -0
  20. package/dist/src/lib/messages/index.d.ts.map +1 -0
  21. package/dist/src/lib/messages/index.js +6 -0
  22. package/dist/src/lib/transactionBuilder.d.ts +10 -5
  23. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  24. package/dist/src/lib/transactionBuilder.js +17 -7
  25. package/dist/src/lib/transferBuilders/index.d.ts +2 -2
  26. package/dist/src/lib/transferBuilders/index.d.ts.map +1 -1
  27. package/dist/src/lib/transferBuilders/index.js +3 -2
  28. package/dist/src/register.d.ts +2 -0
  29. package/dist/src/register.d.ts.map +1 -1
  30. package/dist/src/register.js +39 -2
  31. package/dist/src/sepeth.d.ts +8 -0
  32. package/dist/src/sepeth.d.ts.map +1 -0
  33. package/dist/src/sepeth.js +14 -0
  34. package/dist/test/fixtures/eth.d.ts +39 -0
  35. package/dist/test/fixtures/eth.d.ts.map +1 -0
  36. package/dist/test/fixtures/eth.js +262 -0
  37. package/dist/test/resources/erc1155Abi.d.ts +40 -0
  38. package/dist/test/resources/erc1155Abi.d.ts.map +1 -0
  39. package/dist/test/resources/erc1155Abi.js +329 -0
  40. package/dist/test/resources/erc721Abi.d.ts +12 -0
  41. package/dist/test/resources/erc721Abi.d.ts.map +1 -0
  42. package/dist/test/resources/erc721Abi.js +34 -0
  43. package/dist/test/resources/eth.d.ts +51 -0
  44. package/dist/test/resources/eth.d.ts.map +1 -0
  45. package/dist/test/resources/eth.js +72 -0
  46. package/dist/test/resources/nftEncodings.d.ts +4 -0
  47. package/dist/test/resources/nftEncodings.d.ts.map +1 -0
  48. package/dist/test/resources/nftEncodings.js +7 -0
  49. package/dist/test/resources/walletSimpleAbi.d.ts +12 -0
  50. package/dist/test/resources/walletSimpleAbi.d.ts.map +1 -0
  51. package/dist/test/resources/walletSimpleAbi.js +44 -0
  52. package/dist/test/unit/erc7984Token.d.ts +2 -0
  53. package/dist/test/unit/erc7984Token.d.ts.map +1 -0
  54. package/dist/test/unit/erc7984Token.js +1589 -0
  55. package/dist/test/unit/eth.d.ts +2 -0
  56. package/dist/test/unit/eth.d.ts.map +1 -0
  57. package/dist/test/unit/eth.js +2701 -0
  58. package/dist/test/unit/ethWallet.d.ts +2 -0
  59. package/dist/test/unit/ethWallet.d.ts.map +1 -0
  60. package/dist/test/unit/ethWallet.js +552 -0
  61. package/dist/test/unit/fixtures/ethMultiSigBackupKey.d.ts +4 -0
  62. package/dist/test/unit/fixtures/ethMultiSigBackupKey.d.ts.map +1 -0
  63. package/dist/test/unit/fixtures/ethMultiSigBackupKey.js +10 -0
  64. package/dist/test/unit/fixtures/ethTssBackupKey.d.ts +5 -0
  65. package/dist/test/unit/fixtures/ethTssBackupKey.d.ts.map +1 -0
  66. package/dist/test/unit/fixtures/ethTssBackupKey.js +25 -0
  67. package/dist/test/unit/getBuilder.d.ts +3 -0
  68. package/dist/test/unit/getBuilder.d.ts.map +1 -0
  69. package/dist/test/unit/getBuilder.js +10 -0
  70. package/dist/test/unit/keyPair.d.ts +2 -0
  71. package/dist/test/unit/keyPair.d.ts.map +1 -0
  72. package/dist/test/unit/keyPair.js +175 -0
  73. package/dist/test/unit/register.d.ts +2 -0
  74. package/dist/test/unit/register.d.ts.map +1 -0
  75. package/dist/test/unit/register.js +75 -0
  76. package/dist/test/unit/transaction.d.ts +2 -0
  77. package/dist/test/unit/transaction.d.ts.map +1 -0
  78. package/dist/test/unit/transaction.js +117 -0
  79. package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +2 -0
  80. package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
  81. package/dist/test/unit/transactionBuilder/addressInitialization.js +101 -0
  82. package/dist/test/unit/transactionBuilder/contractCall.d.ts +2 -0
  83. package/dist/test/unit/transactionBuilder/contractCall.d.ts.map +1 -0
  84. package/dist/test/unit/transactionBuilder/contractCall.js +101 -0
  85. package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts +2 -0
  86. package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts.map +1 -0
  87. package/dist/test/unit/transactionBuilder/decryptionDelegation.js +59 -0
  88. package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.d.ts +2 -0
  89. package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.d.ts.map +1 -0
  90. package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.js +136 -0
  91. package/dist/test/unit/transactionBuilder/flushCoins.d.ts +2 -0
  92. package/dist/test/unit/transactionBuilder/flushCoins.d.ts.map +1 -0
  93. package/dist/test/unit/transactionBuilder/flushCoins.js +133 -0
  94. package/dist/test/unit/transactionBuilder/flushTokens.d.ts +2 -0
  95. package/dist/test/unit/transactionBuilder/flushTokens.d.ts.map +1 -0
  96. package/dist/test/unit/transactionBuilder/flushTokens.js +298 -0
  97. package/dist/test/unit/transactionBuilder/send.d.ts +2 -0
  98. package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
  99. package/dist/test/unit/transactionBuilder/send.js +331 -0
  100. package/dist/test/unit/transactionBuilder/sendERC7984Token.d.ts +2 -0
  101. package/dist/test/unit/transactionBuilder/sendERC7984Token.d.ts.map +1 -0
  102. package/dist/test/unit/transactionBuilder/sendERC7984Token.js +361 -0
  103. package/dist/test/unit/transactionBuilder/sendNFT.d.ts +2 -0
  104. package/dist/test/unit/transactionBuilder/sendNFT.d.ts.map +1 -0
  105. package/dist/test/unit/transactionBuilder/sendNFT.js +295 -0
  106. package/dist/test/unit/transactionBuilder/singleSigSend.d.ts +2 -0
  107. package/dist/test/unit/transactionBuilder/singleSigSend.d.ts.map +1 -0
  108. package/dist/test/unit/transactionBuilder/singleSigSend.js +196 -0
  109. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +2 -0
  110. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
  111. package/dist/test/unit/transactionBuilder/walletInitialization.js +436 -0
  112. package/dist/test/unit/transferBuilder.d.ts +2 -0
  113. package/dist/test/unit/transferBuilder.d.ts.map +1 -0
  114. package/dist/test/unit/transferBuilder.js +124 -0
  115. package/dist/test/unit/utils.d.ts +2 -0
  116. package/dist/test/unit/utils.d.ts.map +1 -0
  117. package/dist/test/unit/utils.js +74 -0
  118. package/dist/tsconfig.tsbuildinfo +1 -0
  119. package/package.json +17 -13
  120. package/.eslintignore +0 -5
  121. package/.mocharc.yml +0 -8
  122. package/CHANGELOG.md +0 -771
@@ -0,0 +1,1589 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ /**
40
+ * Unit tests for Erc7984Token.
41
+ *
42
+ * Covers:
43
+ * - getTokenEnablementConfig
44
+ * - verifyTransaction (TSS and multisig paths)
45
+ * - verifyTransaction (confidential transfer / SendERC7984 path)
46
+ * - decodeTokenAddressesFromDelegationCalldata (round-trip and forwarder-wrapped)
47
+ * - recover() (ERC-7984 confidential token recovery)
48
+ * - queryConfidentialBalance()
49
+ */
50
+ const should_1 = __importDefault(require("should"));
51
+ const sinon_1 = __importDefault(require("sinon"));
52
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
53
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
54
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
55
+ const abstract_eth_1 = require("@bitgo-beta/abstract-eth");
56
+ const getBuilder_1 = require("./getBuilder");
57
+ const register_1 = require("../../src/register");
58
+ const testData = __importStar(require("../resources/eth"));
59
+ // ---------------------------------------------------------------------------
60
+ // Constants
61
+ // ---------------------------------------------------------------------------
62
+ // Hoodi ACL contract address (Networks.test.hoodi.zamaAclContractAddress)
63
+ const ZAMA_ACL_ADDRESS = '0x6d3faf6f86e1ff9f3b0831dda920aba1cbd5bd68';
64
+ const DELEGATE_ADDRESS = '0x1111111111111111111111111111111111111111';
65
+ // hteth:ctest1 token contract address (from statics/erc7984Tokens.ts)
66
+ const CTEST1_TOKEN_ADDRESS = '0x7b1d59bbcd291daa59cb6c8c5bc04de1afc4aba1';
67
+ // hteth:cusdt token contract address (from statics/erc7984Tokens.ts)
68
+ const CUSDT_TOKEN_ADDRESS = '0x2debbe0487ef921df4457f9e36ed05be2df1ac75';
69
+ const WRONG_TOKEN_ADDRESS = '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
70
+ const WRONG_ACL_ADDRESS = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
71
+ const FORWARDER_ADDRESS = '0x1234567890123456789012345678901234567890';
72
+ const EXPIRY = Math.floor(Date.now() / 1000) + 365 * 86400;
73
+ // ---------------------------------------------------------------------------
74
+ // Helpers
75
+ // ---------------------------------------------------------------------------
76
+ /**
77
+ * Builds a root-wallet delegation tx hex (to = ACL, data = multicall).
78
+ */
79
+ async function buildDelegationTxHex(aclAddress, tokenAddresses, value = '0') {
80
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
81
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
82
+ txBuilder.counter(1);
83
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
84
+ txBuilder.contract(aclAddress);
85
+ const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, tokenAddresses, EXPIRY);
86
+ txBuilder.data(calldata);
87
+ if (value !== '0') {
88
+ txBuilder.value(value);
89
+ }
90
+ const tx = await txBuilder.build();
91
+ return tx.toBroadcastFormat();
92
+ }
93
+ /**
94
+ * Builds a forwarder delegation tx hex (to = forwarder, data = callFromParent(ACL, 0, multicall)).
95
+ * This mirrors what DecryptionDelegationBuilder.build() returns when forwarderAddress is set.
96
+ */
97
+ async function buildForwarderDelegationTxHex(forwarderAddress, aclAddress, tokenAddresses) {
98
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
99
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
100
+ txBuilder.counter(1);
101
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
102
+ txBuilder.contract(forwarderAddress);
103
+ const innerCalldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, tokenAddresses, EXPIRY);
104
+ const outerCalldata = (0, abstract_eth_1.wrapInCallFromParent)(aclAddress, innerCalldata);
105
+ txBuilder.data(outerCalldata);
106
+ const tx = await txBuilder.build();
107
+ return tx.toBroadcastFormat();
108
+ }
109
+ // ---------------------------------------------------------------------------
110
+ // Tests
111
+ // ---------------------------------------------------------------------------
112
+ describe('Erc7984Token', function () {
113
+ let bitgo;
114
+ let coin;
115
+ before(function () {
116
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
117
+ bitgo.initializeTestVars();
118
+ (0, register_1.register)(bitgo);
119
+ coin = bitgo.coin('hteth:ctest1');
120
+ });
121
+ // -------------------------------------------------------------------------
122
+ describe('getTokenEnablementConfig', function () {
123
+ it('should return requiresTokenEnablement: true', function () {
124
+ const config = coin.getTokenEnablementConfig();
125
+ config.requiresTokenEnablement.should.equal(true);
126
+ });
127
+ it('should return supportsMultipleTokenEnablements: true', function () {
128
+ const config = coin.getTokenEnablementConfig();
129
+ config.supportsMultipleTokenEnablements.should.equal(true);
130
+ });
131
+ });
132
+ // -------------------------------------------------------------------------
133
+ describe('verifyTransaction – non-enable-token', function () {
134
+ it('should route to confidential transfer path when type is not enabletoken', async function () {
135
+ // Non-enabletoken transactions route to verifyConfidentialTransfer.
136
+ // Empty recipients triggers our ERC7984-specific validation error,
137
+ // confirming the override only intercepts the enabletoken type.
138
+ await coin
139
+ .verifyTransaction({
140
+ txParams: { recipients: [] },
141
+ txPrebuild: {},
142
+ wallet: {},
143
+ })
144
+ .should.be.rejectedWith(/recipients must contain at least one entry/);
145
+ });
146
+ });
147
+ // -------------------------------------------------------------------------
148
+ describe('verifyTransaction – TSS path', function () {
149
+ it('should verify a valid single-token delegation tx', async function () {
150
+ const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
151
+ const result = await coin.verifyTransaction({
152
+ txParams: {
153
+ type: 'enabletoken',
154
+ enableTokens: [{ name: 'hteth:ctest1' }],
155
+ },
156
+ txPrebuild: { txHex },
157
+ wallet: {},
158
+ walletType: 'tss',
159
+ });
160
+ result.should.equal(true);
161
+ });
162
+ it('should verify a valid multi-token delegation tx', async function () {
163
+ const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS, CUSDT_TOKEN_ADDRESS]);
164
+ const result = await coin.verifyTransaction({
165
+ txParams: {
166
+ type: 'enabletoken',
167
+ enableTokens: [{ name: 'hteth:ctest1' }, { name: 'hteth:cusdt' }],
168
+ },
169
+ txPrebuild: { txHex },
170
+ wallet: {},
171
+ walletType: 'tss',
172
+ });
173
+ result.should.equal(true);
174
+ });
175
+ it('should throw when ACL address does not match', async function () {
176
+ const txHex = await buildDelegationTxHex(WRONG_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
177
+ await coin
178
+ .verifyTransaction({
179
+ txParams: {
180
+ type: 'enabletoken',
181
+ enableTokens: [{ name: 'hteth:ctest1' }],
182
+ },
183
+ txPrebuild: { txHex },
184
+ wallet: {},
185
+ walletType: 'tss',
186
+ })
187
+ .should.be.rejectedWith(/does not match ACL contract/);
188
+ });
189
+ it('should throw when calldata contains wrong token address', async function () {
190
+ const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [WRONG_TOKEN_ADDRESS]);
191
+ await coin
192
+ .verifyTransaction({
193
+ txParams: {
194
+ type: 'enabletoken',
195
+ enableTokens: [{ name: 'hteth:ctest1' }],
196
+ },
197
+ txPrebuild: { txHex },
198
+ wallet: {},
199
+ walletType: 'tss',
200
+ })
201
+ .should.be.rejectedWith(/not found in delegation calldata/);
202
+ });
203
+ it('should verify a valid forwarder delegation tx (callFromParent shape)', async function () {
204
+ const txHex = await buildForwarderDelegationTxHex(FORWARDER_ADDRESS, ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
205
+ const result = await coin.verifyTransaction({
206
+ txParams: {
207
+ type: 'enabletoken',
208
+ enableTokens: [{ name: 'hteth:ctest1' }],
209
+ },
210
+ txPrebuild: { txHex },
211
+ wallet: {},
212
+ walletType: 'tss',
213
+ });
214
+ result.should.equal(true);
215
+ });
216
+ it('should verify a forwarder delegation tx with multiple tokens', async function () {
217
+ const txHex = await buildForwarderDelegationTxHex(FORWARDER_ADDRESS, ZAMA_ACL_ADDRESS, [
218
+ CTEST1_TOKEN_ADDRESS,
219
+ CUSDT_TOKEN_ADDRESS,
220
+ ]);
221
+ const result = await coin.verifyTransaction({
222
+ txParams: {
223
+ type: 'enabletoken',
224
+ enableTokens: [{ name: 'hteth:ctest1' }, { name: 'hteth:cusdt' }],
225
+ },
226
+ txPrebuild: { txHex },
227
+ wallet: {},
228
+ walletType: 'tss',
229
+ });
230
+ result.should.equal(true);
231
+ });
232
+ it('should throw when forwarder calldata contains wrong token address', async function () {
233
+ const txHex = await buildForwarderDelegationTxHex(FORWARDER_ADDRESS, ZAMA_ACL_ADDRESS, [WRONG_TOKEN_ADDRESS]);
234
+ await coin
235
+ .verifyTransaction({
236
+ txParams: {
237
+ type: 'enabletoken',
238
+ enableTokens: [{ name: 'hteth:ctest1' }],
239
+ },
240
+ txPrebuild: { txHex },
241
+ wallet: {},
242
+ walletType: 'tss',
243
+ })
244
+ .should.be.rejectedWith(/not found in delegation calldata/);
245
+ });
246
+ it('should throw when calldata has unrecognised method ID', async function () {
247
+ // Build a tx with arbitrary calldata that is neither multicall nor callFromParent
248
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
249
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
250
+ txBuilder.counter(1);
251
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
252
+ txBuilder.contract(ZAMA_ACL_ADDRESS);
253
+ txBuilder.data('0xdeadbeef');
254
+ const tx = await txBuilder.build();
255
+ const txHex = tx.toBroadcastFormat();
256
+ await coin
257
+ .verifyTransaction({
258
+ txParams: {
259
+ type: 'enabletoken',
260
+ enableTokens: [{ name: 'hteth:ctest1' }],
261
+ },
262
+ txPrebuild: { txHex },
263
+ wallet: {},
264
+ walletType: 'tss',
265
+ })
266
+ .should.be.rejectedWith(/unrecognised calldata method ID/);
267
+ });
268
+ it('should throw when transaction value is not 0', async function () {
269
+ const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS], '1');
270
+ await coin
271
+ .verifyTransaction({
272
+ txParams: {
273
+ type: 'enabletoken',
274
+ enableTokens: [{ name: 'hteth:ctest1' }],
275
+ },
276
+ txPrebuild: { txHex },
277
+ wallet: {},
278
+ walletType: 'tss',
279
+ })
280
+ .should.be.rejectedWith(/expected transaction value 0/);
281
+ });
282
+ it('should throw when enableTokens is empty', async function () {
283
+ const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
284
+ await coin
285
+ .verifyTransaction({
286
+ txParams: {
287
+ type: 'enabletoken',
288
+ enableTokens: [],
289
+ },
290
+ txPrebuild: { txHex },
291
+ wallet: {},
292
+ walletType: 'tss',
293
+ })
294
+ .should.be.rejectedWith(/enableTokens must be non-empty/);
295
+ });
296
+ it('should throw when txHex is missing', async function () {
297
+ await coin
298
+ .verifyTransaction({
299
+ txParams: {
300
+ type: 'enabletoken',
301
+ enableTokens: [{ name: 'hteth:ctest1' }],
302
+ },
303
+ txPrebuild: {},
304
+ wallet: {},
305
+ walletType: 'tss',
306
+ })
307
+ .should.be.rejectedWith(/missing txHex/);
308
+ });
309
+ });
310
+ // -------------------------------------------------------------------------
311
+ describe('verifyTransaction – multisig path', function () {
312
+ it('should verify valid buildParams recipients', async function () {
313
+ const result = await coin.verifyTransaction({
314
+ txParams: {
315
+ type: 'enabletoken',
316
+ recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
317
+ },
318
+ txPrebuild: {
319
+ buildParams: {
320
+ type: 'enabletoken',
321
+ recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
322
+ },
323
+ },
324
+ wallet: {},
325
+ walletType: 'onchain',
326
+ });
327
+ result.should.equal(true);
328
+ });
329
+ it('should verify multiple token recipients', async function () {
330
+ const result = await coin.verifyTransaction({
331
+ txParams: {
332
+ type: 'enabletoken',
333
+ recipients: [
334
+ { tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' },
335
+ { tokenName: 'hteth:cusdt', address: '0xabc', amount: '0' },
336
+ ],
337
+ },
338
+ txPrebuild: {
339
+ buildParams: {
340
+ type: 'enabletoken',
341
+ recipients: [
342
+ { tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' },
343
+ { tokenName: 'hteth:cusdt', address: '0xabc', amount: '0' },
344
+ ],
345
+ },
346
+ },
347
+ wallet: {},
348
+ walletType: 'onchain',
349
+ });
350
+ result.should.equal(true);
351
+ });
352
+ it('should throw when buildParams recipients have wrong tokenName', async function () {
353
+ await coin
354
+ .verifyTransaction({
355
+ txParams: {
356
+ type: 'enabletoken',
357
+ recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
358
+ },
359
+ txPrebuild: {
360
+ buildParams: {
361
+ type: 'enabletoken',
362
+ recipients: [{ tokenName: 'hteth:wrongtoken', address: '0xabc', amount: '0' }],
363
+ },
364
+ },
365
+ wallet: {},
366
+ walletType: 'onchain',
367
+ })
368
+ .should.be.rejectedWith(/not found in buildParams recipients/);
369
+ });
370
+ it('should throw when amount is not 0', async function () {
371
+ await coin
372
+ .verifyTransaction({
373
+ txParams: {
374
+ type: 'enabletoken',
375
+ recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
376
+ },
377
+ txPrebuild: {
378
+ buildParams: {
379
+ type: 'enabletoken',
380
+ recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '100' }],
381
+ },
382
+ },
383
+ wallet: {},
384
+ walletType: 'onchain',
385
+ })
386
+ .should.be.rejectedWith(/expected amount 0/);
387
+ });
388
+ it('should throw when recipients is missing', async function () {
389
+ await coin
390
+ .verifyTransaction({
391
+ txParams: {
392
+ type: 'enabletoken',
393
+ },
394
+ txPrebuild: {
395
+ buildParams: {},
396
+ },
397
+ wallet: {},
398
+ walletType: 'onchain',
399
+ })
400
+ .should.be.rejectedWith(/missing buildParams.recipients/);
401
+ });
402
+ });
403
+ });
404
+ // ---------------------------------------------------------------------------
405
+ // verifyTransaction – confidential transfer (SendERC7984) tests
406
+ // ---------------------------------------------------------------------------
407
+ /**
408
+ * Build a raw signed sendMultiSig tx hex that wraps a confidentialTransfer call.
409
+ * The wallet contract (sendMultiSig wrapper) is `walletContractAddress`.
410
+ */
411
+ async function buildConfidentialTransferTxHex(opts) {
412
+ const key = testData.KEYPAIR_PRV.getKeys().prv;
413
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
414
+ txBuilder.fee({ fee: '1000000000', gasLimit: '12100000' });
415
+ txBuilder.counter(1);
416
+ txBuilder.contract(opts.walletContractAddress);
417
+ txBuilder.type(sdk_core_1.TransactionType.SendERC7984);
418
+ const transferBuilder = txBuilder.transfer();
419
+ transferBuilder
420
+ .from('0x19645032c7f1533395d44a629462e751084d3e4d')
421
+ .to(opts.recipientAddress)
422
+ .tokenContractAddress(opts.tokenContractAddress)
423
+ .encryptedHandle(opts.encryptedHandle)
424
+ .inputProof(opts.inputProof)
425
+ .contractSequenceId(1)
426
+ .expirationTime(Math.floor(Date.now() / 1000) + 3600)
427
+ .key(key);
428
+ txBuilder.sign({ key: testData.PRIVATE_KEY });
429
+ const tx = await txBuilder.build();
430
+ return tx.toBroadcastFormat();
431
+ }
432
+ describe('verifyTransaction – confidential transfer (SendERC7984)', function () {
433
+ // Wallet contract that wraps the sendMultiSig call
434
+ const WALLET_CONTRACT = '0x8f977e912ef500548a0c3be6ddde9899f1199b81';
435
+ // Recipient of the confidential transfer
436
+ const RECIPIENT = '0x19645032c7f1533395d44a629462e751084d3e4c';
437
+ // Encrypted handle: synthetic 32 bytes
438
+ const HANDLE = '0x' + 'ab'.repeat(32);
439
+ // Input proof: synthetic 50 bytes
440
+ const PROOF = '0x' + 'cd'.repeat(50);
441
+ // A different recipient to trigger mismatch
442
+ const WRONG_RECIPIENT = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
443
+ // A different token contract to trigger mismatch
444
+ const WRONG_TOKEN = '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
445
+ let bitgo;
446
+ let coin;
447
+ before(function () {
448
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
449
+ bitgo.initializeTestVars();
450
+ (0, register_1.register)(bitgo);
451
+ coin = bitgo.coin('hteth:ctest1');
452
+ });
453
+ // Representative plaintext amount in base units (e.g., 1 cTEST1 = 1_000_000 units at 6 decimals)
454
+ const AMOUNT = '1000000';
455
+ it('should verify a valid confidential transfer transaction with matching amounts', async function () {
456
+ const txHex = await buildConfidentialTransferTxHex({
457
+ walletContractAddress: WALLET_CONTRACT,
458
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
459
+ recipientAddress: RECIPIENT,
460
+ encryptedHandle: HANDLE,
461
+ inputProof: PROOF,
462
+ });
463
+ const result = await coin.verifyTransaction({
464
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
465
+ txPrebuild: { txHex, buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] } },
466
+ wallet: {},
467
+ });
468
+ result.should.equal(true);
469
+ });
470
+ it('should throw when no recipient info is provided in either txParams or buildParams', async function () {
471
+ const txHex = await buildConfidentialTransferTxHex({
472
+ walletContractAddress: WALLET_CONTRACT,
473
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
474
+ recipientAddress: RECIPIENT,
475
+ encryptedHandle: HANDLE,
476
+ inputProof: PROOF,
477
+ });
478
+ await coin
479
+ .verifyTransaction({
480
+ txParams: {},
481
+ txPrebuild: { txHex },
482
+ wallet: {},
483
+ })
484
+ .should.be.rejectedWith(/missing expected recipient/);
485
+ });
486
+ it('should verify successfully using buildParams.recipients when txParams has no recipients', async function () {
487
+ const txHex = await buildConfidentialTransferTxHex({
488
+ walletContractAddress: WALLET_CONTRACT,
489
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
490
+ recipientAddress: RECIPIENT,
491
+ encryptedHandle: HANDLE,
492
+ inputProof: PROOF,
493
+ });
494
+ const result = await coin.verifyTransaction({
495
+ txParams: {},
496
+ txPrebuild: {
497
+ txHex,
498
+ buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
499
+ },
500
+ wallet: {},
501
+ });
502
+ result.should.equal(true);
503
+ });
504
+ it('should throw when token contract address does not match this coin', async function () {
505
+ const txHex = await buildConfidentialTransferTxHex({
506
+ walletContractAddress: WALLET_CONTRACT,
507
+ tokenContractAddress: WRONG_TOKEN,
508
+ recipientAddress: RECIPIENT,
509
+ encryptedHandle: HANDLE,
510
+ inputProof: PROOF,
511
+ });
512
+ await coin
513
+ .verifyTransaction({
514
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
515
+ txPrebuild: { txHex },
516
+ wallet: {},
517
+ })
518
+ .should.be.rejectedWith(/token contract address mismatch/);
519
+ });
520
+ it('should throw when recipient address does not match txParams', async function () {
521
+ const txHex = await buildConfidentialTransferTxHex({
522
+ walletContractAddress: WALLET_CONTRACT,
523
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
524
+ recipientAddress: RECIPIENT,
525
+ encryptedHandle: HANDLE,
526
+ inputProof: PROOF,
527
+ });
528
+ await coin
529
+ .verifyTransaction({
530
+ txParams: { recipients: [{ address: WRONG_RECIPIENT, amount: AMOUNT }] },
531
+ txPrebuild: { txHex },
532
+ wallet: {},
533
+ })
534
+ .should.be.rejectedWith(/recipient address mismatch/);
535
+ });
536
+ it('should throw when calldata is not a confidential transfer', async function () {
537
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
538
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
539
+ txBuilder.counter(1);
540
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
541
+ txBuilder.contract(WALLET_CONTRACT);
542
+ txBuilder.data('0xdeadbeef00000000000000000000000000000000000000000000000000000000');
543
+ const tx = await txBuilder.build();
544
+ const txHex = tx.toBroadcastFormat();
545
+ await coin
546
+ .verifyTransaction({
547
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
548
+ txPrebuild: { txHex },
549
+ wallet: {},
550
+ })
551
+ .should.be.rejectedWith(/failed to decode confidential transfer calldata/);
552
+ });
553
+ it('should throw when txParams amount does not match buildParams amount (with txHex)', async function () {
554
+ const txHex = await buildConfidentialTransferTxHex({
555
+ walletContractAddress: WALLET_CONTRACT,
556
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
557
+ recipientAddress: RECIPIENT,
558
+ encryptedHandle: HANDLE,
559
+ inputProof: PROOF,
560
+ });
561
+ await coin
562
+ .verifyTransaction({
563
+ txParams: { recipients: [{ address: RECIPIENT, amount: '9999999' }] },
564
+ txPrebuild: {
565
+ txHex,
566
+ buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
567
+ },
568
+ wallet: {},
569
+ })
570
+ .should.be.rejectedWith(/amount mismatch/);
571
+ });
572
+ it('should throw when txParams amount is 0 (with txHex)', async function () {
573
+ const txHex = await buildConfidentialTransferTxHex({
574
+ walletContractAddress: WALLET_CONTRACT,
575
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
576
+ recipientAddress: RECIPIENT,
577
+ encryptedHandle: HANDLE,
578
+ inputProof: PROOF,
579
+ });
580
+ await coin
581
+ .verifyTransaction({
582
+ txParams: { recipients: [{ address: RECIPIENT, amount: '0' }] },
583
+ txPrebuild: { txHex },
584
+ wallet: {},
585
+ })
586
+ .should.be.rejectedWith(/amount must be a positive integer string/);
587
+ });
588
+ // ── First-signer (no txHex) tests ──────────────────────────────────────────
589
+ it('should verify valid first-signer params when no txHex is present', async function () {
590
+ const result = await coin.verifyTransaction({
591
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
592
+ txPrebuild: {},
593
+ wallet: {},
594
+ });
595
+ result.should.equal(true);
596
+ });
597
+ it('should verify first-signer params when txParams and buildParams amounts match', async function () {
598
+ const result = await coin.verifyTransaction({
599
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
600
+ txPrebuild: { buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] } },
601
+ wallet: {},
602
+ });
603
+ result.should.equal(true);
604
+ });
605
+ it('should throw when recipients is empty and no txHex is present', async function () {
606
+ await coin
607
+ .verifyTransaction({
608
+ txParams: { recipients: [] },
609
+ txPrebuild: {},
610
+ wallet: {},
611
+ })
612
+ .should.be.rejectedWith(/recipients must contain at least one entry/);
613
+ });
614
+ it('should throw when recipient address is invalid and no txHex is present', async function () {
615
+ await coin
616
+ .verifyTransaction({
617
+ txParams: { recipients: [{ address: 'not-an-address', amount: AMOUNT }] },
618
+ txPrebuild: {},
619
+ wallet: {},
620
+ })
621
+ .should.be.rejectedWith(/recipient address is missing or invalid/);
622
+ });
623
+ it('should throw when amount is 0 and no txHex is present', async function () {
624
+ await coin
625
+ .verifyTransaction({
626
+ txParams: { recipients: [{ address: RECIPIENT, amount: '0' }] },
627
+ txPrebuild: {},
628
+ wallet: {},
629
+ })
630
+ .should.be.rejectedWith(/amount must be a positive integer string/);
631
+ });
632
+ it('should throw when amount is empty and no txHex is present', async function () {
633
+ await coin
634
+ .verifyTransaction({
635
+ txParams: { recipients: [{ address: RECIPIENT, amount: '' }] },
636
+ txPrebuild: {},
637
+ wallet: {},
638
+ })
639
+ .should.be.rejectedWith(/amount must be a positive integer string/);
640
+ });
641
+ it('should throw when txParams and buildParams amounts mismatch and no txHex is present', async function () {
642
+ await coin
643
+ .verifyTransaction({
644
+ txParams: { recipients: [{ address: RECIPIENT, amount: '9999999' }] },
645
+ txPrebuild: { buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] } },
646
+ wallet: {},
647
+ })
648
+ .should.be.rejectedWith(/amount mismatch/);
649
+ });
650
+ it('should throw when txParams and buildParams recipient addresses mismatch and no txHex is present', async function () {
651
+ await coin
652
+ .verifyTransaction({
653
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
654
+ txPrebuild: {
655
+ buildParams: { recipients: [{ address: WRONG_RECIPIENT, amount: AMOUNT }] },
656
+ },
657
+ wallet: {},
658
+ })
659
+ .should.be.rejectedWith(/recipient address mismatch/);
660
+ });
661
+ it('should verify when txHex absent and buildParams has matching recipient address', async function () {
662
+ const result = await coin.verifyTransaction({
663
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
664
+ txPrebuild: {
665
+ buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
666
+ },
667
+ wallet: {},
668
+ });
669
+ result.should.equal(true);
670
+ });
671
+ it('should verify decoded recipient against buildParams when txParams.recipients is absent', async function () {
672
+ const txHex = await buildConfidentialTransferTxHex({
673
+ walletContractAddress: WALLET_CONTRACT,
674
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
675
+ recipientAddress: RECIPIENT,
676
+ encryptedHandle: HANDLE,
677
+ inputProof: PROOF,
678
+ });
679
+ // No recipients in txParams — falls back to buildParams for recipient verification
680
+ const result = await coin.verifyTransaction({
681
+ txParams: {},
682
+ txPrebuild: {
683
+ txHex,
684
+ buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
685
+ },
686
+ wallet: {},
687
+ });
688
+ result.should.equal(true);
689
+ });
690
+ it('should throw when decoded recipient does not match buildParams recipient (txParams absent)', async function () {
691
+ const txHex = await buildConfidentialTransferTxHex({
692
+ walletContractAddress: WALLET_CONTRACT,
693
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
694
+ recipientAddress: RECIPIENT,
695
+ encryptedHandle: HANDLE,
696
+ inputProof: PROOF,
697
+ });
698
+ await coin
699
+ .verifyTransaction({
700
+ txParams: {},
701
+ txPrebuild: {
702
+ txHex,
703
+ buildParams: { recipients: [{ address: WRONG_RECIPIENT, amount: AMOUNT }] },
704
+ },
705
+ wallet: {},
706
+ })
707
+ .should.be.rejectedWith(/recipient address mismatch/);
708
+ });
709
+ });
710
+ // ---------------------------------------------------------------------------
711
+ // verifyTransaction – direct confidentialTransfer (hot/TSS EOA wallet) tests
712
+ // ---------------------------------------------------------------------------
713
+ /**
714
+ * Builds a raw tx hex where the EOA calls confidentialTransfer directly on the token
715
+ * contract (no sendMultiSig wrapper). This is the hot/TSS wallet path.
716
+ */
717
+ async function buildDirectConfidentialTransferTxHex(opts) {
718
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
719
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
720
+ txBuilder.counter(1);
721
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
722
+ // tx.to = token contract (EOA calls it directly)
723
+ txBuilder.contract(opts.tokenContractAddress);
724
+ // Inner calldata: confidentialTransfer(address, bytes32, bytes) — no sendMultiSig wrapper
725
+ const calldata = new abstract_eth_1.TransferBuilderERC7984()
726
+ .to(opts.recipientAddress)
727
+ .tokenContractAddress(opts.tokenContractAddress)
728
+ .encryptedHandle(opts.encryptedHandle)
729
+ .inputProof(opts.inputProof)
730
+ .build();
731
+ txBuilder.data(calldata);
732
+ const tx = await txBuilder.build();
733
+ return tx.toBroadcastFormat();
734
+ }
735
+ describe('verifyTransaction – direct confidentialTransfer (hot/TSS EOA wallet)', function () {
736
+ const RECIPIENT = '0x19645032c7f1533395d44a629462e751084d3e4c';
737
+ const HANDLE = '0x' + 'ab'.repeat(32);
738
+ const PROOF = '0x' + 'cd'.repeat(50);
739
+ const WRONG_RECIPIENT = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
740
+ const WRONG_TOKEN = '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
741
+ const AMOUNT = '1000000';
742
+ let bitgo;
743
+ let coin;
744
+ before(function () {
745
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
746
+ bitgo.initializeTestVars();
747
+ (0, register_1.register)(bitgo);
748
+ coin = bitgo.coin('hteth:ctest1');
749
+ });
750
+ it('should verify a valid direct confidentialTransfer tx', async function () {
751
+ const txHex = await buildDirectConfidentialTransferTxHex({
752
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
753
+ recipientAddress: RECIPIENT,
754
+ encryptedHandle: HANDLE,
755
+ inputProof: PROOF,
756
+ });
757
+ const result = await coin.verifyTransaction({
758
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
759
+ txPrebuild: { txHex, buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] } },
760
+ wallet: {},
761
+ });
762
+ result.should.equal(true);
763
+ });
764
+ it('should verify using buildParams.recipients when txParams has no recipients', async function () {
765
+ const txHex = await buildDirectConfidentialTransferTxHex({
766
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
767
+ recipientAddress: RECIPIENT,
768
+ encryptedHandle: HANDLE,
769
+ inputProof: PROOF,
770
+ });
771
+ const result = await coin.verifyTransaction({
772
+ txParams: {},
773
+ txPrebuild: {
774
+ txHex,
775
+ buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
776
+ },
777
+ wallet: {},
778
+ });
779
+ result.should.equal(true);
780
+ });
781
+ it('should throw when token contract address (tx.to) does not match this coin', async function () {
782
+ const txHex = await buildDirectConfidentialTransferTxHex({
783
+ tokenContractAddress: WRONG_TOKEN,
784
+ recipientAddress: RECIPIENT,
785
+ encryptedHandle: HANDLE,
786
+ inputProof: PROOF,
787
+ });
788
+ await coin
789
+ .verifyTransaction({
790
+ txParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
791
+ txPrebuild: { txHex },
792
+ wallet: {},
793
+ })
794
+ .should.be.rejectedWith(/token contract address mismatch/);
795
+ });
796
+ it('should throw when recipient address does not match txParams', async function () {
797
+ const txHex = await buildDirectConfidentialTransferTxHex({
798
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
799
+ recipientAddress: RECIPIENT,
800
+ encryptedHandle: HANDLE,
801
+ inputProof: PROOF,
802
+ });
803
+ await coin
804
+ .verifyTransaction({
805
+ txParams: { recipients: [{ address: WRONG_RECIPIENT, amount: AMOUNT }] },
806
+ txPrebuild: { txHex },
807
+ wallet: {},
808
+ })
809
+ .should.be.rejectedWith(/recipient address mismatch/);
810
+ });
811
+ it('should throw when no recipient info is provided in either txParams or buildParams', async function () {
812
+ const txHex = await buildDirectConfidentialTransferTxHex({
813
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
814
+ recipientAddress: RECIPIENT,
815
+ encryptedHandle: HANDLE,
816
+ inputProof: PROOF,
817
+ });
818
+ await coin
819
+ .verifyTransaction({
820
+ txParams: {},
821
+ txPrebuild: { txHex },
822
+ wallet: {},
823
+ })
824
+ .should.be.rejectedWith(/missing expected recipient/);
825
+ });
826
+ it('should throw when txParams amount does not match buildParams amount', async function () {
827
+ const txHex = await buildDirectConfidentialTransferTxHex({
828
+ tokenContractAddress: CTEST1_TOKEN_ADDRESS,
829
+ recipientAddress: RECIPIENT,
830
+ encryptedHandle: HANDLE,
831
+ inputProof: PROOF,
832
+ });
833
+ await coin
834
+ .verifyTransaction({
835
+ txParams: { recipients: [{ address: RECIPIENT, amount: '9999999' }] },
836
+ txPrebuild: {
837
+ txHex,
838
+ buildParams: { recipients: [{ address: RECIPIENT, amount: AMOUNT }] },
839
+ },
840
+ wallet: {},
841
+ })
842
+ .should.be.rejectedWith(/amount mismatch/);
843
+ });
844
+ });
845
+ // ---------------------------------------------------------------------------
846
+ // decodeTokenAddressesFromDelegationCalldata tests
847
+ // ---------------------------------------------------------------------------
848
+ describe('decodeTokenAddressesFromDelegationCalldata', function () {
849
+ it('should decode a single-token multicall calldata', function () {
850
+ const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS], EXPIRY);
851
+ const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(calldata);
852
+ addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase()]);
853
+ });
854
+ it('should decode a multi-token multicall calldata', function () {
855
+ const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS, CUSDT_TOKEN_ADDRESS], EXPIRY);
856
+ const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(calldata);
857
+ addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase(), CUSDT_TOKEN_ADDRESS.toLowerCase()]);
858
+ });
859
+ it('should return addresses in lowercase', function () {
860
+ const mixedCase = '0x7B1D59bbCD291daA59cB6C8C5bc04De1AFC4aBA1';
861
+ const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [mixedCase], EXPIRY);
862
+ const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(calldata);
863
+ addresses[0].should.equal(mixedCase.toLowerCase());
864
+ });
865
+ it('should handle callFromParent-wrapped multicall calldata', function () {
866
+ const inner = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS, CUSDT_TOKEN_ADDRESS], EXPIRY);
867
+ const wrapped = (0, abstract_eth_1.wrapInCallFromParent)(ZAMA_ACL_ADDRESS, inner);
868
+ const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(wrapped);
869
+ addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase(), CUSDT_TOKEN_ADDRESS.toLowerCase()]);
870
+ });
871
+ it('should work with calldata missing 0x prefix', function () {
872
+ const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS], EXPIRY);
873
+ const noPrefix = calldata.slice(2); // strip 0x
874
+ const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(noPrefix);
875
+ addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase()]);
876
+ });
877
+ it('should throw for unrecognised calldata', function () {
878
+ should_1.default.throws(() => (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)('0xdeadbeef00000000'), /Not a valid delegation calldata/);
879
+ });
880
+ });
881
+ // ---------------------------------------------------------------------------
882
+ // verifyTransaction – confidential consolidation (FlushERC7984ForwarderToken)
883
+ // ---------------------------------------------------------------------------
884
+ const MULTISIG_WALLET_CONTRACT = '0x3b58684525564b38a381e46a731703ed03f32122';
885
+ const CONSOLIDATION_FORWARDER = '0xf4bcb366bb5e34ebbee51fae5de98cc876c0146f';
886
+ const CONSOLIDATION_BASE_ADDRESS = '0x3b58684525564b38a381e46a731703ed03f32122';
887
+ const CONSOLIDATION_HANDLE = '0x65df136b609ab395c1a99ae46f7939c7f8b20dff4bff0000000088bb0050';
888
+ const DUMMY_MULTISIG_SIGNATURE = '0x' + '00'.repeat(65);
889
+ async function buildMultisigConsolidationTxHex() {
890
+ const flushCalldata = (0, abstract_eth_1.buildFlushERC7984ForwarderTokenCalldata)(CTEST1_TOKEN_ADDRESS, CONSOLIDATION_BASE_ADDRESS, CONSOLIDATION_HANDLE);
891
+ const sendData = (0, abstract_eth_1.sendMultiSigData)(CONSOLIDATION_FORWARDER, '0', flushCalldata, Math.floor(Date.now() / 1000) + 3600, 14, DUMMY_MULTISIG_SIGNATURE);
892
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
893
+ txBuilder.fee({ fee: '1000000000', gasLimit: '12100000' });
894
+ txBuilder.counter(1);
895
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
896
+ txBuilder.contract(MULTISIG_WALLET_CONTRACT);
897
+ txBuilder.data(sendData);
898
+ const tx = await txBuilder.build();
899
+ return tx.toBroadcastFormat();
900
+ }
901
+ async function buildDirectConsolidationTxHex() {
902
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
903
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
904
+ txBuilder.counter(1);
905
+ txBuilder.type(sdk_core_1.TransactionType.FlushERC7984ForwarderToken);
906
+ txBuilder.contract(CONSOLIDATION_FORWARDER);
907
+ txBuilder.forwarderAddress(CONSOLIDATION_FORWARDER);
908
+ txBuilder.tokenContractAddress(CTEST1_TOKEN_ADDRESS);
909
+ txBuilder.parentAddress(CONSOLIDATION_BASE_ADDRESS);
910
+ txBuilder.encryptedHandle(CONSOLIDATION_HANDLE);
911
+ const tx = await txBuilder.build();
912
+ return tx.toBroadcastFormat();
913
+ }
914
+ describe('verifyTransaction – confidential consolidation (FlushERC7984ForwarderToken)', function () {
915
+ let bitgo;
916
+ let coin;
917
+ before(function () {
918
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
919
+ bitgo.initializeTestVars();
920
+ (0, register_1.register)(bitgo);
921
+ coin = bitgo.coin('hteth:ctest1');
922
+ });
923
+ it('should verify a valid multisig consolidation tx (sendMultiSig → callFromParent → confidentialTransferNoProof)', async function () {
924
+ const txHex = await buildMultisigConsolidationTxHex();
925
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
926
+ coinSpecific: { baseAddress: CONSOLIDATION_BASE_ADDRESS },
927
+ });
928
+ const result = await coin.verifyTransaction({
929
+ txParams: { type: 'consolidate' },
930
+ txPrebuild: {
931
+ consolidateId: '6a44ebc0326e1be45c1d797542c8c634',
932
+ txHex,
933
+ recipients: [{ address: CONSOLIDATION_FORWARDER, amount: '0' }],
934
+ },
935
+ wallet,
936
+ });
937
+ result.should.equal(true);
938
+ });
939
+ it('should verify a valid direct callFromParent consolidation tx (TSS shape)', async function () {
940
+ const txHex = await buildDirectConsolidationTxHex();
941
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
942
+ coinSpecific: { baseAddress: CONSOLIDATION_BASE_ADDRESS },
943
+ });
944
+ const result = await coin.verifyTransaction({
945
+ txParams: { type: 'consolidate' },
946
+ txPrebuild: {
947
+ consolidateId: '6a44ebc0326e1be45c1d797542c8c634',
948
+ txHex,
949
+ },
950
+ wallet,
951
+ verification: { consolidationToBaseAddress: true },
952
+ });
953
+ result.should.equal(true);
954
+ });
955
+ it('should reject multisig consolidation when parent address does not match wallet base address', async function () {
956
+ const txHex = await buildMultisigConsolidationTxHex();
957
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
958
+ coinSpecific: { baseAddress: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' },
959
+ });
960
+ await coin
961
+ .verifyTransaction({
962
+ txParams: { type: 'consolidate' },
963
+ txPrebuild: { consolidateId: 'abc123', txHex },
964
+ wallet,
965
+ })
966
+ .should.be.rejectedWith(/parent address mismatch/);
967
+ });
968
+ it('should verify multisig consolidation using forwarder address from txPrebuild.txInfo.recipients', async function () {
969
+ const txHex = await buildMultisigConsolidationTxHex();
970
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
971
+ coinSpecific: { baseAddress: CONSOLIDATION_BASE_ADDRESS },
972
+ });
973
+ // No top-level recipients; forwarder comes from txInfo.recipients
974
+ const result = await coin.verifyTransaction({
975
+ txParams: { type: 'consolidate' },
976
+ txPrebuild: {
977
+ consolidateId: '6a44ebc0326e1be45c1d797542c8c634',
978
+ txHex,
979
+ txInfo: { recipients: [{ address: CONSOLIDATION_FORWARDER, amount: '0' }] },
980
+ },
981
+ wallet,
982
+ });
983
+ result.should.equal(true);
984
+ });
985
+ it('should reject multisig consolidation when txInfo.recipients forwarder address does not match tx forwarder', async function () {
986
+ const txHex = await buildMultisigConsolidationTxHex();
987
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
988
+ coinSpecific: { baseAddress: CONSOLIDATION_BASE_ADDRESS },
989
+ });
990
+ await coin
991
+ .verifyTransaction({
992
+ txParams: { type: 'consolidate' },
993
+ txPrebuild: {
994
+ consolidateId: 'abc123',
995
+ txHex,
996
+ txInfo: { recipients: [{ address: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', amount: '0' }] },
997
+ },
998
+ wallet,
999
+ })
1000
+ .should.be.rejectedWith(/forwarder address mismatch/);
1001
+ });
1002
+ // TSS MPCv2 signing path — resolveEffectiveTxParams sets type from intent.intentType ('consolidateToken'),
1003
+ // and txPrebuild has only txHex (no consolidateId, no recipients). This was the broken path before
1004
+ // isConsolidationTransaction was updated to recognise 'consolidateToken'.
1005
+ it('should verify a valid direct callFromParent consolidation tx when type is consolidateToken (TSS MPCv2 signing path)', async function () {
1006
+ const txHex = await buildDirectConsolidationTxHex();
1007
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1008
+ coinSpecific: { baseAddress: CONSOLIDATION_BASE_ADDRESS },
1009
+ });
1010
+ const result = await coin.verifyTransaction({
1011
+ txParams: {
1012
+ type: 'consolidateToken',
1013
+ recipients: [{ address: CONSOLIDATION_FORWARDER, amount: '0' }],
1014
+ },
1015
+ txPrebuild: { txHex },
1016
+ wallet,
1017
+ });
1018
+ result.should.equal(true);
1019
+ });
1020
+ it('should reject callFromParent consolidation with type consolidateToken when parent address does not match wallet base address', async function () {
1021
+ const txHex = await buildDirectConsolidationTxHex();
1022
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1023
+ coinSpecific: { baseAddress: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' },
1024
+ });
1025
+ await coin
1026
+ .verifyTransaction({
1027
+ txParams: {
1028
+ type: 'consolidateToken',
1029
+ recipients: [{ address: CONSOLIDATION_FORWARDER, amount: '0' }],
1030
+ },
1031
+ txPrebuild: { txHex },
1032
+ wallet,
1033
+ })
1034
+ .should.be.rejectedWith(/parent address mismatch/);
1035
+ });
1036
+ });
1037
+ // ---------------------------------------------------------------------------
1038
+ // recover() – ERC-7984 confidential token recovery
1039
+ // ---------------------------------------------------------------------------
1040
+ describe('Erc7984Token – recover()', function () {
1041
+ let bitgo;
1042
+ let coin;
1043
+ let explorerStub;
1044
+ const WALLET_CONTRACT = '0x8f977e912ef500548a0c3be6ddde9899f1199b81';
1045
+ const RECOVERY_DEST = '0x19645032c7f1533395d44a629462e751084d3e4c';
1046
+ const HANDLE = '0x' + 'ab'.repeat(32);
1047
+ const ZERO_HANDLE = '0x' + '00'.repeat(32);
1048
+ const USER_KEY = testData.PRIVATE_KEY;
1049
+ const BACKUP_KEY = testData.PRIVATE_KEY;
1050
+ const WALLET_PASSPHRASE = 'test wallet passphrase';
1051
+ // Encrypted keys for test (encrypt with the test passphrase)
1052
+ let encryptedUserKey;
1053
+ let encryptedBackupKey;
1054
+ before(async function () {
1055
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1056
+ bitgo.initializeTestVars();
1057
+ (0, register_1.register)(bitgo);
1058
+ coin = bitgo.coin('hteth:ctest1');
1059
+ encryptedUserKey = await bitgo.encrypt({ input: USER_KEY, password: WALLET_PASSPHRASE });
1060
+ encryptedBackupKey = await bitgo.encrypt({ input: BACKUP_KEY, password: WALLET_PASSPHRASE });
1061
+ });
1062
+ beforeEach(function () {
1063
+ explorerStub = sinon_1.default.stub(coin, 'recoveryBlockchainExplorerQuery');
1064
+ });
1065
+ afterEach(function () {
1066
+ sinon_1.default.restore();
1067
+ });
1068
+ function mockExplorerForRecovery(handle = HANDLE) {
1069
+ explorerStub.callsFake(async (query) => {
1070
+ if (query.action === 'txlist') {
1071
+ // getAddressNonce: return empty tx list (nonce = 0)
1072
+ return { result: [] };
1073
+ }
1074
+ if (query.action === 'balance') {
1075
+ // queryAddressBalance: return enough ETH for gas
1076
+ return { result: '100000000000000000' }; // 0.1 ETH
1077
+ }
1078
+ if (query.action === 'eth_call' && query.data?.startsWith('a0b7967b')) {
1079
+ // querySequenceId: getNextSequenceId
1080
+ return { result: '0x0000000000000000000000000000000000000000000000000000000000000005' };
1081
+ }
1082
+ if (query.action === 'eth_call' && query.to === CTEST1_TOKEN_ADDRESS) {
1083
+ // queryConfidentialBalance
1084
+ return { result: handle };
1085
+ }
1086
+ throw new Error(`Unexpected explorer query: ${JSON.stringify(query)}`);
1087
+ });
1088
+ }
1089
+ it('should build a full balance sweep recovery transaction', async function () {
1090
+ mockExplorerForRecovery();
1091
+ const result = await coin.recover({
1092
+ userKey: encryptedUserKey,
1093
+ backupKey: encryptedBackupKey,
1094
+ walletPassphrase: WALLET_PASSPHRASE,
1095
+ walletContractAddress: WALLET_CONTRACT,
1096
+ recoveryDestination: RECOVERY_DEST,
1097
+ });
1098
+ should_1.default.exist(result);
1099
+ result.should.have.property('id');
1100
+ result.should.have.property('tx');
1101
+ result.tx.should.be.a.String();
1102
+ result.tx.length.should.be.greaterThan(0);
1103
+ });
1104
+ it('should use user-provided encryptedHandle and skip auto-query', async function () {
1105
+ const userHandle = '0x' + 'ff'.repeat(32);
1106
+ explorerStub.callsFake(async (query) => {
1107
+ if (query.action === 'txlist') {
1108
+ return { result: [] };
1109
+ }
1110
+ if (query.action === 'balance') {
1111
+ return { result: '100000000000000000' };
1112
+ }
1113
+ if (query.action === 'eth_call' && query.data?.startsWith('a0b7967b')) {
1114
+ return { result: '0x0000000000000000000000000000000000000000000000000000000000000005' };
1115
+ }
1116
+ if (query.action === 'eth_call' && query.to === CTEST1_TOKEN_ADDRESS) {
1117
+ throw new Error('Should not query confidentialBalanceOf when handle is provided');
1118
+ }
1119
+ throw new Error(`Unexpected explorer query: ${JSON.stringify(query)}`);
1120
+ });
1121
+ const result = await coin.recover({
1122
+ userKey: encryptedUserKey,
1123
+ backupKey: encryptedBackupKey,
1124
+ walletPassphrase: WALLET_PASSPHRASE,
1125
+ walletContractAddress: WALLET_CONTRACT,
1126
+ recoveryDestination: RECOVERY_DEST,
1127
+ encryptedHandle: userHandle,
1128
+ });
1129
+ should_1.default.exist(result);
1130
+ result.should.have.property('tx');
1131
+ });
1132
+ it('should still build a recovery tx even with a zero-value handle (encrypted handles are always non-zero)', async function () {
1133
+ mockExplorerForRecovery(ZERO_HANDLE);
1134
+ const result = await coin.recover({
1135
+ userKey: encryptedUserKey,
1136
+ backupKey: encryptedBackupKey,
1137
+ walletPassphrase: WALLET_PASSPHRASE,
1138
+ walletContractAddress: WALLET_CONTRACT,
1139
+ recoveryDestination: RECOVERY_DEST,
1140
+ });
1141
+ should_1.default.exist(result);
1142
+ result.should.have.property('tx');
1143
+ });
1144
+ it('should return unsigned sweep format when isUnsignedSweep is true', async function () {
1145
+ mockExplorerForRecovery();
1146
+ const result = await coin.recover({
1147
+ userKey: testData.PUBLIC_KEY,
1148
+ backupKey: testData.PUBLIC_KEY,
1149
+ walletContractAddress: WALLET_CONTRACT,
1150
+ recoveryDestination: RECOVERY_DEST,
1151
+ isUnsignedSweep: true,
1152
+ });
1153
+ should_1.default.exist(result);
1154
+ result.should.have.property('tx');
1155
+ result.should.have.property('userKey');
1156
+ result.should.have.property('backupKey');
1157
+ });
1158
+ it('should return KRS recovery format with backupKey and coin', async function () {
1159
+ explorerStub.callsFake(async (query) => {
1160
+ if (query.action === 'txlist') {
1161
+ return { result: [] };
1162
+ }
1163
+ if (query.action === 'balance') {
1164
+ return { result: '100000000000000000' };
1165
+ }
1166
+ if (query.action === 'eth_call' && query.data?.startsWith('a0b7967b')) {
1167
+ return { result: '0x0000000000000000000000000000000000000000000000000000000000000005' };
1168
+ }
1169
+ if (query.action === 'eth_call' && query.to === CTEST1_TOKEN_ADDRESS) {
1170
+ return { result: HANDLE };
1171
+ }
1172
+ throw new Error(`Unexpected explorer query: ${JSON.stringify(query)}`);
1173
+ });
1174
+ const result = (await coin.recover({
1175
+ userKey: encryptedUserKey,
1176
+ backupKey: testData.PUBLIC_KEY,
1177
+ walletPassphrase: WALLET_PASSPHRASE,
1178
+ walletContractAddress: WALLET_CONTRACT,
1179
+ recoveryDestination: RECOVERY_DEST,
1180
+ krsProvider: 'keyternal',
1181
+ }));
1182
+ should_1.default.exist(result);
1183
+ result.should.have.property('tx');
1184
+ result.should.have.property('backupKey', testData.PUBLIC_KEY);
1185
+ result.should.have.property('coin', 'hteth:ctest1');
1186
+ });
1187
+ it('should throw when backup key has insufficient gas', async function () {
1188
+ explorerStub.callsFake(async (query) => {
1189
+ if (query.action === 'txlist') {
1190
+ return { result: [] };
1191
+ }
1192
+ if (query.action === 'balance') {
1193
+ // Very low balance, not enough for 12M gas
1194
+ return { result: '100' };
1195
+ }
1196
+ throw new Error(`Unexpected explorer query: ${JSON.stringify(query)}`);
1197
+ });
1198
+ await coin
1199
+ .recover({
1200
+ userKey: encryptedUserKey,
1201
+ backupKey: encryptedBackupKey,
1202
+ walletPassphrase: WALLET_PASSPHRASE,
1203
+ walletContractAddress: WALLET_CONTRACT,
1204
+ recoveryDestination: RECOVERY_DEST,
1205
+ })
1206
+ .should.be.rejectedWith(/has balance.*Gwei/);
1207
+ });
1208
+ it('should throw when userKey is missing', async function () {
1209
+ await coin
1210
+ .recover({
1211
+ userKey: undefined,
1212
+ backupKey: encryptedBackupKey,
1213
+ walletPassphrase: WALLET_PASSPHRASE,
1214
+ walletContractAddress: WALLET_CONTRACT,
1215
+ recoveryDestination: RECOVERY_DEST,
1216
+ })
1217
+ .should.be.rejectedWith(/missing userKey/);
1218
+ });
1219
+ it('should throw when walletContractAddress is invalid', async function () {
1220
+ await coin
1221
+ .recover({
1222
+ userKey: encryptedUserKey,
1223
+ backupKey: encryptedBackupKey,
1224
+ walletPassphrase: WALLET_PASSPHRASE,
1225
+ walletContractAddress: 'not-an-address',
1226
+ recoveryDestination: RECOVERY_DEST,
1227
+ })
1228
+ .should.be.rejectedWith(/invalid walletContractAddress/);
1229
+ });
1230
+ it('should produce tx with inner calldata matching confidentialTransfer selector 0x5bebed7e', async function () {
1231
+ mockExplorerForRecovery();
1232
+ const result = (await coin.recover({
1233
+ userKey: encryptedUserKey,
1234
+ backupKey: encryptedBackupKey,
1235
+ walletPassphrase: WALLET_PASSPHRASE,
1236
+ walletContractAddress: WALLET_CONTRACT,
1237
+ recoveryDestination: RECOVERY_DEST,
1238
+ }));
1239
+ should_1.default.exist(result.tx);
1240
+ // The serialized tx contains the sendMultiSig calldata which wraps confidentialTransfer.
1241
+ // The confidentialTransfer selector (5bebed7e) must appear somewhere in the serialized tx.
1242
+ const selectorNoPrefix = abstract_eth_1.confidentialTransferNoProofMethodId.slice(2);
1243
+ result.tx.should.containEql(selectorNoPrefix);
1244
+ });
1245
+ });
1246
+ // ---------------------------------------------------------------------------
1247
+ // queryConfidentialBalance() tests
1248
+ // ---------------------------------------------------------------------------
1249
+ describe('Erc7984Token – queryConfidentialBalance()', function () {
1250
+ let bitgo;
1251
+ let coin;
1252
+ let explorerStub;
1253
+ const WALLET_ADDRESS = '0x8f977e912ef500548a0c3be6ddde9899f1199b81';
1254
+ const HANDLE = '0x' + 'ab'.repeat(32);
1255
+ before(function () {
1256
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1257
+ bitgo.initializeTestVars();
1258
+ (0, register_1.register)(bitgo);
1259
+ coin = bitgo.coin('hteth:ctest1');
1260
+ });
1261
+ beforeEach(function () {
1262
+ explorerStub = sinon_1.default.stub(coin, 'recoveryBlockchainExplorerQuery');
1263
+ });
1264
+ afterEach(function () {
1265
+ sinon_1.default.restore();
1266
+ });
1267
+ it('should return a valid bytes32 handle from eth_call', async function () {
1268
+ explorerStub.resolves({ result: HANDLE });
1269
+ const result = await coin.queryConfidentialBalance(WALLET_ADDRESS);
1270
+ result.should.equal(HANDLE);
1271
+ });
1272
+ it('should verify the eth_call is made to the correct token contract', async function () {
1273
+ explorerStub.resolves({ result: HANDLE });
1274
+ await coin.queryConfidentialBalance(WALLET_ADDRESS);
1275
+ explorerStub.calledOnce.should.be.true();
1276
+ const callArgs = explorerStub.firstCall.args[0];
1277
+ callArgs.should.have.property('action', 'eth_call');
1278
+ callArgs.should.have.property('to', CTEST1_TOKEN_ADDRESS);
1279
+ callArgs.should.have.property('module', 'proxy');
1280
+ });
1281
+ it('should throw when explorer returns no result', async function () {
1282
+ explorerStub.resolves({ result: null });
1283
+ await coin.queryConfidentialBalance(WALLET_ADDRESS).should.be.rejectedWith(/Could not obtain confidential balance/);
1284
+ });
1285
+ it('should throw when response format is unexpected (not 66 chars)', async function () {
1286
+ explorerStub.resolves({ result: '0xabcd' });
1287
+ await coin
1288
+ .queryConfidentialBalance(WALLET_ADDRESS)
1289
+ .should.be.rejectedWith(/Unexpected confidentialBalanceOf response format/);
1290
+ });
1291
+ });
1292
+ // ---------------------------------------------------------------------------
1293
+ // verifyTransaction – WrapERC7984 (shield)
1294
+ // ---------------------------------------------------------------------------
1295
+ const WRAP_BASE_ADDRESS = '0x1111111111111111111111111111111111111111';
1296
+ const WRAP_AMOUNT = '1000000';
1297
+ const WRAP_RATE = '1';
1298
+ async function buildDirectWrapTxHex(tokenAddress, recipient, amount) {
1299
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
1300
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
1301
+ txBuilder.counter(1);
1302
+ txBuilder.type(sdk_core_1.TransactionType.WrapERC7984);
1303
+ txBuilder.contract(tokenAddress);
1304
+ txBuilder.wrapRecipient(recipient);
1305
+ txBuilder.wrapAmount(amount);
1306
+ txBuilder.wrapRate(WRAP_RATE);
1307
+ const tx = await txBuilder.build();
1308
+ return tx.toBroadcastFormat();
1309
+ }
1310
+ async function buildMultisigWrapTxHex(tokenAddress, recipient, amount) {
1311
+ const wrapCalldata = (0, abstract_eth_1.buildWrapCalldata)(recipient, amount, WRAP_RATE);
1312
+ const sendData = (0, abstract_eth_1.sendMultiSigData)(tokenAddress, '0', wrapCalldata, Math.floor(Date.now() / 1000) + 3600, 14, DUMMY_MULTISIG_SIGNATURE);
1313
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
1314
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
1315
+ txBuilder.counter(1);
1316
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
1317
+ txBuilder.contract(MULTISIG_WALLET_CONTRACT);
1318
+ txBuilder.data(sendData);
1319
+ const tx = await txBuilder.build();
1320
+ return tx.toBroadcastFormat();
1321
+ }
1322
+ describe('verifyTransaction – WrapERC7984', function () {
1323
+ let bitgo;
1324
+ let coin;
1325
+ before(function () {
1326
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1327
+ bitgo.initializeTestVars();
1328
+ (0, register_1.register)(bitgo);
1329
+ coin = bitgo.coin('hteth:ctest1');
1330
+ });
1331
+ it('should verify a valid direct wrap tx (TSS shape)', async function () {
1332
+ const txHex = await buildDirectWrapTxHex(CTEST1_TOKEN_ADDRESS, WRAP_BASE_ADDRESS, WRAP_AMOUNT);
1333
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1334
+ coinSpecific: { baseAddress: WRAP_BASE_ADDRESS },
1335
+ });
1336
+ const result = await coin.verifyTransaction({
1337
+ txParams: {
1338
+ type: 'wrap',
1339
+ recipients: [{ address: WRAP_BASE_ADDRESS, amount: WRAP_AMOUNT }],
1340
+ },
1341
+ txPrebuild: { txHex },
1342
+ wallet,
1343
+ });
1344
+ result.should.equal(true);
1345
+ });
1346
+ it('should verify a valid multisig wrap tx (sendMultiSig → wrap)', async function () {
1347
+ const txHex = await buildMultisigWrapTxHex(CTEST1_TOKEN_ADDRESS, WRAP_BASE_ADDRESS, WRAP_AMOUNT);
1348
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1349
+ coinSpecific: { baseAddress: WRAP_BASE_ADDRESS },
1350
+ });
1351
+ const result = await coin.verifyTransaction({
1352
+ txParams: {
1353
+ type: 'wrap',
1354
+ recipients: [{ address: WRAP_BASE_ADDRESS, amount: WRAP_AMOUNT }],
1355
+ },
1356
+ txPrebuild: { txHex },
1357
+ wallet,
1358
+ });
1359
+ result.should.equal(true);
1360
+ });
1361
+ it('should reject wrap when recipient does not match wallet base address', async function () {
1362
+ const txHex = await buildDirectWrapTxHex(CTEST1_TOKEN_ADDRESS, WRAP_BASE_ADDRESS, WRAP_AMOUNT);
1363
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1364
+ coinSpecific: { baseAddress: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' },
1365
+ });
1366
+ await coin
1367
+ .verifyTransaction({
1368
+ txParams: { type: 'wrap', recipients: [{ address: WRAP_BASE_ADDRESS, amount: WRAP_AMOUNT }] },
1369
+ txPrebuild: { txHex },
1370
+ wallet,
1371
+ })
1372
+ .should.be.rejectedWith(/wrap recipient must equal wallet base address/);
1373
+ });
1374
+ it('should reject wrap when amount mismatches recipients', async function () {
1375
+ const txHex = await buildDirectWrapTxHex(CTEST1_TOKEN_ADDRESS, WRAP_BASE_ADDRESS, WRAP_AMOUNT);
1376
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1377
+ coinSpecific: { baseAddress: WRAP_BASE_ADDRESS },
1378
+ });
1379
+ await coin
1380
+ .verifyTransaction({
1381
+ txParams: { type: 'wrap', recipients: [{ address: WRAP_BASE_ADDRESS, amount: '999' }] },
1382
+ txPrebuild: { txHex },
1383
+ wallet,
1384
+ })
1385
+ .should.be.rejectedWith(/amount mismatch/);
1386
+ });
1387
+ });
1388
+ // ---------------------------------------------------------------------------
1389
+ // verifyTransaction – UnwrapERC7984 (unshield phase-1)
1390
+ // ---------------------------------------------------------------------------
1391
+ const UNWRAP_BASE_ADDRESS = '0x1111111111111111111111111111111111111111';
1392
+ const UNWRAP_ENCRYPTED_AMOUNT = '0x' + 'ab'.repeat(32);
1393
+ const UNWRAP_INPUT_PROOF = '0x' + 'cd'.repeat(64);
1394
+ async function buildDirectUnwrapTxHex(tokenAddress, from, to, encryptedAmount, inputProof) {
1395
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
1396
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
1397
+ txBuilder.counter(1);
1398
+ txBuilder.type(sdk_core_1.TransactionType.UnwrapERC7984);
1399
+ txBuilder.contract(tokenAddress);
1400
+ txBuilder.unwrapFrom(from);
1401
+ txBuilder.unwrapTo(to);
1402
+ txBuilder.unwrapEncryptedAmount(encryptedAmount);
1403
+ txBuilder.unwrapInputProof(inputProof);
1404
+ const tx = await txBuilder.build();
1405
+ return tx.toBroadcastFormat();
1406
+ }
1407
+ async function buildMultisigUnwrapTxHex(tokenAddress, from, to, encryptedAmount, inputProof) {
1408
+ const unwrapCalldata = (0, abstract_eth_1.buildUnwrapCalldata)(from, to, encryptedAmount, inputProof);
1409
+ const sendData = (0, abstract_eth_1.sendMultiSigData)(tokenAddress, '0', unwrapCalldata, Math.floor(Date.now() / 1000) + 3600, 14, DUMMY_MULTISIG_SIGNATURE);
1410
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
1411
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
1412
+ txBuilder.counter(1);
1413
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
1414
+ txBuilder.contract(MULTISIG_WALLET_CONTRACT);
1415
+ txBuilder.data(sendData);
1416
+ const tx = await txBuilder.build();
1417
+ return tx.toBroadcastFormat();
1418
+ }
1419
+ describe('verifyTransaction – UnwrapERC7984', function () {
1420
+ let bitgo;
1421
+ let coin;
1422
+ before(function () {
1423
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1424
+ bitgo.initializeTestVars();
1425
+ (0, register_1.register)(bitgo);
1426
+ coin = bitgo.coin('hteth:ctest1');
1427
+ });
1428
+ it('should verify a valid direct unwrap tx (TSS shape)', async function () {
1429
+ const txHex = await buildDirectUnwrapTxHex(CTEST1_TOKEN_ADDRESS, UNWRAP_BASE_ADDRESS, UNWRAP_BASE_ADDRESS, UNWRAP_ENCRYPTED_AMOUNT, UNWRAP_INPUT_PROOF);
1430
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1431
+ coinSpecific: { baseAddress: UNWRAP_BASE_ADDRESS },
1432
+ });
1433
+ const result = await coin.verifyTransaction({
1434
+ txParams: { type: 'unwrap' },
1435
+ txPrebuild: { txHex },
1436
+ wallet,
1437
+ });
1438
+ result.should.equal(true);
1439
+ });
1440
+ it('should verify a valid multisig unwrap tx (sendMultiSig → unwrap)', async function () {
1441
+ const txHex = await buildMultisigUnwrapTxHex(CTEST1_TOKEN_ADDRESS, UNWRAP_BASE_ADDRESS, UNWRAP_BASE_ADDRESS, UNWRAP_ENCRYPTED_AMOUNT, UNWRAP_INPUT_PROOF);
1442
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1443
+ coinSpecific: { baseAddress: UNWRAP_BASE_ADDRESS },
1444
+ });
1445
+ const result = await coin.verifyTransaction({
1446
+ txParams: { type: 'unwrap' },
1447
+ txPrebuild: { txHex },
1448
+ wallet,
1449
+ });
1450
+ result.should.equal(true);
1451
+ });
1452
+ it('should reject unwrap when from does not match wallet base address', async function () {
1453
+ const txHex = await buildDirectUnwrapTxHex(CTEST1_TOKEN_ADDRESS, UNWRAP_BASE_ADDRESS, UNWRAP_BASE_ADDRESS, UNWRAP_ENCRYPTED_AMOUNT, UNWRAP_INPUT_PROOF);
1454
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1455
+ coinSpecific: { baseAddress: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' },
1456
+ });
1457
+ await coin
1458
+ .verifyTransaction({
1459
+ txParams: { type: 'unwrap' },
1460
+ txPrebuild: { txHex },
1461
+ wallet,
1462
+ })
1463
+ .should.be.rejectedWith(/unwrap from must equal wallet base address/);
1464
+ });
1465
+ it('should reject unwrap when to differs from from (non-self-directed)', async function () {
1466
+ const other = '0x2222222222222222222222222222222222222222';
1467
+ const txHex = await buildDirectUnwrapTxHex(CTEST1_TOKEN_ADDRESS, UNWRAP_BASE_ADDRESS, other, UNWRAP_ENCRYPTED_AMOUNT, UNWRAP_INPUT_PROOF);
1468
+ const wallet = new sdk_core_1.Wallet(bitgo, coin, {
1469
+ coinSpecific: { baseAddress: UNWRAP_BASE_ADDRESS },
1470
+ });
1471
+ await coin
1472
+ .verifyTransaction({
1473
+ txParams: { type: 'unwrap' },
1474
+ txPrebuild: { txHex },
1475
+ wallet,
1476
+ })
1477
+ .should.be.rejectedWith(/unwrap to must equal wallet base address/);
1478
+ });
1479
+ });
1480
+ // ---------------------------------------------------------------------------
1481
+ // verifyTransaction – FinalizeUnwrapERC7984 (unshield phase-2)
1482
+ // ---------------------------------------------------------------------------
1483
+ const FINALIZE_REQUEST_ID = '0x' + '11'.repeat(32);
1484
+ const FINALIZE_CLEARTEXT_AMOUNT = '1000000';
1485
+ const FINALIZE_DECRYPTION_PROOF = '0x' + 'ee'.repeat(64);
1486
+ async function buildDirectFinalizeUnwrapTxHex(tokenAddress, requestId, cleartextAmount, decryptionProof) {
1487
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
1488
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
1489
+ txBuilder.counter(1);
1490
+ txBuilder.type(sdk_core_1.TransactionType.FinalizeUnwrapERC7984);
1491
+ txBuilder.contract(tokenAddress);
1492
+ txBuilder.finalizeUnwrapRequestId(requestId);
1493
+ txBuilder.finalizeUnwrapCleartextAmount(cleartextAmount);
1494
+ txBuilder.finalizeUnwrapDecryptionProof(decryptionProof);
1495
+ const tx = await txBuilder.build();
1496
+ return tx.toBroadcastFormat();
1497
+ }
1498
+ async function buildMultisigFinalizeUnwrapTxHex(tokenAddress, requestId, cleartextAmount, decryptionProof) {
1499
+ const finalizeCalldata = (0, abstract_eth_1.buildFinalizeUnwrapCalldata)(requestId, cleartextAmount, decryptionProof);
1500
+ const sendData = (0, abstract_eth_1.sendMultiSigData)(tokenAddress, '0', finalizeCalldata, Math.floor(Date.now() / 1000) + 3600, 14, DUMMY_MULTISIG_SIGNATURE);
1501
+ const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
1502
+ txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
1503
+ txBuilder.counter(1);
1504
+ txBuilder.type(sdk_core_1.TransactionType.ContractCall);
1505
+ txBuilder.contract(MULTISIG_WALLET_CONTRACT);
1506
+ txBuilder.data(sendData);
1507
+ const tx = await txBuilder.build();
1508
+ return tx.toBroadcastFormat();
1509
+ }
1510
+ describe('verifyTransaction – FinalizeUnwrapERC7984', function () {
1511
+ let bitgo;
1512
+ let coin;
1513
+ before(function () {
1514
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1515
+ bitgo.initializeTestVars();
1516
+ (0, register_1.register)(bitgo);
1517
+ coin = bitgo.coin('hteth:ctest1');
1518
+ });
1519
+ it('should verify a valid direct finalizeUnwrap tx (TSS shape)', async function () {
1520
+ const txHex = await buildDirectFinalizeUnwrapTxHex(CTEST1_TOKEN_ADDRESS, FINALIZE_REQUEST_ID, FINALIZE_CLEARTEXT_AMOUNT, FINALIZE_DECRYPTION_PROOF);
1521
+ const result = await coin.verifyTransaction({
1522
+ txParams: {
1523
+ type: 'finalizeUnwrap',
1524
+ recipients: [{ address: UNWRAP_BASE_ADDRESS, amount: FINALIZE_CLEARTEXT_AMOUNT }],
1525
+ },
1526
+ txPrebuild: { txHex },
1527
+ wallet: {},
1528
+ });
1529
+ result.should.equal(true);
1530
+ });
1531
+ it('should verify a valid multisig finalizeUnwrap tx (sendMultiSig → finalizeUnwrap)', async function () {
1532
+ const txHex = await buildMultisigFinalizeUnwrapTxHex(CTEST1_TOKEN_ADDRESS, FINALIZE_REQUEST_ID, FINALIZE_CLEARTEXT_AMOUNT, FINALIZE_DECRYPTION_PROOF);
1533
+ const result = await coin.verifyTransaction({
1534
+ txParams: {
1535
+ type: 'finalizeUnwrap',
1536
+ recipients: [{ address: UNWRAP_BASE_ADDRESS, amount: FINALIZE_CLEARTEXT_AMOUNT }],
1537
+ },
1538
+ txPrebuild: { txHex },
1539
+ wallet: {},
1540
+ });
1541
+ result.should.equal(true);
1542
+ });
1543
+ it('should reject finalizeUnwrap when amount mismatches recipients', async function () {
1544
+ const txHex = await buildDirectFinalizeUnwrapTxHex(CTEST1_TOKEN_ADDRESS, FINALIZE_REQUEST_ID, FINALIZE_CLEARTEXT_AMOUNT, FINALIZE_DECRYPTION_PROOF);
1545
+ await coin
1546
+ .verifyTransaction({
1547
+ txParams: {
1548
+ type: 'finalizeUnwrap',
1549
+ recipients: [{ address: UNWRAP_BASE_ADDRESS, amount: '999' }],
1550
+ },
1551
+ txPrebuild: { txHex },
1552
+ wallet: {},
1553
+ })
1554
+ .should.be.rejectedWith(/amount mismatch/);
1555
+ });
1556
+ it('should reject finalizeUnwrap when wrapper address mismatches token', async function () {
1557
+ const wrongWrapper = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
1558
+ const txHex = await buildDirectFinalizeUnwrapTxHex(wrongWrapper, FINALIZE_REQUEST_ID, FINALIZE_CLEARTEXT_AMOUNT, FINALIZE_DECRYPTION_PROOF);
1559
+ await coin
1560
+ .verifyTransaction({
1561
+ txParams: { type: 'finalizeUnwrap' },
1562
+ txPrebuild: { txHex },
1563
+ wallet: {},
1564
+ })
1565
+ .should.be.rejectedWith(/wrapper address mismatch/);
1566
+ });
1567
+ });
1568
+ // ---------------------------------------------------------------------------
1569
+ // setGasLimit() override tests
1570
+ // ---------------------------------------------------------------------------
1571
+ describe('Erc7984Token – setGasLimit()', function () {
1572
+ let bitgo;
1573
+ let coin;
1574
+ before(function () {
1575
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
1576
+ bitgo.initializeTestVars();
1577
+ (0, register_1.register)(bitgo);
1578
+ coin = bitgo.coin('hteth:ctest1');
1579
+ });
1580
+ it('should return 800000 as default gas limit', function () {
1581
+ const gasLimit = coin.setGasLimit();
1582
+ gasLimit.should.equal(800000);
1583
+ });
1584
+ it('should accept user-provided gas limit', function () {
1585
+ const gasLimit = coin.setGasLimit(1000000);
1586
+ gasLimit.should.equal(1000000);
1587
+ });
1588
+ });
1589
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJjNzk4NFRva2VuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2VyYzc5ODRUb2tlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFDSCxvREFBNEI7QUFDNUIsa0RBQTBCO0FBQzFCLGlEQUErQztBQUMvQyxtREFBK0Q7QUFDL0QsbURBQStEO0FBQy9ELDJEQVdrQztBQUdsQyw2Q0FBMEM7QUFDMUMsaURBQThDO0FBQzlDLDJEQUE2QztBQUU3Qyw4RUFBOEU7QUFDOUUsWUFBWTtBQUNaLDhFQUE4RTtBQUU5RSwwRUFBMEU7QUFDMUUsTUFBTSxnQkFBZ0IsR0FBRyw0Q0FBNEMsQ0FBQztBQUN0RSxNQUFNLGdCQUFnQixHQUFHLDRDQUE0QyxDQUFDO0FBRXRFLHNFQUFzRTtBQUN0RSxNQUFNLG9CQUFvQixHQUFHLDRDQUE0QyxDQUFDO0FBQzFFLHFFQUFxRTtBQUNyRSxNQUFNLG1CQUFtQixHQUFHLDRDQUE0QyxDQUFDO0FBRXpFLE1BQU0sbUJBQW1CLEdBQUcsNENBQTRDLENBQUM7QUFDekUsTUFBTSxpQkFBaUIsR0FBRyw0Q0FBNEMsQ0FBQztBQUN2RSxNQUFNLGlCQUFpQixHQUFHLDRDQUE0QyxDQUFDO0FBRXZFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUM7QUFFM0QsOEVBQThFO0FBQzlFLFVBQVU7QUFDViw4RUFBOEU7QUFFOUU7O0dBRUc7QUFDSCxLQUFLLFVBQVUsb0JBQW9CLENBQUMsVUFBa0IsRUFBRSxjQUF3QixFQUFFLEtBQUssR0FBRyxHQUFHO0lBQzNGLE1BQU0sU0FBUyxHQUFHLElBQUEsdUJBQVUsRUFBQyxPQUFPLENBQXVCLENBQUM7SUFDNUQsU0FBUyxDQUFD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QUN2QyxJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxJQUFrQixDQUFDO0lBRXZCLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsSUFBQSxtQkFBUSxFQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hCLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBaUIsQ0FBQztJQUNwRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQywyQ0FBMkMsRUFBRTtRQUM5QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDcEMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUNBQXVDLEVBQUU7UUFDMUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNqQyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVbml0IHRlc3RzIGZvciBFcmM3OTg0VG9rZW4uXG4gKlxuICogQ292ZXJzOlxuICogICAtIGdldFRva2VuRW5hYmxlbWVudENvbmZpZ1xuICogICAtIHZlcmlmeVRyYW5zYWN0aW9uIChUU1MgYW5kIG11bHRpc2lnIHBhdGhzKVxuICogICAtIHZlcmlmeVRyYW5zYWN0aW9uIChjb25maWRlbnRpYWwgdHJhbnNmZXIgLyBTZW5kRVJDNzk4NCBwYXRoKVxuICogICAtIGRlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YSAocm91bmQtdHJpcCBhbmQgZm9yd2FyZGVyLXdyYXBwZWQpXG4gKiAgIC0gcmVjb3ZlcigpIChFUkMtNzk4NCBjb25maWRlbnRpYWwgdG9rZW4gcmVjb3ZlcnkpXG4gKiAgIC0gcXVlcnlDb25maWRlbnRpYWxCYWxhbmNlKClcbiAqL1xuaW1wb3J0IHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWFwaSc7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcbmltcG9ydCB7IFRyYW5zYWN0aW9uVHlwZSwgV2FsbGV0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0IHtcbiAgYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEsXG4gIGJ1aWxkRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YSxcbiAgYnVpbGRXcmFwQ2FsbGRhdGEsXG4gIGJ1aWxkVW53cmFwQ2FsbGRhdGEsXG4gIGJ1aWxkRmluYWxpemVVbndyYXBDYWxsZGF0YSxcbiAgc2VuZE11bHRpU2lnRGF0YSxcbiAgd3JhcEluQ2FsbEZyb21QYXJlbnQsXG4gIGRlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YSxcbiAgVHJhbnNmZXJCdWlsZGVyRVJDNzk4NCxcbiAgY29uZmlkZW50aWFsVHJhbnNmZXJOb1Byb29mTWV0aG9kSWQsXG59IGZyb20gJ0BiaXRnby1iZXRhL2Fic3RyYWN0LWV0aCc7XG5pbXBvcnQgeyBFcmM3OTg0VG9rZW4gfSBmcm9tICcuLi8uLi9zcmMvZXJjNzk4NFRva2VuJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uQnVpbGRlciB9IGZyb20gJy4uLy4uL3NyYy9saWInO1xuaW1wb3J0IHsgZ2V0QnVpbGRlciB9IGZyb20gJy4vZ2V0QnVpbGRlcic7XG5pbXBvcnQgeyByZWdpc3RlciB9IGZyb20gJy4uLy4uL3NyYy9yZWdpc3Rlcic7XG5pbXBvcnQgKiBhcyB0ZXN0RGF0YSBmcm9tICcuLi9yZXNvdXJjZXMvZXRoJztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDb25zdGFudHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBIb29kaSBBQ0wgY29udHJhY3QgYWRkcmVzcyAoTmV0d29ya3MudGVzdC5ob29kaS56YW1hQWNsQ29udHJhY3RBZGRyZXNzKVxuY29uc3QgWkFNQV9BQ0xfQUREUkVTUyA9ICcweDZkM2ZhZjZmODZlMWZmOWYzYjA4MzFkZGE5MjBhYmExY2JkNWJkNjgnO1xuY29uc3QgREVMRUdBVEVfQUREUkVTUyA9ICcweDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEnO1xuXG4vLyBodGV0aDpjdGVzdDEgdG9rZW4gY29udHJhY3QgYWRkcmVzcyAoZnJvbSBzdGF0aWNzL2VyYzc5ODRUb2tlbnMudHMpXG5jb25zdCBDVEVTVDFfVE9LRU5fQUREUkVTUyA9ICcweDdiMWQ1OWJiY2QyOTFkYWE1OWNiNmM4YzViYzA0ZGUxYWZjNGFiYTEnO1xuLy8gaHRldGg6Y3VzZHQgdG9rZW4gY29udHJhY3QgYWRkcmVzcyAoZnJvbSBzdGF0aWNzL2VyYzc5ODRUb2tlbnMudHMpXG5jb25zdCBDVVNEVF9UT0tFTl9BRERSRVNTID0gJzB4MmRlYmJlMDQ4N2VmOTIxZGY0NDU3ZjllMzZlZDA1YmUyZGYxYWM3NSc7XG5cbmNvbnN0IFdST05HX1RPS0VOX0FERFJFU1MgPSAnMHhkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmJztcbmNvbnN0IFdST05HX0FDTF9BRERSRVNTID0gJzB4YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSc7XG5jb25zdCBGT1JXQVJERVJfQUREUkVTUyA9ICcweDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAnO1xuXG5jb25zdCBFWFBJUlkgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKSArIDM2NSAqIDg2NDAwO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIEhlbHBlcnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEJ1aWxkcyBhIHJvb3Qtd2FsbGV0IGRlbGVnYXRpb24gdHggaGV4ICh0byA9IEFDTCwgZGF0YSA9IG11bHRpY2FsbCkuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkRGVsZWdhdGlvblR4SGV4KGFjbEFkZHJlc3M6IHN0cmluZywgdG9rZW5BZGRyZXNzZXM6IHN0cmluZ1tdLCB2YWx1ZSA9ICcwJyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMjAwMDAwJyB9KTtcbiAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICB0eEJ1aWxkZXIuY29udHJhY3QoYWNsQWRkcmVzcyk7XG4gIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgdG9rZW5BZGRyZXNzZXMsIEVYUElSWSk7XG4gIHR4QnVpbGRlci5kYXRhKGNhbGxkYXRhKTtcbiAgaWYgKHZhbHVlICE9PSAnMCcpIHtcbiAgICB0eEJ1aWxkZXIudmFsdWUodmFsdWUpO1xuICB9XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIGZvcndhcmRlciBkZWxlZ2F0aW9uIHR4IGhleCAodG8gPSBmb3J3YXJkZXIsIGRhdGEgPSBjYWxsRnJvbVBhcmVudChBQ0wsIDAsIG11bHRpY2FsbCkpLlxuICogVGhpcyBtaXJyb3JzIHdoYXQgRGVjcnlwdGlvbkRlbGVnYXRpb25CdWlsZGVyLmJ1aWxkKCkgcmV0dXJucyB3aGVuIGZvcndhcmRlckFkZHJlc3MgaXMgc2V0LlxuICovXG5hc3luYyBmdW5jdGlvbiBidWlsZEZvcndhcmRlckRlbGVnYXRpb25UeEhleChcbiAgZm9yd2FyZGVyQWRkcmVzczogc3RyaW5nLFxuICBhY2xBZGRyZXNzOiBzdHJpbmcsXG4gIHRva2VuQWRkcmVzc2VzOiBzdHJpbmdbXVxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gIHR4QnVpbGRlci5mZWUoeyBmZWU6ICcxMDAwMDAwMDAwJywgZ2FzTGltaXQ6ICcyMDAwMDAnIH0pO1xuICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gIHR4QnVpbGRlci5jb250cmFjdChmb3J3YXJkZXJBZGRyZXNzKTtcbiAgY29uc3QgaW5uZXJDYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIHRva2VuQWRkcmVzc2VzLCBFWFBJUlkpO1xuICBjb25zdCBvdXRlckNhbGxkYXRhID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoYWNsQWRkcmVzcywgaW5uZXJDYWxsZGF0YSk7XG4gIHR4QnVpbGRlci5kYXRhKG91dGVyQ2FsbGRhdGEpO1xuICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICByZXR1cm4gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUZXN0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmRlc2NyaWJlKCdFcmM3OTg0VG9rZW4nLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgY29pbjogRXJjNzk4NFRva2VuO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgcmVnaXN0ZXIoYml0Z28pO1xuICAgIGNvaW4gPSBiaXRnby5jb2luKCdodGV0aDpjdGVzdDEnKSBhcyBFcmM3OTg0VG9rZW47XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ2dldFRva2VuRW5hYmxlbWVudENvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiByZXF1aXJlc1Rva2VuRW5hYmxlbWVudDogdHJ1ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IGNvaW4uZ2V0VG9rZW5FbmFibGVtZW50Q29uZmlnKCk7XG4gICAgICBjb25maWcucmVxdWlyZXNUb2tlbkVuYWJsZW1lbnQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gc3VwcG9ydHNNdWx0aXBsZVRva2VuRW5hYmxlbWVudHM6IHRydWUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb25maWcgPSBjb2luLmdldFRva2VuRW5hYmxlbWVudENvbmZpZygpO1xuICAgICAgY29uZmlnLnN1cHBvcnRzTXVsdGlwbGVUb2tlbkVuYWJsZW1lbnRzLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24g4oCTIG5vbi1lbmFibGUtdG9rZW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByb3V0ZSB0byBjb25maWRlbnRpYWwgdHJhbnNmZXIgcGF0aCB3aGVuIHR5cGUgaXMgbm90IGVuYWJsZXRva2VuJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gTm9uLWVuYWJsZXRva2VuIHRyYW5zYWN0aW9ucyByb3V0ZSB0byB2ZXJpZnlDb25maWRlbnRpYWxUcmFuc2Zlci5cbiAgICAgIC8vIEVtcHR5IHJlY2lwaWVudHMgdHJpZ2dlcnMgb3VyIEVSQzc5ODQtc3BlY2lmaWMgdmFsaWRhdGlvbiBlcnJvcixcbiAgICAgIC8vIGNvbmZpcm1pbmcgdGhlIG92ZXJyaWRlIG9ubHkgaW50ZXJjZXB0cyB0aGUgZW5hYmxldG9rZW4gdHlwZS5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbXSB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3JlY2lwaWVudHMgbXVzdCBjb250YWluIGF0IGxlYXN0IG9uZSBlbnRyeS8pO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIGRlc2NyaWJlKCd2ZXJpZnlUcmFuc2FjdGlvbiDigJMgVFNTIHBhdGgnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBzaW5nbGUtdG9rZW4gZGVsZWdhdGlvbiB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREZWxlZ2F0aW9uVHhIZXgoWkFNQV9BQ0xfQUREUkVTUywgW0NURVNUMV9UT0tFTl9BRERSRVNTXSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgbXVsdGktdG9rZW4gZGVsZWdhdGlvbiB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREZWxlZ2F0aW9uVHhIZXgoWkFNQV9BQ0xfQUREUkVTUywgW0NURVNUMV9UT0tFTl9BRERSRVNTLCBDVVNEVF9UT0tFTl9BRERSRVNTXSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfSwgeyBuYW1lOiAnaHRldGg6Y3VzZHQnIH1dLFxuICAgICAgICB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gQUNMIGFkZHJlc3MgZG9lcyBub3QgbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRGVsZWdhdGlvblR4SGV4KFdST05HX0FDTF9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1NdKTtcbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvZG9lcyBub3QgbWF0Y2ggQUNMIGNvbnRyYWN0Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gY2FsbGRhdGEgY29udGFpbnMgd3JvbmcgdG9rZW4gYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREZWxlZ2F0aW9uVHhIZXgoWkFNQV9BQ0xfQUREUkVTUywgW1dST05HX1RPS0VOX0FERFJFU1NdKTtcbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbm90IGZvdW5kIGluIGRlbGVnYXRpb24gY2FsbGRhdGEvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgZm9yd2FyZGVyIGRlbGVnYXRpb24gdHggKGNhbGxGcm9tUGFyZW50IHNoYXBlKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRGb3J3YXJkZXJEZWxlZ2F0aW9uVHhIZXgoRk9SV0FSREVSX0FERFJFU1MsIFpBTUFfQUNMX0FERFJFU1MsIFtDVEVTVDFfVE9LRU5fQUREUkVTU10pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICBlbmFibGVUb2tlbnM6IFt7IG5hbWU6ICdodGV0aDpjdGVzdDEnIH1dLFxuICAgICAgICB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIGZvcndhcmRlciBkZWxlZ2F0aW9uIHR4IHdpdGggbXVsdGlwbGUgdG9rZW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZEZvcndhcmRlckRlbGVnYXRpb25UeEhleChGT1JXQVJERVJfQUREUkVTUywgWkFNQV9BQ0xfQUREUkVTUywgW1xuICAgICAgICBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICAgICAgQ1VTRFRfVE9LRU5fQUREUkVTUyxcbiAgICAgIF0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICBlbmFibGVUb2tlbnM6IFt7IG5hbWU6ICdodGV0aDpjdGVzdDEnIH0sIHsgbmFtZTogJ2h0ZXRoOmN1c2R0JyB9XSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGZvcndhcmRlciBjYWxsZGF0YSBjb250YWlucyB3cm9uZyB0b2tlbiBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZEZvcndhcmRlckRlbGVnYXRpb25UeEhleChGT1JXQVJERVJfQUREUkVTUywgWkFNQV9BQ0xfQUREUkVTUywgW1dST05HX1RPS0VOX0FERFJFU1NdKTtcbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbm90IGZvdW5kIGluIGRlbGVnYXRpb24gY2FsbGRhdGEvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBjYWxsZGF0YSBoYXMgdW5yZWNvZ25pc2VkIG1ldGhvZCBJRCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIEJ1aWxkIGEgdHggd2l0aCBhcmJpdHJhcnkgY2FsbGRhdGEgdGhhdCBpcyBuZWl0aGVyIG11bHRpY2FsbCBub3IgY2FsbEZyb21QYXJlbnRcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgICAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAwMDAwMDAnLCBnYXNMaW1pdDogJzIwMDAwMCcgfSk7XG4gICAgICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICAgICAgdHhCdWlsZGVyLmNvbnRyYWN0KFpBTUFfQUNMX0FERFJFU1MpO1xuICAgICAgdHhCdWlsZGVyLmRhdGEoJzB4ZGVhZGJlZWYnKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0eEhleCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvdW5yZWNvZ25pc2VkIGNhbGxkYXRhIG1ldGhvZCBJRC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHRyYW5zYWN0aW9uIHZhbHVlIGlzIG5vdCAwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERlbGVnYXRpb25UeEhleChaQU1BX0FDTF9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1NdLCAnMScpO1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9leHBlY3RlZCB0cmFuc2FjdGlvbiB2YWx1ZSAwLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gZW5hYmxlVG9rZW5zIGlzIGVtcHR5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERlbGVnYXRpb25UeEhleChaQU1BX0FDTF9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1NdKTtcbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIGVuYWJsZVRva2VuczogW10sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvZW5hYmxlVG9rZW5zIG11c3QgYmUgbm9uLWVtcHR5Lyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHhIZXggaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9taXNzaW5nIHR4SGV4Lyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ3ZlcmlmeVRyYW5zYWN0aW9uIOKAkyBtdWx0aXNpZyBwYXRoJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdmVyaWZ5IHZhbGlkIGJ1aWxkUGFyYW1zIHJlY2lwaWVudHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIHJlY2lwaWVudHM6IFt7IHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzAnIH1dIGFzIGFueSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIGJ1aWxkUGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICB3YWxsZXRUeXBlOiAnb25jaGFpbicsXG4gICAgICB9KTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBtdWx0aXBsZSB0b2tlbiByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICB7IHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzAnIH0sXG4gICAgICAgICAgICB7IHRva2VuTmFtZTogJ2h0ZXRoOmN1c2R0JywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfSxcbiAgICAgICAgICBdIGFzIGFueSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIGJ1aWxkUGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7IHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzAnIH0sXG4gICAgICAgICAgICAgIHsgdG9rZW5OYW1lOiAnaHRldGg6Y3VzZHQnLCBhZGRyZXNzOiAnMHhhYmMnLCBhbW91bnQ6ICcwJyB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgIHdhbGxldFR5cGU6ICdvbmNoYWluJyxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBidWlsZFBhcmFtcyByZWNpcGllbnRzIGhhdmUgd3JvbmcgdG9rZW5OYW1lJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfV0gYXMgYW55LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgICAgcmVjaXBpZW50czogW3sgdG9rZW5OYW1lOiAnaHRldGg6d3Jvbmd0b2tlbicsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzAnIH1dLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXRUeXBlOiAnb25jaGFpbicsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9ub3QgZm91bmQgaW4gYnVpbGRQYXJhbXMgcmVjaXBpZW50cy8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGFtb3VudCBpcyBub3QgMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzAnIH1dIGFzIGFueSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIGJ1aWxkUGFyYW1zOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IHRva2VuTmFtZTogJ2h0ZXRoOmN0ZXN0MScsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzEwMCcgfV0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICdvbmNoYWluJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2V4cGVjdGVkIGFtb3VudCAwLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50cyBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgYnVpbGRQYXJhbXM6IHt9LFxuICAgICAgICAgIH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICdvbmNoYWluJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL21pc3NpbmcgYnVpbGRQYXJhbXMucmVjaXBpZW50cy8pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIHZlcmlmeVRyYW5zYWN0aW9uIOKAkyBjb25maWRlbnRpYWwgdHJhbnNmZXIgKFNlbmRFUkM3OTg0KSB0ZXN0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQnVpbGQgYSByYXcgc2lnbmVkIHNlbmRNdWx0aVNpZyB0eCBoZXggdGhhdCB3cmFwcyBhIGNvbmZpZGVudGlhbFRyYW5zZmVyIGNhbGwuXG4gKiBUaGUgd2FsbGV0IGNvbnRyYWN0IChzZW5kTXVsdGlTaWcgd3JhcHBlcikgaXMgYHdhbGxldENvbnRyYWN0QWRkcmVzc2AuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkQ29uZmlkZW50aWFsVHJhbnNmZXJUeEhleChvcHRzOiB7XG4gIHdhbGxldENvbnRyYWN0QWRkcmVzczogc3RyaW5nO1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzczogc3RyaW5nO1xuICByZWNpcGllbnRBZGRyZXNzOiBzdHJpbmc7XG4gIGVuY3J5cHRlZEhhbmRsZTogc3RyaW5nO1xuICBpbnB1dFByb29mOiBzdHJpbmc7XG59KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3Qga2V5ID0gdGVzdERhdGEuS0VZUEFJUl9QUlYuZ2V0S2V5cygpLnBydiBhcyBzdHJpbmc7XG4gIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMTIxMDAwMDAnIH0pO1xuICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgdHhCdWlsZGVyLmNvbnRyYWN0KG9wdHMud2FsbGV0Q29udHJhY3RBZGRyZXNzKTtcbiAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmRFUkM3OTg0KTtcblxuICBjb25zdCB0cmFuc2ZlckJ1aWxkZXIgPSB0eEJ1aWxkZXIudHJhbnNmZXIoKSBhcyBUcmFuc2ZlckJ1aWxkZXJFUkM3OTg0O1xuICB0cmFuc2ZlckJ1aWxkZXJcbiAgICAuZnJvbSgnMHgxOTY0NTAzMmM3ZjE1MzMzOTVkNDRhNjI5NDYyZTc1MTA4NGQzZTRkJylcbiAgICAudG8ob3B0cy5yZWNpcGllbnRBZGRyZXNzKVxuICAgIC50b2tlbkNvbnRyYWN0QWRkcmVzcyhvcHRzLnRva2VuQ29udHJhY3RBZGRyZXNzKVxuICAgIC5lbmNyeXB0ZWRIYW5kbGUob3B0cy5lbmNyeXB0ZWRIYW5kbGUpXG4gICAgLmlucHV0UHJvb2Yob3B0cy5pbnB1dFByb29mKVxuICAgIC5jb250cmFjdFNlcXVlbmNlSWQoMSlcbiAgICAuZXhwaXJhdGlvblRpbWUoTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCkgKyAzNjAwKVxuICAgIC5rZXkoa2V5KTtcblxuICB0eEJ1aWxkZXIuc2lnbih7IGtleTogdGVzdERhdGEuUFJJVkFURV9LRVkgfSk7XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG5kZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24g4oCTIGNvbmZpZGVudGlhbCB0cmFuc2ZlciAoU2VuZEVSQzc5ODQpJywgZnVuY3Rpb24gKCkge1xuICAvLyBXYWxsZXQgY29udHJhY3QgdGhhdCB3cmFwcyB0aGUgc2VuZE11bHRpU2lnIGNhbGxcbiAgY29uc3QgV0FMTEVUX0NPTlRSQUNUID0gJzB4OGY5NzdlOTEyZWY1MDA1NDhhMGMzYmU2ZGRkZTk4OTlmMTE5OWI4MSc7XG4gIC8vIFJlY2lwaWVudCBvZiB0aGUgY29uZmlkZW50aWFsIHRyYW5zZmVyXG4gIGNvbnN0IFJFQ0lQSUVOVCA9ICcweDE5NjQ1MDMyYzdmMTUzMzM5NWQ0NGE2Mjk0NjJlNzUxMDg0ZDNlNGMnO1xuICAvLyBFbmNyeXB0ZWQgaGFuZGxlOiBzeW50aGV0aWMgMzIgYnl0ZXNcbiAgY29uc3QgSEFORExFID0gJzB4JyArICdhYicucmVwZWF0KDMyKTtcbiAgLy8gSW5wdXQgcHJvb2Y6IHN5bnRoZXRpYyA1MCBieXRlc1xuICBjb25zdCBQUk9PRiA9ICcweCcgKyAnY2QnLnJlcGVhdCg1MCk7XG4gIC8vIEEgZGlmZmVyZW50IHJlY2lwaWVudCB0byB0cmlnZ2VyIG1pc21hdGNoXG4gIGNvbnN0IFdST05HX1JFQ0lQSUVOVCA9ICcweGFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEnO1xuICAvLyBBIGRpZmZlcmVudCB0b2tlbiBjb250cmFjdCB0byB0cmlnZ2VyIG1pc21hdGNoXG4gIGNvbnN0IFdST05HX1RPS0VOID0gJzB4YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYic7XG5cbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBjb2luOiBFcmM3OTg0VG9rZW47XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICByZWdpc3RlcihiaXRnbyk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoOmN0ZXN0MScpIGFzIEVyYzc5ODRUb2tlbjtcbiAgfSk7XG5cbiAgLy8gUmVwcmVzZW50YXRpdmUgcGxhaW50ZXh0IGFtb3VudCBpbiBiYXNlIHVuaXRzIChlLmcuLCAxIGNURVNUMSA9IDFfMDAwXzAwMCB1bml0cyBhdCA2IGRlY2ltYWxzKVxuICBjb25zdCBBTU9VTlQgPSAnMTAwMDAwMCc7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBjb25maWRlbnRpYWwgdHJhbnNmZXIgdHJhbnNhY3Rpb24gd2l0aCBtYXRjaGluZyBhbW91bnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgcmVjaXBpZW50QWRkcmVzczogUkVDSVBJRU5ULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiBIQU5ETEUsXG4gICAgICBpbnB1dFByb29mOiBQUk9PRixcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgdHhQcmVidWlsZDogeyB0eEhleCwgYnVpbGRQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9IH0gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIG5vIHJlY2lwaWVudCBpbmZvIGlzIHByb3ZpZGVkIGluIGVpdGhlciB0eFBhcmFtcyBvciBidWlsZFBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkQ29uZmlkZW50aWFsVHJhbnNmZXJUeEhleCh7XG4gICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IFdBTExFVF9DT05UUkFDVCxcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICAgIHJlY2lwaWVudEFkZHJlc3M6IFJFQ0lQSUVOVCxcbiAgICAgIGVuY3J5cHRlZEhhbmRsZTogSEFORExFLFxuICAgICAgaW5wdXRQcm9vZjogUFJPT0YsXG4gICAgfSk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9taXNzaW5nIGV4cGVjdGVkIHJlY2lwaWVudC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHZlcmlmeSBzdWNjZXNzZnVsbHkgdXNpbmcgYnVpbGRQYXJhbXMucmVjaXBpZW50cyB3aGVuIHR4UGFyYW1zIGhhcyBubyByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgcmVjaXBpZW50QWRkcmVzczogUkVDSVBJRU5ULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiBIQU5ETEUsXG4gICAgICBpbnB1dFByb29mOiBQUk9PRixcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHt9LFxuICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICB0eEhleCxcbiAgICAgICAgYnVpbGRQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgfSBhcyBhbnksXG4gICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICB9KTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdG9rZW4gY29udHJhY3QgYWRkcmVzcyBkb2VzIG5vdCBtYXRjaCB0aGlzIGNvaW4nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZENvbmZpZGVudGlhbFRyYW5zZmVyVHhIZXgoe1xuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogV1JPTkdfVE9LRU4sXG4gICAgICByZWNpcGllbnRBZGRyZXNzOiBSRUNJUElFTlQsXG4gICAgICBlbmNyeXB0ZWRIYW5kbGU6IEhBTkRMRSxcbiAgICAgIGlucHV0UHJvb2Y6IFBST09GLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvdG9rZW4gY29udHJhY3QgYWRkcmVzcyBtaXNtYXRjaC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50IGFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggdHhQYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZENvbmZpZGVudGlhbFRyYW5zZmVyVHhIZXgoe1xuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogQ1RFU1QxX1RPS0VOX0FERFJFU1MsXG4gICAgICByZWNpcGllbnRBZGRyZXNzOiBSRUNJUElFTlQsXG4gICAgICBlbmNyeXB0ZWRIYW5kbGU6IEhBTkRMRSxcbiAgICAgIGlucHV0UHJvb2Y6IFBST09GLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogV1JPTkdfUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvcmVjaXBpZW50IGFkZHJlc3MgbWlzbWF0Y2gvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGNhbGxkYXRhIGlzIG5vdCBhIGNvbmZpZGVudGlhbCB0cmFuc2ZlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMjAwMDAwJyB9KTtcbiAgICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgICB0eEJ1aWxkZXIuY29udHJhY3QoV0FMTEVUX0NPTlRSQUNUKTtcbiAgICB0eEJ1aWxkZXIuZGF0YSgnMHhkZWFkYmVlZjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyk7XG4gICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICBjb25zdCB0eEhleCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9mYWlsZWQgdG8gZGVjb2RlIGNvbmZpZGVudGlhbCB0cmFuc2ZlciBjYWxsZGF0YS8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHhQYXJhbXMgYW1vdW50IGRvZXMgbm90IG1hdGNoIGJ1aWxkUGFyYW1zIGFtb3VudCAod2l0aCB0eEhleCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZENvbmZpZGVudGlhbFRyYW5zZmVyVHhIZXgoe1xuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogQ1RFU1QxX1RPS0VOX0FERFJFU1MsXG4gICAgICByZWNpcGllbnRBZGRyZXNzOiBSRUNJUElFTlQsXG4gICAgICBlbmNyeXB0ZWRIYW5kbGU6IEhBTkRMRSxcbiAgICAgIGlucHV0UHJvb2Y6IFBST09GLFxuICAgIH0pO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6ICc5OTk5OTk5JyB9XSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXgsXG4gICAgICAgICAgYnVpbGRQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2Ftb3VudCBtaXNtYXRjaC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHhQYXJhbXMgYW1vdW50IGlzIDAgKHdpdGggdHhIZXgpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgcmVjaXBpZW50QWRkcmVzczogUkVDSVBJRU5ULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiBIQU5ETEUsXG4gICAgICBpbnB1dFByb29mOiBQUk9PRixcbiAgICB9KTtcblxuICAgIGF3YWl0IGNvaW5cbiAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7IHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFJFQ0lQSUVOVCwgYW1vdW50OiAnMCcgfV0gfSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2Ftb3VudCBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlciBzdHJpbmcvKTtcbiAgfSk7XG5cbiAgLy8g4pSA4pSAIEZpcnN0LXNpZ25lciAobm8gdHhIZXgpIHRlc3RzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IHZhbGlkIGZpcnN0LXNpZ25lciBwYXJhbXMgd2hlbiBubyB0eEhleCBpcyBwcmVzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgdHhQcmVidWlsZDoge30gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgZmlyc3Qtc2lnbmVyIHBhcmFtcyB3aGVuIHR4UGFyYW1zIGFuZCBidWlsZFBhcmFtcyBhbW91bnRzIG1hdGNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgdHhQcmVidWlsZDogeyBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0gfSBhcyBhbnksXG4gICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICB9KTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50cyBpcyBlbXB0eSBhbmQgbm8gdHhIZXggaXMgcHJlc2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbXSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7fSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9yZWNpcGllbnRzIG11c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgZW50cnkvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHJlY2lwaWVudCBhZGRyZXNzIGlzIGludmFsaWQgYW5kIG5vIHR4SGV4IGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogJ25vdC1hbi1hZGRyZXNzJywgYW1vdW50OiBBTU9VTlQgfV0gfSxcbiAgICAgICAgdHhQcmVidWlsZDoge30gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvcmVjaXBpZW50IGFkZHJlc3MgaXMgbWlzc2luZyBvciBpbnZhbGlkLyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBhbW91bnQgaXMgMCBhbmQgbm8gdHhIZXggaXMgcHJlc2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogJzAnIH1dIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHt9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2Ftb3VudCBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlciBzdHJpbmcvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGFtb3VudCBpcyBlbXB0eSBhbmQgbm8gdHhIZXggaXMgcHJlc2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogJycgfV0gfSxcbiAgICAgICAgdHhQcmVidWlsZDoge30gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvYW1vdW50IG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIHN0cmluZy8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHhQYXJhbXMgYW5kIGJ1aWxkUGFyYW1zIGFtb3VudHMgbWlzbWF0Y2ggYW5kIG5vIHR4SGV4IGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6ICc5OTk5OTk5JyB9XSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IGJ1aWxkUGFyYW1zOiB7IHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFJFQ0lQSUVOVCwgYW1vdW50OiBBTU9VTlQgfV0gfSB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2Ftb3VudCBtaXNtYXRjaC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHhQYXJhbXMgYW5kIGJ1aWxkUGFyYW1zIHJlY2lwaWVudCBhZGRyZXNzZXMgbWlzbWF0Y2ggYW5kIG5vIHR4SGV4IGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgYnVpbGRQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogV1JPTkdfUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3JlY2lwaWVudCBhZGRyZXNzIG1pc21hdGNoLyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IHdoZW4gdHhIZXggYWJzZW50IGFuZCBidWlsZFBhcmFtcyBoYXMgbWF0Y2hpbmcgcmVjaXBpZW50IGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0sXG4gICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgIGJ1aWxkUGFyYW1zOiB7IHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFJFQ0lQSUVOVCwgYW1vdW50OiBBTU9VTlQgfV0gfSxcbiAgICAgIH0gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgZGVjb2RlZCByZWNpcGllbnQgYWdhaW5zdCBidWlsZFBhcmFtcyB3aGVuIHR4UGFyYW1zLnJlY2lwaWVudHMgaXMgYWJzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgcmVjaXBpZW50QWRkcmVzczogUkVDSVBJRU5ULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiBIQU5ETEUsXG4gICAgICBpbnB1dFByb29mOiBQUk9PRixcbiAgICB9KTtcblxuICAgIC8vIE5vIHJlY2lwaWVudHMgaW4gdHhQYXJhbXMg4oCUIGZhbGxzIGJhY2sgdG8gYnVpbGRQYXJhbXMgZm9yIHJlY2lwaWVudCB2ZXJpZmljYXRpb25cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7fSxcbiAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgdHhIZXgsXG4gICAgICAgIGJ1aWxkUGFyYW1zOiB7IHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFJFQ0lQSUVOVCwgYW1vdW50OiBBTU9VTlQgfV0gfSxcbiAgICAgIH0gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGRlY29kZWQgcmVjaXBpZW50IGRvZXMgbm90IG1hdGNoIGJ1aWxkUGFyYW1zIHJlY2lwaWVudCAodHhQYXJhbXMgYWJzZW50KScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkQ29uZmlkZW50aWFsVHJhbnNmZXJUeEhleCh7XG4gICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IFdBTExFVF9DT05UUkFDVCxcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICAgIHJlY2lwaWVudEFkZHJlc3M6IFJFQ0lQSUVOVCxcbiAgICAgIGVuY3J5cHRlZEhhbmRsZTogSEFORExFLFxuICAgICAgaW5wdXRQcm9vZjogUFJPT0YsXG4gICAgfSk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleCxcbiAgICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBXUk9OR19SRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvcmVjaXBpZW50IGFkZHJlc3MgbWlzbWF0Y2gvKTtcbiAgfSk7XG59KTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyB2ZXJpZnlUcmFuc2FjdGlvbiDigJMgZGlyZWN0IGNvbmZpZGVudGlhbFRyYW5zZmVyIChob3QvVFNTIEVPQSB3YWxsZXQpIHRlc3RzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBCdWlsZHMgYSByYXcgdHggaGV4IHdoZXJlIHRoZSBFT0EgY2FsbHMgY29uZmlkZW50aWFsVHJhbnNmZXIgZGlyZWN0bHkgb24gdGhlIHRva2VuXG4gKiBjb250cmFjdCAobm8gc2VuZE11bHRpU2lnIHdyYXBwZXIpLiBUaGlzIGlzIHRoZSBob3QvVFNTIHdhbGxldCBwYXRoLlxuICovXG5hc3luYyBmdW5jdGlvbiBidWlsZERpcmVjdENvbmZpZGVudGlhbFRyYW5zZmVyVHhIZXgob3B0czoge1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzczogc3RyaW5nO1xuICByZWNpcGllbnRBZGRyZXNzOiBzdHJpbmc7XG4gIGVuY3J5cHRlZEhhbmRsZTogc3RyaW5nO1xuICBpbnB1dFByb29mOiBzdHJpbmc7XG59KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gIHR4QnVpbGRlci5mZWUoeyBmZWU6ICcxMDAwMDAwMDAwJywgZ2FzTGltaXQ6ICcyMDAwMDAnIH0pO1xuICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gIC8vIHR4LnRvID0gdG9rZW4gY29udHJhY3QgKEVPQSBjYWxscyBpdCBkaXJlY3RseSlcbiAgdHhCdWlsZGVyLmNvbnRyYWN0KG9wdHMudG9rZW5Db250cmFjdEFkZHJlc3MpO1xuICAvLyBJbm5lciBjYWxsZGF0YTogY29uZmlkZW50aWFsVHJhbnNmZXIoYWRkcmVzcywgYnl0ZXMzMiwgYnl0ZXMpIOKAlCBubyBzZW5kTXVsdGlTaWcgd3JhcHBlclxuICBjb25zdCBjYWxsZGF0YSA9IG5ldyBUcmFuc2ZlckJ1aWxkZXJFUkM3OTg0KClcbiAgICAudG8ob3B0cy5yZWNpcGllbnRBZGRyZXNzKVxuICAgIC50b2tlbkNvbnRyYWN0QWRkcmVzcyhvcHRzLnRva2VuQ29udHJhY3RBZGRyZXNzKVxuICAgIC5lbmNyeXB0ZWRIYW5kbGUob3B0cy5lbmNyeXB0ZWRIYW5kbGUpXG4gICAgLmlucHV0UHJvb2Yob3B0cy5pbnB1dFByb29mKVxuICAgIC5idWlsZCgpO1xuICB0eEJ1aWxkZXIuZGF0YShjYWxsZGF0YSk7XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG5kZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24g4oCTIGRpcmVjdCBjb25maWRlbnRpYWxUcmFuc2ZlciAoaG90L1RTUyBFT0Egd2FsbGV0KScsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgUkVDSVBJRU5UID0gJzB4MTk2NDUwMzJjN2YxNTMzMzk1ZDQ0YTYyOTQ2MmU3NTEwODRkM2U0Yyc7XG4gIGNvbnN0IEhBTkRMRSA9ICcweCcgKyAnYWInLnJlcGVhdCgzMik7XG4gIGNvbnN0IFBST09GID0gJzB4JyArICdjZCcucmVwZWF0KDUwKTtcbiAgY29uc3QgV1JPTkdfUkVDSVBJRU5UID0gJzB4YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSc7XG4gIGNvbnN0IFdST05HX1RPS0VOID0gJzB4YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYic7XG4gIGNvbnN0IEFNT1VOVCA9ICcxMDAwMDAwJztcblxuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IEVyYzc5ODRUb2tlbjtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIHJlZ2lzdGVyKGJpdGdvKTtcbiAgICBjb2luID0gYml0Z28uY29pbignaHRldGg6Y3Rlc3QxJykgYXMgRXJjNzk4NFRva2VuO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIGRpcmVjdCBjb25maWRlbnRpYWxUcmFuc2ZlciB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRGlyZWN0Q29uZmlkZW50aWFsVHJhbnNmZXJUeEhleCh7XG4gICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogQ1RFU1QxX1RPS0VOX0FERFJFU1MsXG4gICAgICByZWNpcGllbnRBZGRyZXNzOiBSRUNJUElFTlQsXG4gICAgICBlbmNyeXB0ZWRIYW5kbGU6IEhBTkRMRSxcbiAgICAgIGlucHV0UHJvb2Y6IFBST09GLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgdHhQcmVidWlsZDogeyB0eEhleCwgYnVpbGRQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9IH0gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgdXNpbmcgYnVpbGRQYXJhbXMucmVjaXBpZW50cyB3aGVuIHR4UGFyYW1zIGhhcyBubyByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICAgIHJlY2lwaWVudEFkZHJlc3M6IFJFQ0lQSUVOVCxcbiAgICAgIGVuY3J5cHRlZEhhbmRsZTogSEFORExFLFxuICAgICAgaW5wdXRQcm9vZjogUFJPT0YsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICB0eFBhcmFtczoge30sXG4gICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgIHR4SGV4LFxuICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0sXG4gICAgICB9IGFzIGFueSxcbiAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgIH0pO1xuICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiB0b2tlbiBjb250cmFjdCBhZGRyZXNzICh0eC50bykgZG9lcyBub3QgbWF0Y2ggdGhpcyBjb2luJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBXUk9OR19UT0tFTixcbiAgICAgIHJlY2lwaWVudEFkZHJlc3M6IFJFQ0lQSUVOVCxcbiAgICAgIGVuY3J5cHRlZEhhbmRsZTogSEFORExFLFxuICAgICAgaW5wdXRQcm9vZjogUFJPT0YsXG4gICAgfSk7XG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogUkVDSVBJRU5ULCBhbW91bnQ6IEFNT1VOVCB9XSB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvdG9rZW4gY29udHJhY3QgYWRkcmVzcyBtaXNtYXRjaC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50IGFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggdHhQYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERpcmVjdENvbmZpZGVudGlhbFRyYW5zZmVyVHhIZXgoe1xuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgcmVjaXBpZW50QWRkcmVzczogUkVDSVBJRU5ULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiBIQU5ETEUsXG4gICAgICBpbnB1dFByb29mOiBQUk9PRixcbiAgICB9KTtcbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBXUk9OR19SRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9yZWNpcGllbnQgYWRkcmVzcyBtaXNtYXRjaC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gbm8gcmVjaXBpZW50IGluZm8gaXMgcHJvdmlkZWQgaW4gZWl0aGVyIHR4UGFyYW1zIG9yIGJ1aWxkUGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RDb25maWRlbnRpYWxUcmFuc2ZlclR4SGV4KHtcbiAgICAgIHRva2VuQ29udHJhY3RBZGRyZXNzOiBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICAgIHJlY2lwaWVudEFkZHJlc3M6IFJFQ0lQSUVOVCxcbiAgICAgIGVuY3J5cHRlZEhhbmRsZTogSEFORExFLFxuICAgICAgaW5wdXRQcm9vZjogUFJPT0YsXG4gICAgfSk7XG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHt9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbWlzc2luZyBleHBlY3RlZCByZWNpcGllbnQvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHR4UGFyYW1zIGFtb3VudCBkb2VzIG5vdCBtYXRjaCBidWlsZFBhcmFtcyBhbW91bnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERpcmVjdENvbmZpZGVudGlhbFRyYW5zZmVyVHhIZXgoe1xuICAgICAgdG9rZW5Db250cmFjdEFkZHJlc3M6IENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgcmVjaXBpZW50QWRkcmVzczogUkVDSVBJRU5ULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiBIQU5ETEUsXG4gICAgICBpbnB1dFByb29mOiBQUk9PRixcbiAgICB9KTtcbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogJzk5OTk5OTknIH1dIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleCxcbiAgICAgICAgICBidWlsZFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBSRUNJUElFTlQsIGFtb3VudDogQU1PVU5UIH1dIH0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvYW1vdW50IG1pc21hdGNoLyk7XG4gIH0pO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhIHRlc3RzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZGVzY3JpYmUoJ2RlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgaXQoJ3Nob3VsZCBkZWNvZGUgYSBzaW5nbGUtdG9rZW4gbXVsdGljYWxsIGNhbGxkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW0NURVNUMV9UT0tFTl9BRERSRVNTXSwgRVhQSVJZKTtcbiAgICBjb25zdCBhZGRyZXNzZXMgPSBkZWNvZGVUb2tlbkFkZHJlc3Nlc0Zyb21EZWxlZ2F0aW9uQ2FsbGRhdGEoY2FsbGRhdGEpO1xuICAgIGFkZHJlc3Nlcy5zaG91bGQuZGVlcEVxdWFsKFtDVEVTVDFfVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpXSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgZGVjb2RlIGEgbXVsdGktdG9rZW4gbXVsdGljYWxsIGNhbGxkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoXG4gICAgICBERUxFR0FURV9BRERSRVNTLFxuICAgICAgW0NURVNUMV9UT0tFTl9BRERSRVNTLCBDVVNEVF9UT0tFTl9BRERSRVNTXSxcbiAgICAgIEVYUElSWVxuICAgICk7XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhKGNhbGxkYXRhKTtcbiAgICBhZGRyZXNzZXMuc2hvdWxkLmRlZXBFcXVhbChbQ1RFU1QxX1RPS0VOX0FERFJFU1MudG9Mb3dlckNhc2UoKSwgQ1VTRFRfVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpXSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGFkZHJlc3NlcyBpbiBsb3dlcmNhc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgbWl4ZWRDYXNlID0gJzB4N0IxRDU5YmJDRDI5MWRhQTU5Y0I2QzhDNWJjMDREZTFBRkM0YUJBMSc7XG4gICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbbWl4ZWRDYXNlXSwgRVhQSVJZKTtcbiAgICBjb25zdCBhZGRyZXNzZXMgPSBkZWNvZGVUb2tlbkFkZHJlc3Nlc0Zyb21EZWxlZ2F0aW9uQ2FsbGRhdGEoY2FsbGRhdGEpO1xuICAgIGFkZHJlc3Nlc1swXS5zaG91bGQuZXF1YWwobWl4ZWRDYXNlLnRvTG93ZXJDYXNlKCkpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGhhbmRsZSBjYWxsRnJvbVBhcmVudC13cmFwcGVkIG11bHRpY2FsbCBjYWxsZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBpbm5lciA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKFxuICAgICAgREVMRUdBVEVfQUREUkVTUyxcbiAgICAgIFtDVEVTVDFfVE9LRU5fQUREUkVTUywgQ1VTRFRfVE9LRU5fQUREUkVTU10sXG4gICAgICBFWFBJUllcbiAgICApO1xuICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChaQU1BX0FDTF9BRERSRVNTLCBpbm5lcik7XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhKHdyYXBwZWQpO1xuICAgIGFkZHJlc3Nlcy5zaG91bGQuZGVlcEVxdWFsKFtDVEVTVDFfVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpLCBDVVNEVF9UT0tFTl9BRERSRVNTLnRvTG93ZXJDYXNlKCldKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB3b3JrIHdpdGggY2FsbGRhdGEgbWlzc2luZyAweCBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgIGNvbnN0IG5vUHJlZml4ID0gY2FsbGRhdGEuc2xpY2UoMik7IC8vIHN0cmlwIDB4XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhKG5vUHJlZml4KTtcbiAgICBhZGRyZXNzZXMuc2hvdWxkLmRlZXBFcXVhbChbQ1RFU1QxX1RPS0VOX0FERFJFU1MudG9Mb3dlckNhc2UoKV0pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGZvciB1bnJlY29nbmlzZWQgY2FsbGRhdGEnLCBmdW5jdGlvbiAoKSB7XG4gICAgc2hvdWxkLnRocm93cyhcbiAgICAgICgpID0+IGRlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YSgnMHhkZWFkYmVlZjAwMDAwMDAwJyksXG4gICAgICAvTm90IGEgdmFsaWQgZGVsZWdhdGlvbiBjYWxsZGF0YS9cbiAgICApO1xuICB9KTtcbn0pO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIHZlcmlmeVRyYW5zYWN0aW9uIOKAkyBjb25maWRlbnRpYWwgY29uc29saWRhdGlvbiAoRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW4pXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuY29uc3QgTVVMVElTSUdfV0FMTEVUX0NPTlRSQUNUID0gJzB4M2I1ODY4NDUyNTU2NGIzOGEzODFlNDZhNzMxNzAzZWQwM2YzMjEyMic7XG5jb25zdCBDT05TT0xJREFUSU9OX0ZPUldBUkRFUiA9ICcweGY0YmNiMzY2YmI1ZTM0ZWJiZWU1MWZhZTVkZTk4Y2M4NzZjMDE0NmYnO1xuY29uc3QgQ09OU09MSURBVElPTl9CQVNFX0FERFJFU1MgPSAnMHgzYjU4Njg0NTI1NTY0YjM4YTM4MWU0NmE3MzE3MDNlZDAzZjMyMTIyJztcbmNvbnN0IENPTlNPTElEQVRJT05fSEFORExFID0gJzB4NjVkZjEzNmI2MDlhYjM5NWMxYTk5YWU0NmY3OTM5YzdmOGIyMGRmZjRiZmYwMDAwMDAwMDg4YmIwMDUwJztcbmNvbnN0IERVTU1ZX01VTFRJU0lHX1NJR05BVFVSRSA9ICcweCcgKyAnMDAnLnJlcGVhdCg2NSk7XG5cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkTXVsdGlzaWdDb25zb2xpZGF0aW9uVHhIZXgoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgZmx1c2hDYWxsZGF0YSA9IGJ1aWxkRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW5DYWxsZGF0YShcbiAgICBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICBDT05TT0xJREFUSU9OX0JBU0VfQUREUkVTUyxcbiAgICBDT05TT0xJREFUSU9OX0hBTkRMRVxuICApO1xuICBjb25zdCBzZW5kRGF0YSA9IHNlbmRNdWx0aVNpZ0RhdGEoXG4gICAgQ09OU09MSURBVElPTl9GT1JXQVJERVIsXG4gICAgJzAnLFxuICAgIGZsdXNoQ2FsbGRhdGEsXG4gICAgTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCkgKyAzNjAwLFxuICAgIDE0LFxuICAgIERVTU1ZX01VTFRJU0lHX1NJR05BVFVSRVxuICApO1xuXG4gIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMTIxMDAwMDAnIH0pO1xuICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gIHR4QnVpbGRlci5jb250cmFjdChNVUxUSVNJR19XQUxMRVRfQ09OVFJBQ1QpO1xuICB0eEJ1aWxkZXIuZGF0YShzZW5kRGF0YSk7XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZERpcmVjdENvbnNvbGlkYXRpb25UeEhleCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAwMDAwMDAnLCBnYXNMaW1pdDogJzIwMDAwMCcgfSk7XG4gIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuRmx1c2hFUkM3OTg0Rm9yd2FyZGVyVG9rZW4pO1xuICB0eEJ1aWxkZXIuY29udHJhY3QoQ09OU09MSURBVElPTl9GT1JXQVJERVIpO1xuICB0eEJ1aWxkZXIuZm9yd2FyZGVyQWRkcmVzcyhDT05TT0xJREFUSU9OX0ZPUldBUkRFUik7XG4gIHR4QnVpbGRlci50b2tlbkNvbnRyYWN0QWRkcmVzcyhDVEVTVDFfVE9LRU5fQUREUkVTUyk7XG4gIHR4QnVpbGRlci5wYXJlbnRBZGRyZXNzKENPTlNPTElEQVRJT05fQkFTRV9BRERSRVNTKTtcbiAgdHhCdWlsZGVyLmVuY3J5cHRlZEhhbmRsZShDT05TT0xJREFUSU9OX0hBTkRMRSk7XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG5kZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24g4oCTIGNvbmZpZGVudGlhbCBjb25zb2xpZGF0aW9uIChGbHVzaEVSQzc5ODRGb3J3YXJkZXJUb2tlbiknLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgY29pbjogRXJjNzk4NFRva2VuO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgcmVnaXN0ZXIoYml0Z28pO1xuICAgIGNvaW4gPSBiaXRnby5jb2luKCdodGV0aDpjdGVzdDEnKSBhcyBFcmM3OTg0VG9rZW47XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgbXVsdGlzaWcgY29uc29saWRhdGlvbiB0eCAoc2VuZE11bHRpU2lnIOKGkiBjYWxsRnJvbVBhcmVudCDihpIgY29uZmlkZW50aWFsVHJhbnNmZXJOb1Byb29mKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkTXVsdGlzaWdDb25zb2xpZGF0aW9uVHhIZXgoKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IENPTlNPTElEQVRJT05fQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICdjb25zb2xpZGF0ZScgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2YTQ0ZWJjMDMyNmUxYmU0NWMxZDc5NzU0MmM4YzYzNCcsXG4gICAgICAgIHR4SGV4LFxuICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBDT05TT0xJREFUSU9OX0ZPUldBUkRFUiwgYW1vdW50OiAnMCcgfV0sXG4gICAgICB9IGFzIGFueSxcbiAgICAgIHdhbGxldCxcbiAgICB9KTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIGRpcmVjdCBjYWxsRnJvbVBhcmVudCBjb25zb2xpZGF0aW9uIHR4IChUU1Mgc2hhcGUpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RDb25zb2xpZGF0aW9uVHhIZXgoKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IENPTlNPTElEQVRJT05fQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICdjb25zb2xpZGF0ZScgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2YTQ0ZWJjMDMyNmUxYmU0NWMxZDc5NzU0MmM4YzYzNCcsXG4gICAgICAgIHR4SGV4LFxuICAgICAgfSBhcyBhbnksXG4gICAgICB3YWxsZXQsXG4gICAgICB2ZXJpZmljYXRpb246IHsgY29uc29saWRhdGlvblRvQmFzZUFkZHJlc3M6IHRydWUgfSxcbiAgICB9KTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCBtdWx0aXNpZyBjb25zb2xpZGF0aW9uIHdoZW4gcGFyZW50IGFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggd2FsbGV0IGJhc2UgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkTXVsdGlzaWdDb25zb2xpZGF0aW9uVHhIZXgoKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6ICcweGFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEnIH0sXG4gICAgfSk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyB0eXBlOiAnY29uc29saWRhdGUnIH0gYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IGNvbnNvbGlkYXRlSWQ6ICdhYmMxMjMnLCB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9wYXJlbnQgYWRkcmVzcyBtaXNtYXRjaC8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHZlcmlmeSBtdWx0aXNpZyBjb25zb2xpZGF0aW9uIHVzaW5nIGZvcndhcmRlciBhZGRyZXNzIGZyb20gdHhQcmVidWlsZC50eEluZm8ucmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkTXVsdGlzaWdDb25zb2xpZGF0aW9uVHhIZXgoKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IENPTlNPTElEQVRJT05fQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICAvLyBObyB0b3AtbGV2ZWwgcmVjaXBpZW50czsgZm9yd2FyZGVyIGNvbWVzIGZyb20gdHhJbmZvLnJlY2lwaWVudHNcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICdjb25zb2xpZGF0ZScgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2YTQ0ZWJjMDMyNmUxYmU0NWMxZDc5NzU0MmM4YzYzNCcsXG4gICAgICAgIHR4SGV4LFxuICAgICAgICB0eEluZm86IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogQ09OU09MSURBVElPTl9GT1JXQVJERVIsIGFtb3VudDogJzAnIH1dIH0sXG4gICAgICB9IGFzIGFueSxcbiAgICAgIHdhbGxldCxcbiAgICB9KTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCBtdWx0aXNpZyBjb25zb2xpZGF0aW9uIHdoZW4gdHhJbmZvLnJlY2lwaWVudHMgZm9yd2FyZGVyIGFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggdHggZm9yd2FyZGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRNdWx0aXNpZ0NvbnNvbGlkYXRpb25UeEhleCgpO1xuICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgIGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogQ09OU09MSURBVElPTl9CQVNFX0FERFJFU1MgfSxcbiAgICB9KTtcblxuICAgIGF3YWl0IGNvaW5cbiAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICdjb25zb2xpZGF0ZScgfSBhcyBhbnksXG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICBjb25zb2xpZGF0ZUlkOiAnYWJjMTIzJyxcbiAgICAgICAgICB0eEhleCxcbiAgICAgICAgICB0eEluZm86IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzB4YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYScsIGFtb3VudDogJzAnIH1dIH0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2ZvcndhcmRlciBhZGRyZXNzIG1pc21hdGNoLyk7XG4gIH0pO1xuXG4gIC8vIFRTUyBNUEN2MiBzaWduaW5nIHBhdGgg4oCUIHJlc29sdmVFZmZlY3RpdmVUeFBhcmFtcyBzZXRzIHR5cGUgZnJvbSBpbnRlbnQuaW50ZW50VHlwZSAoJ2NvbnNvbGlkYXRlVG9rZW4nKSxcbiAgLy8gYW5kIHR4UHJlYnVpbGQgaGFzIG9ubHkgdHhIZXggKG5vIGNvbnNvbGlkYXRlSWQsIG5vIHJlY2lwaWVudHMpLiBUaGlzIHdhcyB0aGUgYnJva2VuIHBhdGggYmVmb3JlXG4gIC8vIGlzQ29uc29saWRhdGlvblRyYW5zYWN0aW9uIHdhcyB1cGRhdGVkIHRvIHJlY29nbmlzZSAnY29uc29saWRhdGVUb2tlbicuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgZGlyZWN0IGNhbGxGcm9tUGFyZW50IGNvbnNvbGlkYXRpb24gdHggd2hlbiB0eXBlIGlzIGNvbnNvbGlkYXRlVG9rZW4gKFRTUyBNUEN2MiBzaWduaW5nIHBhdGgpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RDb25zb2xpZGF0aW9uVHhIZXgoKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IENPTlNPTElEQVRJT05fQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgIHR5cGU6ICdjb25zb2xpZGF0ZVRva2VuJyxcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogQ09OU09MSURBVElPTl9GT1JXQVJERVIsIGFtb3VudDogJzAnIH1dLFxuICAgICAgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgd2FsbGV0LFxuICAgIH0pO1xuICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IGNhbGxGcm9tUGFyZW50IGNvbnNvbGlkYXRpb24gd2l0aCB0eXBlIGNvbnNvbGlkYXRlVG9rZW4gd2hlbiBwYXJlbnQgYWRkcmVzcyBkb2VzIG5vdCBtYXRjaCB3YWxsZXQgYmFzZSBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RDb25zb2xpZGF0aW9uVHhIZXgoKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6ICcweGFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEnIH0sXG4gICAgfSk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgIHR5cGU6ICdjb25zb2xpZGF0ZVRva2VuJyxcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBDT05TT0xJREFUSU9OX0ZPUldBUkRFUiwgYW1vdW50OiAnMCcgfV0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3BhcmVudCBhZGRyZXNzIG1pc21hdGNoLyk7XG4gIH0pO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gcmVjb3ZlcigpIOKAkyBFUkMtNzk4NCBjb25maWRlbnRpYWwgdG9rZW4gcmVjb3Zlcnlcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5kZXNjcmliZSgnRXJjNzk4NFRva2VuIOKAkyByZWNvdmVyKCknLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgY29pbjogRXJjNzk4NFRva2VuO1xuICBsZXQgZXhwbG9yZXJTdHViOiBzaW5vbi5TaW5vblN0dWI7XG5cbiAgY29uc3QgV0FMTEVUX0NPTlRSQUNUID0gJzB4OGY5NzdlOTEyZWY1MDA1NDhhMGMzYmU2ZGRkZTk4OTlmMTE5OWI4MSc7XG4gIGNvbnN0IFJFQ09WRVJZX0RFU1QgPSAnMHgxOTY0NTAzMmM3ZjE1MzMzOTVkNDRhNjI5NDYyZTc1MTA4NGQzZTRjJztcbiAgY29uc3QgSEFORExFID0gJzB4JyArICdhYicucmVwZWF0KDMyKTtcbiAgY29uc3QgWkVST19IQU5ETEUgPSAnMHgnICsgJzAwJy5yZXBlYXQoMzIpO1xuXG4gIGNvbnN0IFVTRVJfS0VZID0gdGVzdERhdGEuUFJJVkFURV9LRVk7XG4gIGNvbnN0IEJBQ0tVUF9LRVkgPSB0ZXN0RGF0YS5QUklWQVRFX0tFWTtcbiAgY29uc3QgV0FMTEVUX1BBU1NQSFJBU0UgPSAndGVzdCB3YWxsZXQgcGFzc3BocmFzZSc7XG5cbiAgLy8gRW5jcnlwdGVkIGtleXMgZm9yIHRlc3QgKGVuY3J5cHQgd2l0aCB0aGUgdGVzdCBwYXNzcGhyYXNlKVxuICBsZXQgZW5jcnlwdGVkVXNlcktleTogc3RyaW5nO1xuICBsZXQgZW5jcnlwdGVkQmFja3VwS2V5OiBzdHJpbmc7XG5cbiAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICByZWdpc3RlcihiaXRnbyk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoOmN0ZXN0MScpIGFzIEVyYzc5ODRUb2tlbjtcblxuICAgIGVuY3J5cHRlZFVzZXJLZXkgPSBhd2FpdCBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6IFVTRVJfS0VZLCBwYXNzd29yZDogV0FMTEVUX1BBU1NQSFJBU0UgfSk7XG4gICAgZW5jcnlwdGVkQmFja3VwS2V5ID0gYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiBCQUNLVVBfS0VZLCBwYXNzd29yZDogV0FMTEVUX1BBU1NQSFJBU0UgfSk7XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIGV4cGxvcmVyU3R1YiA9IHNpbm9uLnN0dWIoY29pbiwgJ3JlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnknIGFzIGFueSk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2lub24ucmVzdG9yZSgpO1xuICB9KTtcblxuICBmdW5jdGlvbiBtb2NrRXhwbG9yZXJGb3JSZWNvdmVyeShoYW5kbGU6IHN0cmluZyA9IEhBTkRMRSkge1xuICAgIGV4cGxvcmVyU3R1Yi5jYWxsc0Zha2UoYXN5bmMgKHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSA9PiB7XG4gICAgICBpZiAocXVlcnkuYWN0aW9uID09PSAndHhsaXN0Jykge1xuICAgICAgICAvLyBnZXRBZGRyZXNzTm9uY2U6IHJldHVybiBlbXB0eSB0eCBsaXN0IChub25jZSA9IDApXG4gICAgICAgIHJldHVybiB7IHJlc3VsdDogW10gfTtcbiAgICAgIH1cbiAgICAgIGlmIChxdWVyeS5hY3Rpb24gPT09ICdiYWxhbmNlJykge1xuICAgICAgICAvLyBxdWVyeUFkZHJlc3NCYWxhbmNlOiByZXR1cm4gZW5vdWdoIEVUSCBmb3IgZ2FzXG4gICAgICAgIHJldHVybiB7IHJlc3VsdDogJzEwMDAwMDAwMDAwMDAwMDAwMCcgfTsgLy8gMC4xIEVUSFxuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ2V0aF9jYWxsJyAmJiBxdWVyeS5kYXRhPy5zdGFydHNXaXRoKCdhMGI3OTY3YicpKSB7XG4gICAgICAgIC8vIHF1ZXJ5U2VxdWVuY2VJZDogZ2V0TmV4dFNlcXVlbmNlSWRcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0OiAnMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA1JyB9O1xuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ2V0aF9jYWxsJyAmJiBxdWVyeS50byA9PT0gQ1RFU1QxX1RPS0VOX0FERFJFU1MpIHtcbiAgICAgICAgLy8gcXVlcnlDb25maWRlbnRpYWxCYWxhbmNlXG4gICAgICAgIHJldHVybiB7IHJlc3VsdDogaGFuZGxlIH07XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgZXhwbG9yZXIgcXVlcnk6ICR7SlNPTi5zdHJpbmdpZnkocXVlcnkpfWApO1xuICAgIH0pO1xuICB9XG5cbiAgaXQoJ3Nob3VsZCBidWlsZCBhIGZ1bGwgYmFsYW5jZSBzd2VlcCByZWNvdmVyeSB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBtb2NrRXhwbG9yZXJGb3JSZWNvdmVyeSgpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi5yZWNvdmVyKHtcbiAgICAgIHVzZXJLZXk6IGVuY3J5cHRlZFVzZXJLZXksXG4gICAgICBiYWNrdXBLZXk6IGVuY3J5cHRlZEJhY2t1cEtleSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFdBTExFVF9QQVNTUEhSQVNFLFxuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBSRUNPVkVSWV9ERVNULFxuICAgIH0pO1xuXG4gICAgc2hvdWxkLmV4aXN0KHJlc3VsdCk7XG4gICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdpZCcpO1xuICAgIHJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHgnKTtcbiAgICAocmVzdWx0IGFzIGFueSkudHguc2hvdWxkLmJlLmEuU3RyaW5nKCk7XG4gICAgKHJlc3VsdCBhcyBhbnkpLnR4Lmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oMCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdXNlIHVzZXItcHJvdmlkZWQgZW5jcnlwdGVkSGFuZGxlIGFuZCBza2lwIGF1dG8tcXVlcnknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdXNlckhhbmRsZSA9ICcweCcgKyAnZmYnLnJlcGVhdCgzMik7XG5cbiAgICBleHBsb3JlclN0dWIuY2FsbHNGYWtlKGFzeW5jIChxdWVyeTogUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPT4ge1xuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ3R4bGlzdCcpIHtcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0OiBbXSB9O1xuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ2JhbGFuY2UnKSB7XG4gICAgICAgIHJldHVybiB7IHJlc3VsdDogJzEwMDAwMDAwMDAwMDAwMDAwMCcgfTtcbiAgICAgIH1cbiAgICAgIGlmIChxdWVyeS5hY3Rpb24gPT09ICdldGhfY2FsbCcgJiYgcXVlcnkuZGF0YT8uc3RhcnRzV2l0aCgnYTBiNzk2N2InKSkge1xuICAgICAgICByZXR1cm4geyByZXN1bHQ6ICcweDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDUnIH07XG4gICAgICB9XG4gICAgICBpZiAocXVlcnkuYWN0aW9uID09PSAnZXRoX2NhbGwnICYmIHF1ZXJ5LnRvID09PSBDVEVTVDFfVE9LRU5fQUREUkVTUykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Nob3VsZCBub3QgcXVlcnkgY29uZmlkZW50aWFsQmFsYW5jZU9mIHdoZW4gaGFuZGxlIGlzIHByb3ZpZGVkJyk7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgZXhwbG9yZXIgcXVlcnk6ICR7SlNPTi5zdHJpbmdpZnkocXVlcnkpfWApO1xuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi5yZWNvdmVyKHtcbiAgICAgIHVzZXJLZXk6IGVuY3J5cHRlZFVzZXJLZXksXG4gICAgICBiYWNrdXBLZXk6IGVuY3J5cHRlZEJhY2t1cEtleSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFdBTExFVF9QQVNTUEhSQVNFLFxuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBSRUNPVkVSWV9ERVNULFxuICAgICAgZW5jcnlwdGVkSGFuZGxlOiB1c2VySGFuZGxlLFxuICAgIH0pO1xuXG4gICAgc2hvdWxkLmV4aXN0KHJlc3VsdCk7XG4gICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHN0aWxsIGJ1aWxkIGEgcmVjb3ZlcnkgdHggZXZlbiB3aXRoIGEgemVyby12YWx1ZSBoYW5kbGUgKGVuY3J5cHRlZCBoYW5kbGVzIGFyZSBhbHdheXMgbm9uLXplcm8pJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIG1vY2tFeHBsb3JlckZvclJlY292ZXJ5KFpFUk9fSEFORExFKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4ucmVjb3Zlcih7XG4gICAgICB1c2VyS2V5OiBlbmNyeXB0ZWRVc2VyS2V5LFxuICAgICAgYmFja3VwS2V5OiBlbmNyeXB0ZWRCYWNrdXBLZXksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlOiBXQUxMRVRfUEFTU1BIUkFTRSxcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogUkVDT1ZFUllfREVTVCxcbiAgICB9KTtcblxuICAgIHNob3VsZC5leGlzdChyZXN1bHQpO1xuICAgIHJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndHgnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gdW5zaWduZWQgc3dlZXAgZm9ybWF0IHdoZW4gaXNVbnNpZ25lZFN3ZWVwIGlzIHRydWUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgbW9ja0V4cGxvcmVyRm9yUmVjb3ZlcnkoKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4ucmVjb3Zlcih7XG4gICAgICB1c2VyS2V5OiB0ZXN0RGF0YS5QVUJMSUNfS0VZLFxuICAgICAgYmFja3VwS2V5OiB0ZXN0RGF0YS5QVUJMSUNfS0VZLFxuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBSRUNPVkVSWV9ERVNULFxuICAgICAgaXNVbnNpZ25lZFN3ZWVwOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgc2hvdWxkLmV4aXN0KHJlc3VsdCk7XG4gICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgIHJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndXNlcktleScpO1xuICAgIHJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYmFja3VwS2V5Jyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIEtSUyByZWNvdmVyeSBmb3JtYXQgd2l0aCBiYWNrdXBLZXkgYW5kIGNvaW4nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgZXhwbG9yZXJTdHViLmNhbGxzRmFrZShhc3luYyAocXVlcnk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pID0+IHtcbiAgICAgIGlmIChxdWVyeS5hY3Rpb24gPT09ICd0eGxpc3QnKSB7XG4gICAgICAgIHJldHVybiB7IHJlc3VsdDogW10gfTtcbiAgICAgIH1cbiAgICAgIGlmIChxdWVyeS5hY3Rpb24gPT09ICdiYWxhbmNlJykge1xuICAgICAgICByZXR1cm4geyByZXN1bHQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAnIH07XG4gICAgICB9XG4gICAgICBpZiAocXVlcnkuYWN0aW9uID09PSAnZXRoX2NhbGwnICYmIHF1ZXJ5LmRhdGE/LnN0YXJ0c1dpdGgoJ2EwYjc5NjdiJykpIHtcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0OiAnMHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA1JyB9O1xuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ2V0aF9jYWxsJyAmJiBxdWVyeS50byA9PT0gQ1RFU1QxX1RPS0VOX0FERFJFU1MpIHtcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0OiBIQU5ETEUgfTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCBleHBsb3JlciBxdWVyeTogJHtKU09OLnN0cmluZ2lmeShxdWVyeSl9YCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSAoYXdhaXQgY29pbi5yZWNvdmVyKHtcbiAgICAgIHVzZXJLZXk6IGVuY3J5cHRlZFVzZXJLZXksXG4gICAgICBiYWNrdXBLZXk6IHRlc3REYXRhLlBVQkxJQ19LRVksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlOiBXQUxMRVRfUEFTU1BIUkFTRSxcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogUkVDT1ZFUllfREVTVCxcbiAgICAgIGtyc1Byb3ZpZGVyOiAna2V5dGVybmFsJyxcbiAgICB9KSkgYXMgYW55O1xuXG4gICAgc2hvdWxkLmV4aXN0KHJlc3VsdCk7XG4gICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuICAgIHJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYmFja3VwS2V5JywgdGVzdERhdGEuUFVCTElDX0tFWSk7XG4gICAgcmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb2luJywgJ2h0ZXRoOmN0ZXN0MScpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gYmFja3VwIGtleSBoYXMgaW5zdWZmaWNpZW50IGdhcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBleHBsb3JlclN0dWIuY2FsbHNGYWtlKGFzeW5jIChxdWVyeTogUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPT4ge1xuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ3R4bGlzdCcpIHtcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0OiBbXSB9O1xuICAgICAgfVxuICAgICAgaWYgKHF1ZXJ5LmFjdGlvbiA9PT0gJ2JhbGFuY2UnKSB7XG4gICAgICAgIC8vIFZlcnkgbG93IGJhbGFuY2UsIG5vdCBlbm91Z2ggZm9yIDEyTSBnYXNcbiAgICAgICAgcmV0dXJuIHsgcmVzdWx0OiAnMTAwJyB9O1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIGV4cGxvcmVyIHF1ZXJ5OiAke0pTT04uc3RyaW5naWZ5KHF1ZXJ5KX1gKTtcbiAgICB9KTtcblxuICAgIGF3YWl0IGNvaW5cbiAgICAgIC5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogZW5jcnlwdGVkVXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBlbmNyeXB0ZWRCYWNrdXBLZXksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFdBTExFVF9QQVNTUEhSQVNFLFxuICAgICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IFdBTExFVF9DT05UUkFDVCxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogUkVDT1ZFUllfREVTVCxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvaGFzIGJhbGFuY2UuKkd3ZWkvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHVzZXJLZXkgaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCBjb2luXG4gICAgICAucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IHVuZGVmaW5lZCBhcyBhbnksXG4gICAgICAgIGJhY2t1cEtleTogZW5jcnlwdGVkQmFja3VwS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBXQUxMRVRfUEFTU1BIUkFTRSxcbiAgICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBXQUxMRVRfQ09OVFJBQ1QsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IFJFQ09WRVJZX0RFU1QsXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL21pc3NpbmcgdXNlcktleS8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IHdoZW4gd2FsbGV0Q29udHJhY3RBZGRyZXNzIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgY29pblxuICAgICAgLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBlbmNyeXB0ZWRVc2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IGVuY3J5cHRlZEJhY2t1cEtleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogV0FMTEVUX1BBU1NQSFJBU0UsXG4gICAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogJ25vdC1hbi1hZGRyZXNzJyxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogUkVDT1ZFUllfREVTVCxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvaW52YWxpZCB3YWxsZXRDb250cmFjdEFkZHJlc3MvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBwcm9kdWNlIHR4IHdpdGggaW5uZXIgY2FsbGRhdGEgbWF0Y2hpbmcgY29uZmlkZW50aWFsVHJhbnNmZXIgc2VsZWN0b3IgMHg1YmViZWQ3ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBtb2NrRXhwbG9yZXJGb3JSZWNvdmVyeSgpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gKGF3YWl0IGNvaW4ucmVjb3Zlcih7XG4gICAgICB1c2VyS2V5OiBlbmNyeXB0ZWRVc2VyS2V5LFxuICAgICAgYmFja3VwS2V5OiBlbmNyeXB0ZWRCYWNrdXBLZXksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlOiBXQUxMRVRfUEFTU1BIUkFTRSxcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogV0FMTEVUX0NPTlRSQUNULFxuICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogUkVDT1ZFUllfREVTVCxcbiAgICB9KSkgYXMgYW55O1xuXG4gICAgc2hvdWxkLmV4aXN0KHJlc3VsdC50eCk7XG4gICAgLy8gVGhlIHNlcmlhbGl6ZWQgdHggY29udGFpbnMgdGhlIHNlbmRNdWx0aVNpZyBjYWxsZGF0YSB3aGljaCB3cmFwcyBjb25maWRlbnRpYWxUcmFuc2Zlci5cbiAgICAvLyBUaGUgY29uZmlkZW50aWFsVHJhbnNmZXIgc2VsZWN0b3IgKDViZWJlZDdlKSBtdXN0IGFwcGVhciBzb21ld2hlcmUgaW4gdGhlIHNlcmlhbGl6ZWQgdHguXG4gICAgY29uc3Qgc2VsZWN0b3JOb1ByZWZpeCA9IGNvbmZpZGVudGlhbFRyYW5zZmVyTm9Qcm9vZk1ldGhvZElkLnNsaWNlKDIpO1xuICAgIHJlc3VsdC50eC5zaG91bGQuY29udGFpbkVxbChzZWxlY3Rvck5vUHJlZml4KTtcbiAgfSk7XG59KTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBxdWVyeUNvbmZpZGVudGlhbEJhbGFuY2UoKSB0ZXN0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmRlc2NyaWJlKCdFcmM3OTg0VG9rZW4g4oCTIHF1ZXJ5Q29uZmlkZW50aWFsQmFsYW5jZSgpJywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IEVyYzc5ODRUb2tlbjtcbiAgbGV0IGV4cGxvcmVyU3R1Yjogc2lub24uU2lub25TdHViO1xuXG4gIGNvbnN0IFdBTExFVF9BRERSRVNTID0gJzB4OGY5NzdlOTEyZWY1MDA1NDhhMGMzYmU2ZGRkZTk4OTlmMTE5OWI4MSc7XG4gIGNvbnN0IEhBTkRMRSA9ICcweCcgKyAnYWInLnJlcGVhdCgzMik7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICByZWdpc3RlcihiaXRnbyk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoOmN0ZXN0MScpIGFzIEVyYzc5ODRUb2tlbjtcbiAgfSk7XG5cbiAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgZXhwbG9yZXJTdHViID0gc2lub24uc3R1Yihjb2luLCAncmVjb3ZlcnlCbG9ja2NoYWluRXhwbG9yZXJRdWVyeScgYXMgYW55KTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGEgdmFsaWQgYnl0ZXMzMiBoYW5kbGUgZnJvbSBldGhfY2FsbCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBleHBsb3JlclN0dWIucmVzb2x2ZXMoeyByZXN1bHQ6IEhBTkRMRSB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4ucXVlcnlDb25maWRlbnRpYWxCYWxhbmNlKFdBTExFVF9BRERSRVNTKTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKEhBTkRMRSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IHRoZSBldGhfY2FsbCBpcyBtYWRlIHRvIHRoZSBjb3JyZWN0IHRva2VuIGNvbnRyYWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGV4cGxvcmVyU3R1Yi5yZXNvbHZlcyh7IHJlc3VsdDogSEFORExFIH0pO1xuXG4gICAgYXdhaXQgY29pbi5xdWVyeUNvbmZpZGVudGlhbEJhbGFuY2UoV0FMTEVUX0FERFJFU1MpO1xuXG4gICAgZXhwbG9yZXJTdHViLmNhbGxlZE9uY2Uuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBjb25zdCBjYWxsQXJncyA9IGV4cGxvcmVyU3R1Yi5maXJzdENhbGwuYXJnc1swXTtcbiAgICBjYWxsQXJncy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWN0aW9uJywgJ2V0aF9jYWxsJyk7XG4gICAgY2FsbEFyZ3Muc2hvdWxkLmhhdmUucHJvcGVydHkoJ3RvJywgQ1RFU1QxX1RPS0VOX0FERFJFU1MpO1xuICAgIGNhbGxBcmdzLnNob3VsZC5oYXZlLnByb3BlcnR5KCdtb2R1bGUnLCAncHJveHknKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGV4cGxvcmVyIHJldHVybnMgbm8gcmVzdWx0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGV4cGxvcmVyU3R1Yi5yZXNvbHZlcyh7IHJlc3VsdDogbnVsbCB9KTtcblxuICAgIGF3YWl0IGNvaW4ucXVlcnlDb25maWRlbnRpYWxCYWxhbmNlKFdBTExFVF9BRERSRVNTKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9Db3VsZCBub3Qgb2J0YWluIGNvbmZpZGVudGlhbCBiYWxhbmNlLyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByZXNwb25zZSBmb3JtYXQgaXMgdW5leHBlY3RlZCAobm90IDY2IGNoYXJzKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBleHBsb3JlclN0dWIucmVzb2x2ZXMoeyByZXN1bHQ6ICcweGFiY2QnIH0pO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnF1ZXJ5Q29uZmlkZW50aWFsQmFsYW5jZShXQUxMRVRfQUREUkVTUylcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9VbmV4cGVjdGVkIGNvbmZpZGVudGlhbEJhbGFuY2VPZiByZXNwb25zZSBmb3JtYXQvKTtcbiAgfSk7XG59KTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyB2ZXJpZnlUcmFuc2FjdGlvbiDigJMgV3JhcEVSQzc5ODQgKHNoaWVsZClcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5jb25zdCBXUkFQX0JBU0VfQUREUkVTUyA9ICcweDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEnO1xuY29uc3QgV1JBUF9BTU9VTlQgPSAnMTAwMDAwMCc7XG5jb25zdCBXUkFQX1JBVEUgPSAnMSc7XG5cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkRGlyZWN0V3JhcFR4SGV4KHRva2VuQWRkcmVzczogc3RyaW5nLCByZWNpcGllbnQ6IHN0cmluZywgYW1vdW50OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAwMDAwMDAnLCBnYXNMaW1pdDogJzIwMDAwMCcgfSk7XG4gIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuV3JhcEVSQzc5ODQpO1xuICB0eEJ1aWxkZXIuY29udHJhY3QodG9rZW5BZGRyZXNzKTtcbiAgdHhCdWlsZGVyLndyYXBSZWNpcGllbnQocmVjaXBpZW50KTtcbiAgdHhCdWlsZGVyLndyYXBBbW91bnQoYW1vdW50KTtcbiAgdHhCdWlsZGVyLndyYXBSYXRlKFdSQVBfUkFURSk7XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZE11bHRpc2lnV3JhcFR4SGV4KHRva2VuQWRkcmVzczogc3RyaW5nLCByZWNpcGllbnQ6IHN0cmluZywgYW1vdW50OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB3cmFwQ2FsbGRhdGEgPSBidWlsZFdyYXBDYWxsZGF0YShyZWNpcGllbnQsIGFtb3VudCwgV1JBUF9SQVRFKTtcbiAgY29uc3Qgc2VuZERhdGEgPSBzZW5kTXVsdGlTaWdEYXRhKFxuICAgIHRva2VuQWRkcmVzcyxcbiAgICAnMCcsXG4gICAgd3JhcENhbGxkYXRhLFxuICAgIE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApICsgMzYwMCxcbiAgICAxNCxcbiAgICBEVU1NWV9NVUxUSVNJR19TSUdOQVRVUkVcbiAgKTtcblxuICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAwMDAwMDAnLCBnYXNMaW1pdDogJzIwMDAwMCcgfSk7XG4gIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgdHhCdWlsZGVyLmNvbnRyYWN0KE1VTFRJU0lHX1dBTExFVF9DT05UUkFDVCk7XG4gIHR4QnVpbGRlci5kYXRhKHNlbmREYXRhKTtcbiAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgcmV0dXJuIHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG59XG5cbmRlc2NyaWJlKCd2ZXJpZnlUcmFuc2FjdGlvbiDigJMgV3JhcEVSQzc5ODQnLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgY29pbjogRXJjNzk4NFRva2VuO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgcmVnaXN0ZXIoYml0Z28pO1xuICAgIGNvaW4gPSBiaXRnby5jb2luKCdodGV0aDpjdGVzdDEnKSBhcyBFcmM3OTg0VG9rZW47XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgZGlyZWN0IHdyYXAgdHggKFRTUyBzaGFwZSknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERpcmVjdFdyYXBUeEhleChDVEVTVDFfVE9LRU5fQUREUkVTUywgV1JBUF9CQVNFX0FERFJFU1MsIFdSQVBfQU1PVU5UKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IFdSQVBfQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgIHR5cGU6ICd3cmFwJyxcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogV1JBUF9CQVNFX0FERFJFU1MsIGFtb3VudDogV1JBUF9BTU9VTlQgfV0sXG4gICAgICB9IGFzIGFueSxcbiAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICB3YWxsZXQsXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBtdWx0aXNpZyB3cmFwIHR4IChzZW5kTXVsdGlTaWcg4oaSIHdyYXApJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRNdWx0aXNpZ1dyYXBUeEhleChDVEVTVDFfVE9LRU5fQUREUkVTUywgV1JBUF9CQVNFX0FERFJFU1MsIFdSQVBfQU1PVU5UKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IFdSQVBfQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgIHR5cGU6ICd3cmFwJyxcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogV1JBUF9CQVNFX0FERFJFU1MsIGFtb3VudDogV1JBUF9BTU9VTlQgfV0sXG4gICAgICB9IGFzIGFueSxcbiAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICB3YWxsZXQsXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3Qgd3JhcCB3aGVuIHJlY2lwaWVudCBkb2VzIG5vdCBtYXRjaCB3YWxsZXQgYmFzZSBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RXcmFwVHhIZXgoQ1RFU1QxX1RPS0VOX0FERFJFU1MsIFdSQVBfQkFTRV9BRERSRVNTLCBXUkFQX0FNT1VOVCk7XG4gICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzOiAnMHhhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhJyB9LFxuICAgIH0pO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgdHlwZTogJ3dyYXAnLCByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBXUkFQX0JBU0VfQUREUkVTUywgYW1vdW50OiBXUkFQX0FNT1VOVCB9XSB9IGFzIGFueSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC93cmFwIHJlY2lwaWVudCBtdXN0IGVxdWFsIHdhbGxldCBiYXNlIGFkZHJlc3MvKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3Qgd3JhcCB3aGVuIGFtb3VudCBtaXNtYXRjaGVzIHJlY2lwaWVudHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERpcmVjdFdyYXBUeEhleChDVEVTVDFfVE9LRU5fQUREUkVTUywgV1JBUF9CQVNFX0FERFJFU1MsIFdSQVBfQU1PVU5UKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IFdSQVBfQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyB0eXBlOiAnd3JhcCcsIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFdSQVBfQkFTRV9BRERSRVNTLCBhbW91bnQ6ICc5OTknIH1dIH0gYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2Ftb3VudCBtaXNtYXRjaC8pO1xuICB9KTtcbn0pO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIHZlcmlmeVRyYW5zYWN0aW9uIOKAkyBVbndyYXBFUkM3OTg0ICh1bnNoaWVsZCBwaGFzZS0xKVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmNvbnN0IFVOV1JBUF9CQVNFX0FERFJFU1MgPSAnMHgxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExJztcbmNvbnN0IFVOV1JBUF9FTkNSWVBURURfQU1PVU5UID0gJzB4JyArICdhYicucmVwZWF0KDMyKTtcbmNvbnN0IFVOV1JBUF9JTlBVVF9QUk9PRiA9ICcweCcgKyAnY2QnLnJlcGVhdCg2NCk7XG5cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkRGlyZWN0VW53cmFwVHhIZXgoXG4gIHRva2VuQWRkcmVzczogc3RyaW5nLFxuICBmcm9tOiBzdHJpbmcsXG4gIHRvOiBzdHJpbmcsXG4gIGVuY3J5cHRlZEFtb3VudDogc3RyaW5nLFxuICBpbnB1dFByb29mOiBzdHJpbmdcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMjAwMDAwJyB9KTtcbiAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5VbndyYXBFUkM3OTg0KTtcbiAgdHhCdWlsZGVyLmNvbnRyYWN0KHRva2VuQWRkcmVzcyk7XG4gIHR4QnVpbGRlci51bndyYXBGcm9tKGZyb20pO1xuICB0eEJ1aWxkZXIudW53cmFwVG8odG8pO1xuICB0eEJ1aWxkZXIudW53cmFwRW5jcnlwdGVkQW1vdW50KGVuY3J5cHRlZEFtb3VudCk7XG4gIHR4QnVpbGRlci51bndyYXBJbnB1dFByb29mKGlucHV0UHJvb2YpO1xuICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICByZXR1cm4gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRNdWx0aXNpZ1Vud3JhcFR4SGV4KFxuICB0b2tlbkFkZHJlc3M6IHN0cmluZyxcbiAgZnJvbTogc3RyaW5nLFxuICB0bzogc3RyaW5nLFxuICBlbmNyeXB0ZWRBbW91bnQ6IHN0cmluZyxcbiAgaW5wdXRQcm9vZjogc3RyaW5nXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB1bndyYXBDYWxsZGF0YSA9IGJ1aWxkVW53cmFwQ2FsbGRhdGEoZnJvbSwgdG8sIGVuY3J5cHRlZEFtb3VudCwgaW5wdXRQcm9vZik7XG4gIGNvbnN0IHNlbmREYXRhID0gc2VuZE11bHRpU2lnRGF0YShcbiAgICB0b2tlbkFkZHJlc3MsXG4gICAgJzAnLFxuICAgIHVud3JhcENhbGxkYXRhLFxuICAgIE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApICsgMzYwMCxcbiAgICAxNCxcbiAgICBEVU1NWV9NVUxUSVNJR19TSUdOQVRVUkVcbiAgKTtcblxuICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAwMDAwMDAnLCBnYXNMaW1pdDogJzIwMDAwMCcgfSk7XG4gIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgdHhCdWlsZGVyLmNvbnRyYWN0KE1VTFRJU0lHX1dBTExFVF9DT05UUkFDVCk7XG4gIHR4QnVpbGRlci5kYXRhKHNlbmREYXRhKTtcbiAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgcmV0dXJuIHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG59XG5cbmRlc2NyaWJlKCd2ZXJpZnlUcmFuc2FjdGlvbiDigJMgVW53cmFwRVJDNzk4NCcsIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBjb2luOiBFcmM3OTg0VG9rZW47XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICByZWdpc3RlcihiaXRnbyk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ2h0ZXRoOmN0ZXN0MScpIGFzIEVyYzc5ODRUb2tlbjtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBkaXJlY3QgdW53cmFwIHR4IChUU1Mgc2hhcGUpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RVbndyYXBUeEhleChcbiAgICAgIENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgVU5XUkFQX0JBU0VfQUREUkVTUyxcbiAgICAgIFVOV1JBUF9CQVNFX0FERFJFU1MsXG4gICAgICBVTldSQVBfRU5DUllQVEVEX0FNT1VOVCxcbiAgICAgIFVOV1JBUF9JTlBVVF9QUk9PRlxuICAgICk7XG4gICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzOiBVTldSQVBfQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICd1bndyYXAnIH0gYXMgYW55LFxuICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgIHdhbGxldCxcbiAgICB9KTtcbiAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIG11bHRpc2lnIHVud3JhcCB0eCAoc2VuZE11bHRpU2lnIOKGkiB1bndyYXApJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRNdWx0aXNpZ1Vud3JhcFR4SGV4KFxuICAgICAgQ1RFU1QxX1RPS0VOX0FERFJFU1MsXG4gICAgICBVTldSQVBfQkFTRV9BRERSRVNTLFxuICAgICAgVU5XUkFQX0JBU0VfQUREUkVTUyxcbiAgICAgIFVOV1JBUF9FTkNSWVBURURfQU1PVU5ULFxuICAgICAgVU5XUkFQX0lOUFVUX1BST09GXG4gICAgKTtcbiAgICBjb25zdCB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBjb2luLCB7XG4gICAgICBjb2luU3BlY2lmaWM6IHsgYmFzZUFkZHJlc3M6IFVOV1JBUF9CQVNFX0FERFJFU1MgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHsgdHlwZTogJ3Vud3JhcCcgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgd2FsbGV0LFxuICAgIH0pO1xuICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IHVud3JhcCB3aGVuIGZyb20gZG9lcyBub3QgbWF0Y2ggd2FsbGV0IGJhc2UgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRGlyZWN0VW53cmFwVHhIZXgoXG4gICAgICBDVEVTVDFfVE9LRU5fQUREUkVTUyxcbiAgICAgIFVOV1JBUF9CQVNFX0FERFJFU1MsXG4gICAgICBVTldSQVBfQkFTRV9BRERSRVNTLFxuICAgICAgVU5XUkFQX0VOQ1JZUFRFRF9BTU9VTlQsXG4gICAgICBVTldSQVBfSU5QVVRfUFJPT0ZcbiAgICApO1xuICAgIGNvbnN0IHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGNvaW4sIHtcbiAgICAgIGNvaW5TcGVjaWZpYzogeyBiYXNlQWRkcmVzczogJzB4YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYScgfSxcbiAgICB9KTtcblxuICAgIGF3YWl0IGNvaW5cbiAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UGFyYW1zOiB7IHR5cGU6ICd1bndyYXAnIH0gYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQsXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3Vud3JhcCBmcm9tIG11c3QgZXF1YWwgd2FsbGV0IGJhc2UgYWRkcmVzcy8pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCB1bndyYXAgd2hlbiB0byBkaWZmZXJzIGZyb20gZnJvbSAobm9uLXNlbGYtZGlyZWN0ZWQpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IG90aGVyID0gJzB4MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMic7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERpcmVjdFVud3JhcFR4SGV4KFxuICAgICAgQ1RFU1QxX1RPS0VOX0FERFJFU1MsXG4gICAgICBVTldSQVBfQkFTRV9BRERSRVNTLFxuICAgICAgb3RoZXIsXG4gICAgICBVTldSQVBfRU5DUllQVEVEX0FNT1VOVCxcbiAgICAgIFVOV1JBUF9JTlBVVF9QUk9PRlxuICAgICk7XG4gICAgY29uc3Qgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgY29pbiwge1xuICAgICAgY29pblNwZWNpZmljOiB7IGJhc2VBZGRyZXNzOiBVTldSQVBfQkFTRV9BRERSRVNTIH0sXG4gICAgfSk7XG5cbiAgICBhd2FpdCBjb2luXG4gICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczogeyB0eXBlOiAndW53cmFwJyB9IGFzIGFueSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0LFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC91bndyYXAgdG8gbXVzdCBlcXVhbCB3YWxsZXQgYmFzZSBhZGRyZXNzLyk7XG4gIH0pO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gdmVyaWZ5VHJhbnNhY3Rpb24g4oCTIEZpbmFsaXplVW53cmFwRVJDNzk4NCAodW5zaGllbGQgcGhhc2UtMilcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5jb25zdCBGSU5BTElaRV9SRVFVRVNUX0lEID0gJzB4JyArICcxMScucmVwZWF0KDMyKTtcbmNvbnN0IEZJTkFMSVpFX0NMRUFSVEVYVF9BTU9VTlQgPSAnMTAwMDAwMCc7XG5jb25zdCBGSU5BTElaRV9ERUNSWVBUSU9OX1BST09GID0gJzB4JyArICdlZScucmVwZWF0KDY0KTtcblxuYXN5bmMgZnVuY3Rpb24gYnVpbGREaXJlY3RGaW5hbGl6ZVVud3JhcFR4SGV4KFxuICB0b2tlbkFkZHJlc3M6IHN0cmluZyxcbiAgcmVxdWVzdElkOiBzdHJpbmcsXG4gIGNsZWFydGV4dEFtb3VudDogc3RyaW5nLFxuICBkZWNyeXB0aW9uUHJvb2Y6IHN0cmluZ1xuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gIHR4QnVpbGRlci5mZWUoeyBmZWU6ICcxMDAwMDAwMDAwJywgZ2FzTGltaXQ6ICcyMDAwMDAnIH0pO1xuICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkZpbmFsaXplVW53cmFwRVJDNzk4NCk7XG4gIHR4QnVpbGRlci5jb250cmFjdCh0b2tlbkFkZHJlc3MpO1xuICB0eEJ1aWxkZXIuZmluYWxpemVVbndyYXBSZXF1ZXN0SWQocmVxdWVzdElkKTtcbiAgdHhCdWlsZGVyLmZpbmFsaXplVW53cmFwQ2xlYXJ0ZXh0QW1vdW50KGNsZWFydGV4dEFtb3VudCk7XG4gIHR4QnVpbGRlci5maW5hbGl6ZVVud3JhcERlY3J5cHRpb25Qcm9vZihkZWNyeXB0aW9uUHJvb2YpO1xuICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICByZXR1cm4gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYnVpbGRNdWx0aXNpZ0ZpbmFsaXplVW53cmFwVHhIZXgoXG4gIHRva2VuQWRkcmVzczogc3RyaW5nLFxuICByZXF1ZXN0SWQ6IHN0cmluZyxcbiAgY2xlYXJ0ZXh0QW1vdW50OiBzdHJpbmcsXG4gIGRlY3J5cHRpb25Qcm9vZjogc3RyaW5nXG4pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBmaW5hbGl6ZUNhbGxkYXRhID0gYnVpbGRGaW5hbGl6ZVVud3JhcENhbGxkYXRhKHJlcXVlc3RJZCwgY2xlYXJ0ZXh0QW1vdW50LCBkZWNyeXB0aW9uUHJvb2YpO1xuICBjb25zdCBzZW5kRGF0YSA9IHNlbmRNdWx0aVNpZ0RhdGEoXG4gICAgdG9rZW5BZGRyZXNzLFxuICAgICcwJyxcbiAgICBmaW5hbGl6ZUNhbGxkYXRhLFxuICAgIE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApICsgMzYwMCxcbiAgICAxNCxcbiAgICBEVU1NWV9NVUxUSVNJR19TSUdOQVRVUkVcbiAgKTtcblxuICBjb25zdCB0eEJ1aWxkZXIgPSBnZXRCdWlsZGVyKCdodGV0aCcpIGFzIFRyYW5zYWN0aW9uQnVpbGRlcjtcbiAgdHhCdWlsZGVyLmZlZSh7IGZlZTogJzEwMDAwMDAwMDAnLCBnYXNMaW1pdDogJzIwMDAwMCcgfSk7XG4gIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICB0eEJ1aWxkZXIudHlwZShUcmFuc2FjdGlvblR5cGUuQ29udHJhY3RDYWxsKTtcbiAgdHhCdWlsZGVyLmNvbnRyYWN0KE1VTFRJU0lHX1dBTExFVF9DT05UUkFDVCk7XG4gIHR4QnVpbGRlci5kYXRhKHNlbmREYXRhKTtcbiAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgcmV0dXJuIHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG59XG5cbmRlc2NyaWJlKCd2ZXJpZnlUcmFuc2FjdGlvbiDigJMgRmluYWxpemVVbndyYXBFUkM3OTg0JywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IEVyYzc5ODRUb2tlbjtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIHJlZ2lzdGVyKGJpdGdvKTtcbiAgICBjb2luID0gYml0Z28uY29pbignaHRldGg6Y3Rlc3QxJykgYXMgRXJjNzk4NFRva2VuO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIGRpcmVjdCBmaW5hbGl6ZVVud3JhcCB0eCAoVFNTIHNoYXBlKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRGlyZWN0RmluYWxpemVVbndyYXBUeEhleChcbiAgICAgIENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgRklOQUxJWkVfUkVRVUVTVF9JRCxcbiAgICAgIEZJTkFMSVpFX0NMRUFSVEVYVF9BTU9VTlQsXG4gICAgICBGSU5BTElaRV9ERUNSWVBUSU9OX1BST09GXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgdHlwZTogJ2ZpbmFsaXplVW53cmFwJyxcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogVU5XUkFQX0JBU0VfQUREUkVTUywgYW1vdW50OiBGSU5BTElaRV9DTEVBUlRFWFRfQU1PVU5UIH1dLFxuICAgICAgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBtdWx0aXNpZyBmaW5hbGl6ZVVud3JhcCB0eCAoc2VuZE11bHRpU2lnIOKGkiBmaW5hbGl6ZVVud3JhcCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZE11bHRpc2lnRmluYWxpemVVbndyYXBUeEhleChcbiAgICAgIENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgRklOQUxJWkVfUkVRVUVTVF9JRCxcbiAgICAgIEZJTkFMSVpFX0NMRUFSVEVYVF9BTU9VTlQsXG4gICAgICBGSU5BTElaRV9ERUNSWVBUSU9OX1BST09GXG4gICAgKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgdHlwZTogJ2ZpbmFsaXplVW53cmFwJyxcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogVU5XUkFQX0JBU0VfQUREUkVTUywgYW1vdW50OiBGSU5BTElaRV9DTEVBUlRFWFRfQU1PVU5UIH1dLFxuICAgICAgfSBhcyBhbnksXG4gICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgfSk7XG4gICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3QgZmluYWxpemVVbndyYXAgd2hlbiBhbW91bnQgbWlzbWF0Y2hlcyByZWNpcGllbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREaXJlY3RGaW5hbGl6ZVVud3JhcFR4SGV4KFxuICAgICAgQ1RFU1QxX1RPS0VOX0FERFJFU1MsXG4gICAgICBGSU5BTElaRV9SRVFVRVNUX0lELFxuICAgICAgRklOQUxJWkVfQ0xFQVJURVhUX0FNT1VOVCxcbiAgICAgIEZJTkFMSVpFX0RFQ1JZUFRJT05fUFJPT0ZcbiAgICApO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZmluYWxpemVVbndyYXAnLFxuICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IFVOV1JBUF9CQVNFX0FERFJFU1MsIGFtb3VudDogJzk5OScgfV0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvYW1vdW50IG1pc21hdGNoLyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IGZpbmFsaXplVW53cmFwIHdoZW4gd3JhcHBlciBhZGRyZXNzIG1pc21hdGNoZXMgdG9rZW4nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgd3JvbmdXcmFwcGVyID0gJzB4YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSc7XG4gICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERpcmVjdEZpbmFsaXplVW53cmFwVHhIZXgoXG4gICAgICB3cm9uZ1dyYXBwZXIsXG4gICAgICBGSU5BTElaRV9SRVFVRVNUX0lELFxuICAgICAgRklOQUxJWkVfQ0xFQVJURVhUX0FNT1VOVCxcbiAgICAgIEZJTkFMSVpFX0RFQ1JZUFRJT05fUFJPT0ZcbiAgICApO1xuXG4gICAgYXdhaXQgY29pblxuICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHsgdHlwZTogJ2ZpbmFsaXplVW53cmFwJyB9IGFzIGFueSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL3dyYXBwZXIgYWRkcmVzcyBtaXNtYXRjaC8pO1xuICB9KTtcbn0pO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIHNldEdhc0xpbWl0KCkgb3ZlcnJpZGUgdGVzdHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5kZXNjcmliZSgnRXJjNzk4NFRva2VuIOKAkyBzZXRHYXNMaW1pdCgpJywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IEVyYzc5ODRUb2tlbjtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIHJlZ2lzdGVyKGJpdGdvKTtcbiAgICBjb2luID0gYml0Z28uY29pbignaHRldGg6Y3Rlc3QxJykgYXMgRXJjNzk4NFRva2VuO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJldHVybiA4MDAwMDAgYXMgZGVmYXVsdCBnYXMgbGltaXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgZ2FzTGltaXQgPSBjb2luLnNldEdhc0xpbWl0KCk7XG4gICAgZ2FzTGltaXQuc2hvdWxkLmVxdWFsKDgwMDAwMCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgYWNjZXB0IHVzZXItcHJvdmlkZWQgZ2FzIGxpbWl0JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGdhc0xpbWl0ID0gY29pbi5zZXRHYXNMaW1pdCgxMDAwMDAwKTtcbiAgICBnYXNMaW1pdC5zaG91bGQuZXF1YWwoMTAwMDAwMCk7XG4gIH0pO1xufSk7XG4iXX0=