@bitgo-beta/sdk-coin-ada 2.3.14-beta.182 → 2.3.14-beta.1821

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 (113) hide show
  1. package/dist/src/ada.d.ts +15 -13
  2. package/dist/src/ada.d.ts.map +1 -1
  3. package/dist/src/ada.js +124 -42
  4. package/dist/src/adaToken.d.ts +16 -11
  5. package/dist/src/adaToken.d.ts.map +1 -1
  6. package/dist/src/adaToken.js +109 -3
  7. package/dist/src/index.js +6 -2
  8. package/dist/src/lib/index.d.ts +3 -1
  9. package/dist/src/lib/index.d.ts.map +1 -1
  10. package/dist/src/lib/index.js +29 -9
  11. package/dist/src/lib/keyPair.js +29 -16
  12. package/dist/src/lib/messages/cip8/cip8Message.d.ts +25 -0
  13. package/dist/src/lib/messages/cip8/cip8Message.d.ts.map +1 -0
  14. package/dist/src/lib/messages/cip8/cip8Message.js +140 -0
  15. package/dist/src/lib/messages/cip8/cip8MessageBuilder.d.ts +19 -0
  16. package/dist/src/lib/messages/cip8/cip8MessageBuilder.d.ts.map +1 -0
  17. package/dist/src/lib/messages/cip8/cip8MessageBuilder.js +27 -0
  18. package/dist/src/lib/messages/cip8/index.d.ts +4 -0
  19. package/dist/src/lib/messages/cip8/index.d.ts.map +1 -0
  20. package/dist/src/lib/messages/cip8/index.js +20 -0
  21. package/dist/src/lib/messages/cip8/utils.d.ts +24 -0
  22. package/dist/src/lib/messages/cip8/utils.d.ts.map +1 -0
  23. package/dist/src/lib/messages/cip8/utils.js +73 -0
  24. package/dist/src/lib/messages/index.d.ts +3 -0
  25. package/dist/src/lib/messages/index.d.ts.map +1 -0
  26. package/dist/src/lib/messages/index.js +19 -0
  27. package/dist/src/lib/messages/messageBuilderFactory.d.ts +7 -0
  28. package/dist/src/lib/messages/messageBuilderFactory.d.ts.map +1 -0
  29. package/dist/src/lib/messages/messageBuilderFactory.js +20 -0
  30. package/dist/src/lib/stakingActivateBuilder.d.ts +1 -1
  31. package/dist/src/lib/stakingActivateBuilder.d.ts.map +1 -1
  32. package/dist/src/lib/stakingActivateBuilder.js +30 -10
  33. package/dist/src/lib/stakingDeactivateBuilder.js +24 -10
  34. package/dist/src/lib/transaction.d.ts +24 -7
  35. package/dist/src/lib/transaction.d.ts.map +1 -1
  36. package/dist/src/lib/transaction.js +81 -17
  37. package/dist/src/lib/transactionBuilder.d.ts +114 -3
  38. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  39. package/dist/src/lib/transactionBuilder.js +464 -20
  40. package/dist/src/lib/transactionBuilderFactory.d.ts +2 -0
  41. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
  42. package/dist/src/lib/transactionBuilderFactory.js +7 -1
  43. package/dist/src/lib/utils.d.ts +22 -0
  44. package/dist/src/lib/utils.d.ts.map +1 -1
  45. package/dist/src/lib/utils.js +152 -17
  46. package/dist/src/lib/voteDelegationBuilder.d.ts +24 -0
  47. package/dist/src/lib/voteDelegationBuilder.d.ts.map +1 -0
  48. package/dist/src/lib/voteDelegationBuilder.js +84 -0
  49. package/dist/test/resources/cip8Resources.d.ts +25 -0
  50. package/dist/test/resources/cip8Resources.d.ts.map +1 -0
  51. package/dist/test/resources/cip8Resources.js +76 -0
  52. package/dist/test/resources/index.d.ts +458 -0
  53. package/dist/test/resources/index.d.ts.map +1 -0
  54. package/dist/test/resources/index.js +659 -0
  55. package/dist/test/unit/StakingActivateBuilder.d.ts +2 -0
  56. package/dist/test/unit/StakingActivateBuilder.d.ts.map +1 -0
  57. package/dist/test/unit/StakingActivateBuilder.js +213 -0
  58. package/dist/test/unit/StakingDeactivateBuilder.d.ts +2 -0
  59. package/dist/test/unit/StakingDeactivateBuilder.d.ts.map +1 -0
  60. package/dist/test/unit/StakingDeactivateBuilder.js +158 -0
  61. package/dist/test/unit/ada.d.ts +5 -0
  62. package/dist/test/unit/ada.d.ts.map +1 -0
  63. package/dist/test/unit/ada.js +1430 -0
  64. package/dist/test/unit/getBuilderFactory.d.ts +3 -0
  65. package/dist/test/unit/getBuilderFactory.d.ts.map +1 -0
  66. package/dist/test/unit/getBuilderFactory.js +10 -0
  67. package/dist/test/unit/index.d.ts +2 -0
  68. package/dist/test/unit/index.d.ts.map +1 -0
  69. package/dist/test/unit/index.js +32 -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 +88 -0
  73. package/dist/test/unit/messages/cip8/cip8Message.d.ts +2 -0
  74. package/dist/test/unit/messages/cip8/cip8Message.d.ts.map +1 -0
  75. package/dist/test/unit/messages/cip8/cip8Message.js +131 -0
  76. package/dist/test/unit/messages/cip8/cip8MessageBuilder.d.ts +2 -0
  77. package/dist/test/unit/messages/cip8/cip8MessageBuilder.d.ts.map +1 -0
  78. package/dist/test/unit/messages/cip8/cip8MessageBuilder.js +132 -0
  79. package/dist/test/unit/messages/cip8/utils.d.ts +2 -0
  80. package/dist/test/unit/messages/cip8/utils.d.ts.map +1 -0
  81. package/dist/test/unit/messages/cip8/utils.js +127 -0
  82. package/dist/test/unit/messages/messageBuilderFactory.d.ts +2 -0
  83. package/dist/test/unit/messages/messageBuilderFactory.d.ts.map +1 -0
  84. package/dist/test/unit/messages/messageBuilderFactory.js +35 -0
  85. package/dist/test/unit/stakingClaimRewardsBuilder.d.ts +2 -0
  86. package/dist/test/unit/stakingClaimRewardsBuilder.d.ts.map +1 -0
  87. package/dist/test/unit/stakingClaimRewardsBuilder.js +70 -0
  88. package/dist/test/unit/stakingPledgeBuilder.d.ts +2 -0
  89. package/dist/test/unit/stakingPledgeBuilder.d.ts.map +1 -0
  90. package/dist/test/unit/stakingPledgeBuilder.js +141 -0
  91. package/dist/test/unit/stakingWithdrawBuilder.d.ts +2 -0
  92. package/dist/test/unit/stakingWithdrawBuilder.d.ts.map +1 -0
  93. package/dist/test/unit/stakingWithdrawBuilder.js +167 -0
  94. package/dist/test/unit/tokenWithdrawal.d.ts +2 -0
  95. package/dist/test/unit/tokenWithdrawal.d.ts.map +1 -0
  96. package/dist/test/unit/tokenWithdrawal.js +959 -0
  97. package/dist/test/unit/transaction.d.ts +2 -0
  98. package/dist/test/unit/transaction.d.ts.map +1 -0
  99. package/dist/test/unit/transaction.js +100 -0
  100. package/dist/test/unit/transactionBuilder.d.ts +2 -0
  101. package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
  102. package/dist/test/unit/transactionBuilder.js +545 -0
  103. package/dist/test/unit/utils.d.ts +2 -0
  104. package/dist/test/unit/utils.d.ts.map +1 -0
  105. package/dist/test/unit/utils.js +138 -0
  106. package/dist/test/unit/voteDelegationBuilder.d.ts +2 -0
  107. package/dist/test/unit/voteDelegationBuilder.d.ts.map +1 -0
  108. package/dist/test/unit/voteDelegationBuilder.js +96 -0
  109. package/dist/tsconfig.tsbuildinfo +1 -0
  110. package/package.json +18 -13
  111. package/.eslintignore +0 -5
  112. package/.mocharc.yml +0 -8
  113. package/CHANGELOG.md +0 -450
@@ -0,0 +1,1430 @@
1
+ "use strict";
2
+ /**
3
+ * @prettier
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ const should = require("should");
43
+ const crypto_1 = require("crypto");
44
+ const sinon = __importStar(require("sinon"));
45
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
46
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
47
+ const resources_1 = require("../resources");
48
+ const _ = __importStar(require("lodash"));
49
+ const CardanoWasm = __importStar(require("@emurgo/cardano-serialization-lib-nodejs"));
50
+ const src_1 = require("../../src");
51
+ const lib_1 = require("../../src/lib");
52
+ const enum_1 = require("../../../sdk-core/src/account-lib/baseCoin/enum");
53
+ const assert_1 = __importDefault(require("assert"));
54
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
55
+ const nock_1 = __importDefault(require("nock"));
56
+ describe('ADA', function () {
57
+ const coinName = 'ada';
58
+ const tcoinName = 't' + coinName;
59
+ let bitgo;
60
+ let basecoin;
61
+ let newTxPrebuild;
62
+ let newTxParams;
63
+ const txPrebuild = {
64
+ txHex: resources_1.rawTx.unsignedTx,
65
+ txInfo: {},
66
+ };
67
+ const txParams = {
68
+ recipients: [
69
+ {
70
+ address: resources_1.rawTx.outputAddress1.address,
71
+ amount: '5000000',
72
+ },
73
+ {
74
+ address: resources_1.rawTx.outputAddress2.address,
75
+ amount: '248329150',
76
+ },
77
+ ],
78
+ };
79
+ const transactionExplanation = {
80
+ displayOrder: ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
81
+ id: 'f48f6ea0f75f3f942855cc0edf29e81e1e0724e75f5db8a1575b166fb202176c',
82
+ outputs: [
83
+ {
84
+ address: 'addr_test1qqnnvptrc3rec64q2n9jh572ncu5wvdtt8uvg4g3aj96s5dwu9nj70mlahzglm9939uevupsmj8dcdqv25d5n5r8vw8sn7prey',
85
+ amount: '7823121',
86
+ },
87
+ {
88
+ address: 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f',
89
+ amount: '13041729',
90
+ },
91
+ ],
92
+ outputAmount: '20864850',
93
+ changeOutputs: [],
94
+ changeAmount: '0',
95
+ fee: { fee: '167173' },
96
+ type: 'Transfer',
97
+ certificates: [],
98
+ withdrawals: [],
99
+ pledgeDetails: undefined,
100
+ };
101
+ before(function () {
102
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
103
+ bitgo.initializeTestVars();
104
+ bitgo.safeRegister(coinName, src_1.Ada.createInstance);
105
+ bitgo.safeRegister(tcoinName, src_1.Tada.createInstance);
106
+ basecoin = bitgo.coin(tcoinName);
107
+ newTxPrebuild = () => {
108
+ return _.cloneDeep(txPrebuild);
109
+ };
110
+ newTxParams = () => {
111
+ return _.cloneDeep(txParams);
112
+ };
113
+ });
114
+ it('should instantiate the coin', function () {
115
+ let localBasecoin = bitgo.coin(tcoinName);
116
+ localBasecoin.should.be.an.instanceof(src_1.Tada);
117
+ localBasecoin.getChain().should.equal(tcoinName);
118
+ localBasecoin.getFullName().should.equal('Testnet Ada');
119
+ localBasecoin = bitgo.coin(coinName);
120
+ localBasecoin.should.be.an.instanceof(src_1.Ada);
121
+ localBasecoin.getChain().should.equal(coinName);
122
+ localBasecoin.getFullName().should.equal('Cardano ADA');
123
+ });
124
+ describe('Sign Message', () => {
125
+ it('should be performed', async () => {
126
+ const keyPair = new src_1.KeyPair();
127
+ const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
128
+ const signature = await basecoin.signMessage(keyPair.getKeys(), messageToSign);
129
+ keyPair.verifySignature(messageToSign, Uint8Array.from(signature)).should.equals(false);
130
+ });
131
+ it('should fail with missing private key', async () => {
132
+ const keyPair = new src_1.KeyPair({
133
+ pub: '7788327c695dca4b3e649a0db45bc3e703a2c67428fce360e61800cc4248f4f7',
134
+ }).getKeys();
135
+ const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
136
+ await basecoin.signMessage(keyPair, messageToSign).should.be.rejectedWith('Invalid key pair options');
137
+ });
138
+ });
139
+ describe('Sign transaction', () => {
140
+ it('should sign transaction', async function () {
141
+ const signed = await basecoin.signTransaction({
142
+ txPrebuild: {
143
+ txHex: resources_1.rawTx.unsignedTx2,
144
+ },
145
+ pubs: [resources_1.publicKeys.pubKey1],
146
+ prv: resources_1.privateKeys.prvKey4,
147
+ });
148
+ signed.txHex.should.equal(resources_1.rawTx.signedTx2);
149
+ });
150
+ it('should fail to sign transaction with an invalid key', async function () {
151
+ try {
152
+ await basecoin.signTransaction({
153
+ txPrebuild: {
154
+ txHex: resources_1.rawTx.unsignedTx2,
155
+ },
156
+ pubs: [resources_1.publicKeys.pubKey1],
157
+ prv: resources_1.privateKeys.prvKey2,
158
+ });
159
+ }
160
+ catch (e) {
161
+ should.equal(e.message, 'Private key cannot sign the transaction');
162
+ }
163
+ });
164
+ it('should fail to build transaction with missing params', async function () {
165
+ try {
166
+ await basecoin.signTransaction({
167
+ txPrebuild: {
168
+ txHex: resources_1.rawTx.unsignedTx,
169
+ key: resources_1.enterpriseAccounts.account1.publicKey,
170
+ },
171
+ prv: resources_1.enterpriseAccounts.account1.secretKey,
172
+ });
173
+ }
174
+ catch (e) {
175
+ should.notEqual(e, null);
176
+ }
177
+ });
178
+ });
179
+ describe('Generate wallet key pair: ', () => {
180
+ it('should generate key pair', () => {
181
+ const kp = basecoin.generateKeyPair();
182
+ basecoin.isValidPub(kp.pub).should.equal(true);
183
+ basecoin.isValidPrv(kp.prv).should.equal(true);
184
+ });
185
+ it('should generate key pair from seed', () => {
186
+ const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
187
+ const kp = basecoin.generateKeyPair(seed);
188
+ basecoin.isValidPub(kp.pub).should.equal(true);
189
+ basecoin.isValidPrv(kp.prv).should.equal(true);
190
+ });
191
+ });
192
+ describe('Verify transaction: ', () => {
193
+ it('should succeed to verify unsigned transaction in hex encoding', async () => {
194
+ const txParams = newTxParams();
195
+ const txPrebuild = newTxPrebuild();
196
+ const verification = {};
197
+ const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
198
+ isTransactionVerified.should.equal(true);
199
+ });
200
+ it('should succeed to verify signed transaction in hex encoding', async () => {
201
+ const txPrebuild = {
202
+ txHex: resources_1.rawTx.signedTx,
203
+ txInfo: {},
204
+ };
205
+ const txParams = newTxParams();
206
+ const verification = {};
207
+ const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
208
+ isTransactionVerified.should.equal(true);
209
+ });
210
+ it('should fail verify transactions when have different recipients', async () => {
211
+ const txPrebuild = newTxPrebuild();
212
+ const txParams = {
213
+ recipients: [
214
+ {
215
+ address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
216
+ amount: '1000000000000000000000000',
217
+ },
218
+ {
219
+ address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
220
+ amount: '2000000000000000000000000',
221
+ },
222
+ ],
223
+ };
224
+ const verification = {};
225
+ await basecoin
226
+ .verifyTransaction({ txParams, txPrebuild, verification })
227
+ .should.be.rejectedWith('cannot find recipient in expected output');
228
+ });
229
+ it('should verify when input `recipients` is absent', async function () {
230
+ const txParams = newTxParams();
231
+ txParams.recipients = undefined;
232
+ const txPrebuild = newTxPrebuild();
233
+ const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
234
+ validTransaction.should.equal(true);
235
+ });
236
+ it('should fail verify when txHex is invalid', async function () {
237
+ const txParams = newTxParams();
238
+ txParams.recipients = undefined;
239
+ const txPrebuild = {};
240
+ await basecoin
241
+ .verifyTransaction({ txParams, txPrebuild })
242
+ .should.rejectedWith('missing required tx prebuild property txHex');
243
+ });
244
+ it('should succeed to verify transactions when recipients has extra data', async function () {
245
+ const txPrebuild = newTxPrebuild();
246
+ const txParams = newTxParams();
247
+ txParams.data = 'data';
248
+ const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
249
+ validTransaction.should.equal(true);
250
+ });
251
+ it('should verify a valid consolidation transaction', async () => {
252
+ const consolidationTx = {
253
+ txRequestId: '1b5c79c5-ab7c-4f47-912b-de6a95fb0779',
254
+ walletId: '64fa31a94db65a0007c9691b',
255
+ txHex: '84a40081825820db46c7c76ea54fec2ca0a2f94b77a238931a8dce2387c99a12b08dd8aac21c4f000181825839004601fc016ac38580916d3520bc76b659298156008738d347aa93142f4601fc016ac38580916d3520bc76b659298156008738d347aa93142f1a3b984357021a000286a9031a060e37eea0f5f6',
256
+ feeInfo: {
257
+ fee: 165545,
258
+ feeString: '165545',
259
+ },
260
+ txInfo: {
261
+ minerFee: '165545',
262
+ spendAmount: '999834455',
263
+ spendAmounts: [
264
+ {
265
+ coinName: 'tada',
266
+ amountString: '999834455',
267
+ },
268
+ ],
269
+ payGoFee: '0',
270
+ outputs: [
271
+ {
272
+ address: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
273
+ value: 999834455,
274
+ wallet: '64fa31a94db65a0007c9691b',
275
+ wallets: ['64fa31a94db65a0007c9691b'],
276
+ enterprise: '62cc59b727443a0007089033',
277
+ enterprises: ['62cc59b727443a0007089033'],
278
+ valueString: '999834455',
279
+ coinName: 'tada',
280
+ walletType: 'hot',
281
+ walletTypes: ['hot'],
282
+ },
283
+ ],
284
+ inputs: [
285
+ {
286
+ value: 1000000000,
287
+ address: 'addr_test1qqlzxfl7tlgp999x4a7334pchycpkk72pykrsr3mryl3yj6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsvpgl8w',
288
+ valueString: '1000000000',
289
+ },
290
+ ],
291
+ type: '0',
292
+ },
293
+ consolidateId: '68b9fc18558006aab53785615fea7c28',
294
+ coin: 'tada',
295
+ };
296
+ const mockedWallet = {
297
+ coinSpecific: () => {
298
+ return {
299
+ rootAddress: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
300
+ };
301
+ },
302
+ };
303
+ try {
304
+ const isVerified = await basecoin.verifyTransaction({
305
+ txParams: {},
306
+ txPrebuild: consolidationTx,
307
+ wallet: mockedWallet,
308
+ verification: {
309
+ consolidationToBaseAddress: true,
310
+ },
311
+ });
312
+ isVerified.should.equal(true);
313
+ }
314
+ catch (e) {
315
+ assert_1.default.fail('Transaction should pass verification');
316
+ }
317
+ });
318
+ it('should verify a valid sponsored consolidation transaction', async () => {
319
+ const consolidationTx = {
320
+ txRequestId: '1b5c79c5-ab7c-4f47-912b-de6a95fb0779',
321
+ walletId: '64fa31a94db65a0007c9691b',
322
+ txHex: '84a40082825820227f65d20ac6e49602d79c623c51911ead824235e01eb2a1e7e33a72f0747cbb00825820227f65d20ac6e49602d79c623c51911ead824235e01eb2a1e7e33a72f0747cbb0201828258390022098270a5c19c9fb706dce0e7e4566b234ec5f0010623cd63f198ad22098270a5c19c9fb706dce0e7e4566b234ec5f0010623cd63f198ad1a0098968082581d60cf90f9fb02c88bad3c5294d90587458c4f160a2db26ba8af3da255b11a05d42fb8021a0002a491031a06d8c048a0f5f6',
323
+ feeInfo: {
324
+ fee: 165545,
325
+ feeString: '165545',
326
+ },
327
+ txInfo: {
328
+ minerFee: '165545',
329
+ spendAmount: '999834455',
330
+ spendAmounts: [
331
+ {
332
+ coinName: 'tada',
333
+ amountString: '999834455',
334
+ },
335
+ ],
336
+ payGoFee: '0',
337
+ outputs: [
338
+ {
339
+ address: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
340
+ value: 999834455,
341
+ wallet: '64fa31a94db65a0007c9691b',
342
+ wallets: ['64fa31a94db65a0007c9691b'],
343
+ enterprise: '62cc59b727443a0007089033',
344
+ enterprises: ['62cc59b727443a0007089033'],
345
+ valueString: '999834455',
346
+ coinName: 'tada',
347
+ walletType: 'hot',
348
+ walletTypes: ['hot'],
349
+ },
350
+ ],
351
+ inputs: [
352
+ {
353
+ value: 1000000000,
354
+ address: 'addr_test1qqlzxfl7tlgp999x4a7334pchycpkk72pykrsr3mryl3yj6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsvpgl8w',
355
+ valueString: '1000000000',
356
+ },
357
+ ],
358
+ type: '0',
359
+ feeAddress: 'addr_test1vr8ep70mqtyghtfu222djpv8gkxy79s29kexh2908k39tvge02d5j',
360
+ },
361
+ consolidateId: '68b9fc18558006aab53785615fea7c28',
362
+ coin: 'tada',
363
+ };
364
+ const mockedWallet = {
365
+ coinSpecific: () => {
366
+ return {
367
+ rootAddress: 'addr_test1qq3qnqns5hqee8ahqmwwpely2e4jxnk97qqsvg7dv0ce3tfzpxp8pfwpnj0mwpkuurn7g4ntyd8vtuqpqc3u6cl3nzksvggu82',
368
+ };
369
+ },
370
+ };
371
+ try {
372
+ const isVerified = await basecoin.verifyTransaction({
373
+ txParams: {},
374
+ txPrebuild: consolidationTx,
375
+ wallet: mockedWallet,
376
+ verification: {
377
+ consolidationToBaseAddress: true,
378
+ },
379
+ });
380
+ isVerified.should.equal(true);
381
+ }
382
+ catch (e) {
383
+ assert_1.default.fail('Transaction should pass verification');
384
+ }
385
+ });
386
+ it('should fail to sign a spoofed consolidation transaction', async function () {
387
+ // Set up wallet data
388
+ const walletData = {
389
+ id: '5b34252f1bf349930e34020a00000000',
390
+ coin: 'tada',
391
+ keys: [
392
+ '5b3424f91bf349930e34017500000000',
393
+ '5b3424f91bf349930e34017600000000',
394
+ '5b3424f91bf349930e34017700000000',
395
+ ],
396
+ coinSpecific: {
397
+ rootAddress: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
398
+ },
399
+ multisigType: 'tss',
400
+ };
401
+ const fakePrv = (0, sdk_api_1.encrypt)('password', 'prv');
402
+ const walletObj = new sdk_core_1.Wallet(bitgo, basecoin, walletData);
403
+ const bgUrl = sdk_core_1.common.Environments['mock'].uri;
404
+ (0, nock_1.default)(bgUrl)
405
+ .get('/api/v2/tada/key/5b3424f91bf349930e34017500000000')
406
+ .reply(200, [
407
+ {
408
+ encryptedPrv: fakePrv,
409
+ },
410
+ ]);
411
+ // Mock the API response for buildAccountConsolidations
412
+ (0, nock_1.default)(bgUrl)
413
+ .post('/api/v2/tada/wallet/5b34252f1bf349930e34020a00000000/consolidateAccount/build')
414
+ .reply(200, [
415
+ {
416
+ txRequestId: '1b5c79c5-ab7c-4f47-912b-de6a95fb0779',
417
+ walletId: '64fa31a94db65a0007c9691b',
418
+ txHex: '84a40081825820db46c7c76ea54fec2ca0a2f94b77a238931a8dce2387c99a12b08dd8aac21c4f01018282581d6033c378cee41b2e15ac848f7f6f1d2f78155ab12d93b713de898d855f1a00989680825839004601fc016ac38580916d3520bc76b659298156008738d347aa93142f4601fc016ac38580916d3520bc76b659298156008738d347aa93142f1b0000000217acebe9021a00028db5031a060e3b41a0f5f6',
419
+ feeInfo: {
420
+ fee: 165545,
421
+ feeString: '165545',
422
+ },
423
+ txInfo: {
424
+ minerFee: '165545',
425
+ spendAmount: '999834455',
426
+ spendAmounts: [
427
+ {
428
+ coinName: 'tada',
429
+ amountString: '999834455',
430
+ },
431
+ ],
432
+ payGoFee: '0',
433
+ outputs: [
434
+ {
435
+ address: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
436
+ value: 999834455,
437
+ wallet: '64fa31a94db65a0007c9691b',
438
+ wallets: ['64fa31a94db65a0007c9691b'],
439
+ enterprise: '62cc59b727443a0007089033',
440
+ enterprises: ['62cc59b727443a0007089033'],
441
+ valueString: '999834455',
442
+ coinName: 'tada',
443
+ walletType: 'hot',
444
+ walletTypes: ['hot'],
445
+ },
446
+ ],
447
+ inputs: [
448
+ {
449
+ value: 1000000000,
450
+ address: 'addr_test1qqlzxfl7tlgp999x4a7334pchycpkk72pykrsr3mryl3yj6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsvpgl8w',
451
+ valueString: '1000000000',
452
+ },
453
+ ],
454
+ type: '0',
455
+ },
456
+ consolidateId: '68b9fc18558006aab53785615fea7c28',
457
+ coin: 'tada',
458
+ },
459
+ ]);
460
+ // Call the function to test
461
+ await assert_1.default.rejects(async () => {
462
+ await walletObj.sendAccountConsolidations({
463
+ walletPassphrase: 'password',
464
+ });
465
+ }, {
466
+ message: 'tx outputs does not match with expected address',
467
+ });
468
+ });
469
+ });
470
+ describe('Explain Transactions:', () => {
471
+ it('should explain an unsigned transfer transaction', async function () {
472
+ const explainedTransaction = await basecoin.explainTransaction({
473
+ txPrebuild: {
474
+ txHex: resources_1.rawTx.unsignedTx2,
475
+ },
476
+ });
477
+ console.log(explainedTransaction);
478
+ explainedTransaction.should.deepEqual(transactionExplanation);
479
+ });
480
+ it('should fail to explain transaction with missing params', async function () {
481
+ try {
482
+ await basecoin.explainTransaction({
483
+ txPrebuild: {},
484
+ });
485
+ }
486
+ catch (error) {
487
+ should.equal(error.message, 'Invalid transaction');
488
+ }
489
+ });
490
+ it('should fail to explain transaction with wrong params', async function () {
491
+ try {
492
+ await basecoin.explainTransaction({
493
+ txPrebuild: {
494
+ txHex: 'invalidTxHex',
495
+ },
496
+ });
497
+ }
498
+ catch (error) {
499
+ should.equal(error.message, 'Invalid transaction');
500
+ }
501
+ });
502
+ });
503
+ describe('Parse Raw Transactions', () => {
504
+ it('should parse staking pledge transaction', function () {
505
+ const tx = new lib_1.Transaction(basecoin);
506
+ tx.fromRawTransaction(resources_1.rawTx.unsignedNewPledgeTx);
507
+ should.equal(tx.type, enum_1.TransactionType.StakingPledge);
508
+ });
509
+ it('should parse staking activation tx', function () {
510
+ const tx = new lib_1.Transaction(basecoin);
511
+ tx.fromRawTransaction(resources_1.rawTx.unsignedStakingActiveTx);
512
+ should.equal(tx.type, enum_1.TransactionType.StakingActivate);
513
+ });
514
+ it('should parse staking deactivation tx', function () {
515
+ const tx = new lib_1.Transaction(basecoin);
516
+ tx.fromRawTransaction(resources_1.rawTx.unsignedStakingDeactiveTx);
517
+ should.equal(tx.type, enum_1.TransactionType.StakingDeactivate);
518
+ });
519
+ });
520
+ describe('Parse Transactions:', () => {
521
+ it('should parse an unsigned transfer transaction', async function () {
522
+ const parsedTransaction = await basecoin.parseTransaction({
523
+ txPrebuild: {
524
+ txHex: resources_1.rawTx.unsignedTx2,
525
+ },
526
+ });
527
+ parsedTransaction.should.deepEqual(transactionExplanation);
528
+ });
529
+ it('should parse a signed transfer transaction', async function () {
530
+ const parsedTransaction = await basecoin.parseTransaction({
531
+ txPrebuild: {
532
+ txHex: resources_1.rawTx.signedTx2,
533
+ },
534
+ });
535
+ parsedTransaction.should.deepEqual(transactionExplanation);
536
+ });
537
+ it('should fail parse a signed transfer transaction when explainTransaction response is undefined', async function () {
538
+ const stub = sinon.stub(src_1.Ada.prototype, 'explainTransaction');
539
+ stub.resolves(undefined);
540
+ await basecoin
541
+ .parseTransaction({
542
+ txPrebuild: {
543
+ txHex: resources_1.rawTx.signedTx,
544
+ },
545
+ })
546
+ .should.be.rejectedWith('Invalid transaction');
547
+ stub.restore();
548
+ });
549
+ });
550
+ describe('Recover Transactions:', () => {
551
+ const destAddr = resources_1.address.address2;
552
+ const sandBox = sinon.createSandbox();
553
+ let callBack;
554
+ beforeEach(function () {
555
+ callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
556
+ callBack
557
+ .withArgs('address_info', {
558
+ _addresses: [resources_1.wrwUser.walletAddress0],
559
+ })
560
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
561
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
562
+ });
563
+ afterEach(function () {
564
+ sandBox.restore();
565
+ });
566
+ it('should take OVC output and generate a signed sweep transaction', async function () {
567
+ const params = resources_1.ovcResponse;
568
+ const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
569
+ recoveryTxn.transactions[0].serializedTx.should.equal('84a400818258204bd0f991c1532cffe31d4a10db492b43175ec326765b6b29ceee598df2b61f470001818258390087379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c87379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c1a05f359ff021a00028701031a024972e1a10081825820bbacb13431b99208e6e8cdbf710147feaf06a39d71565e60b411ce9e4fa3f137584001a4ab8236563f69ff309e5786e8f39c629ed57676c692159cb2e0494c9e663355384c13c749d04c17a80ba2a45cc127df480fc64a43199a772f11acd5b14a0ff5f6');
570
+ recoveryTxn.transactions[0].scanIndex.should.equal(0);
571
+ recoveryTxn.lastScanIndex.should.equal(0);
572
+ });
573
+ it('should take consolidation OVC output and generate multiple signed sweep transactions', async function () {
574
+ const params = resources_1.ovcResponse2;
575
+ const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
576
+ recoveryTxn.transactions[0].serializedTx.should.equal('84a400818258203e62e5ee8b12012c4b949f9777b72165239bb2146ae8b078b4d1c5ca8d3168e300018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa10081825820500e0d725a5ba3a306da3503dfe57b8a14068a09b61b36ec068fcf8cf5c391de5840c836ce6d3262d5654706ea06721522d3b75f6d545245047a7be7463629d88b3f4264b995f591df52bdffcf09da1e6ab9e88de3714c6e2ec1961786cf1c586a07f5f6');
577
+ recoveryTxn.transactions[0].scanIndex.should.equal(1);
578
+ recoveryTxn.transactions[1].serializedTx.should.equal('84a4008182582029c10acf0e08f9523325c88243565af6b32274992189c1153903c410bed7c2c700018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa1008182582062770b224bd314bc526fbd6a94e9082fb6458c425e6e09bad74004dd897e962358403842544f2ff28be054eb7c7997bc303b1e251eb13a41802c82318e592bb24eaa3197c450e797cc8559f0356cd5cdd1ab5eb80c5173e34e9e1d1737533a89520cf5f6');
579
+ recoveryTxn.transactions[1].scanIndex.should.equal(2);
580
+ recoveryTxn.transactions[2].serializedTx.should.equal('84a40081825820dd140f133d865e1bb5642e708fe685bf7601d71d0c99511e5d552da7f8bd10ff00018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa1008182582053b4bb74aa38add458dafc8153f0aa8266acad59322b877ca9c23c5d3873779d5840e94ce7896957d094c6bafbf2ec10df5ebb0f1d2a27a7e31f2d45c531fb687edd6c4d33f8e9b99c7692b6fac6d8399bd8fd47641baae9bbb69f518d42ad11710af5f6');
581
+ recoveryTxn.transactions[2].scanIndex.should.equal(3);
582
+ recoveryTxn.transactions[3].serializedTx.should.equal('84a4008182582015a1d6db5d3f592aa1cda185b6359ca0e2921c3c51959f64222a6b7d95d3392300018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa10081825820600f86ca22d670f0a990ade4e882c05e654343263494735a31517de0819676735840fe199f8e247a4cfabfeb4f9cb574aa35739a0aa98860ee0a85d720c4ab4fecfac7b4504df310b3e4bea04711f60652d4a8cf5eb41817293b8d29977fe695f704f5f6');
583
+ recoveryTxn.transactions[3].scanIndex.should.equal(4);
584
+ recoveryTxn.lastScanIndex.should.equal(20);
585
+ });
586
+ it('should recover a txn for non-bitgo recoveries', async function () {
587
+ const res = await basecoin.recover({
588
+ userKey: resources_1.wrwUser.userKey,
589
+ backupKey: resources_1.wrwUser.backupKey,
590
+ bitgoKey: resources_1.wrwUser.bitgoKey,
591
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
592
+ recoveryDestination: destAddr,
593
+ });
594
+ res.should.not.be.empty();
595
+ res.should.hasOwnProperty('serializedTx');
596
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
597
+ const tx = new lib_1.Transaction(basecoin);
598
+ tx.fromRawTransaction(res.serializedTx);
599
+ const txJson = tx.toJson();
600
+ const fee = Number(tx.explainTransaction().fee.fee);
601
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
602
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
603
+ should.deepEqual(txJson.outputs[0].address, destAddr);
604
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value);
605
+ });
606
+ it('should recover a txn for unsigned sweep recoveries', async function () {
607
+ const res = await basecoin.recover({
608
+ bitgoKey: resources_1.wrwUser.bitgoKey,
609
+ recoveryDestination: destAddr,
610
+ });
611
+ res.should.not.be.empty();
612
+ res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
613
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
614
+ const tx = new lib_1.Transaction(basecoin);
615
+ tx.fromRawTransaction(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
616
+ const txJson = tx.toJson();
617
+ const fee = Number(tx.explainTransaction().fee.fee);
618
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
619
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
620
+ should.deepEqual(txJson.outputs[0].address, destAddr);
621
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value);
622
+ });
623
+ it('should recover ADA plus token UTXOs - token and ADA both appear in outputs (unsigned sweep)', async function () {
624
+ callBack
625
+ .withArgs('address_info', { _addresses: [resources_1.wrwUser.walletAddress0] })
626
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
627
+ const res = await basecoin.recover({
628
+ bitgoKey: resources_1.wrwUser.bitgoKey,
629
+ recoveryDestination: destAddr,
630
+ });
631
+ res.should.not.be.empty();
632
+ const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
633
+ unsignedTx.should.hasOwnProperty('serializedTx');
634
+ const tx = new lib_1.Transaction(basecoin);
635
+ tx.fromRawTransaction(unsignedTx.serializedTx);
636
+ const txJson = tx.toJson();
637
+ txJson.inputs.length.should.equal(2);
638
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
639
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_TOKEN.tx_hash);
640
+ txJson.outputs.length.should.equal(2);
641
+ const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
642
+ const tokenEncodedAssetName = '5741544552';
643
+ const tokenQuantity = '111';
644
+ const minADAForToken = 1500000;
645
+ const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
646
+ should.exist(tokenOutput);
647
+ should.deepEqual(tokenOutput.address, destAddr);
648
+ should.deepEqual(Number(tokenOutput.amount), minADAForToken);
649
+ const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
650
+ const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
651
+ tokenOutput.multiAssets
652
+ .get_asset(expectedPolicyId, expectedAssetName)
653
+ .to_str()
654
+ .should.equal(tokenQuantity);
655
+ const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
656
+ should.exist(adaOutput);
657
+ should.deepEqual(adaOutput.address, destAddr);
658
+ const fee = Number(tx.explainTransaction().fee.fee);
659
+ const totalBalance = resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_TOKEN.value;
660
+ should.deepEqual(Number(adaOutput.amount), totalBalance - minADAForToken - fee);
661
+ const explained = tx.explainTransaction();
662
+ const explainedTokenOutput = explained.outputs.find((o) => o.amount === minADAForToken.toString());
663
+ should.exist(explainedTokenOutput);
664
+ // inputs and outputs in parsedTx should carry multiAssets
665
+ const parsedTxInputs = res.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs;
666
+ parsedTxInputs.length.should.equal(1);
667
+ should.exist(parsedTxInputs[0].multiAssets);
668
+ parsedTxInputs[0].multiAssets.length.should.equal(1);
669
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].policy_id, tokenPolicyId);
670
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].asset_name, tokenEncodedAssetName);
671
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].quantity, tokenQuantity);
672
+ const parsedTxOutputs = res.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs;
673
+ const parsedTokenOutput = parsedTxOutputs.find((o) => o.multiAssets !== undefined);
674
+ should.exist(parsedTokenOutput);
675
+ parsedTokenOutput.multiAssets.length.should.equal(1);
676
+ should.deepEqual(parsedTokenOutput.multiAssets[0].policy_id, tokenPolicyId);
677
+ should.deepEqual(parsedTokenOutput.multiAssets[0].asset_name, tokenEncodedAssetName);
678
+ should.deepEqual(parsedTokenOutput.multiAssets[0].quantity, tokenQuantity);
679
+ // pure ADA output should not have multiAssets
680
+ const parsedAdaOutput = parsedTxOutputs.find((o) => o.multiAssets === undefined);
681
+ should.exist(parsedAdaOutput);
682
+ });
683
+ it('should recover ADA plus token UTXOs - token and ADA both appear in outputs (signed)', async function () {
684
+ callBack
685
+ .withArgs('address_info', { _addresses: [resources_1.wrwUser.walletAddress0] })
686
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
687
+ const res = await basecoin.recover({
688
+ userKey: resources_1.wrwUser.userKey,
689
+ backupKey: resources_1.wrwUser.backupKey,
690
+ bitgoKey: resources_1.wrwUser.bitgoKey,
691
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
692
+ recoveryDestination: destAddr,
693
+ });
694
+ res.should.not.be.empty();
695
+ res.should.hasOwnProperty('serializedTx');
696
+ const tx = new lib_1.Transaction(basecoin);
697
+ tx.fromRawTransaction(res.serializedTx);
698
+ const txJson = tx.toJson();
699
+ txJson.inputs.length.should.equal(2);
700
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
701
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_TOKEN.tx_hash);
702
+ // expect 2 outputs: one token output + one ADA change output, both at destAddr
703
+ txJson.outputs.length.should.equal(2);
704
+ const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
705
+ const tokenEncodedAssetName = '5741544552';
706
+ const tokenQuantity = '111';
707
+ const minADAForToken = 1500000;
708
+ const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
709
+ should.exist(tokenOutput);
710
+ should.deepEqual(tokenOutput.address, destAddr);
711
+ should.deepEqual(Number(tokenOutput.amount), minADAForToken);
712
+ const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
713
+ const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
714
+ tokenOutput.multiAssets
715
+ .get_asset(expectedPolicyId, expectedAssetName)
716
+ .to_str()
717
+ .should.equal(tokenQuantity);
718
+ const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
719
+ should.exist(adaOutput);
720
+ should.deepEqual(adaOutput.address, destAddr);
721
+ const fee = Number(tx.explainTransaction().fee.fee);
722
+ const totalBalance = resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_TOKEN.value;
723
+ should.deepEqual(Number(adaOutput.amount), totalBalance - minADAForToken - fee);
724
+ });
725
+ });
726
+ describe('Recover Transactions Multiple UTXO:', () => {
727
+ const destAddr = resources_1.address.address2;
728
+ const sandBox = sinon.createSandbox();
729
+ beforeEach(function () {
730
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
731
+ callBack
732
+ .withArgs('address_info', {
733
+ _addresses: [resources_1.wrwUser.walletAddress0],
734
+ })
735
+ .resolves(resources_1.endpointResponses.addressInfoResponse.TwoUTXO);
736
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
737
+ });
738
+ afterEach(function () {
739
+ sandBox.restore();
740
+ });
741
+ it('should recover a txn for non-bitgo recoveries', async function () {
742
+ const res = await basecoin.recover({
743
+ userKey: resources_1.wrwUser.userKey,
744
+ backupKey: resources_1.wrwUser.backupKey,
745
+ bitgoKey: resources_1.wrwUser.bitgoKey,
746
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
747
+ recoveryDestination: destAddr,
748
+ });
749
+ res.should.not.be.empty();
750
+ res.should.hasOwnProperty('serializedTx');
751
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
752
+ const tx = new lib_1.Transaction(basecoin);
753
+ tx.fromRawTransaction(res.serializedTx);
754
+ const txJson = tx.toJson();
755
+ const fee = Number(tx.explainTransaction().fee.fee);
756
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
757
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
758
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
759
+ should.deepEqual(txJson.inputs[1].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
760
+ should.deepEqual(txJson.outputs[0].address, destAddr);
761
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_2.value);
762
+ });
763
+ it('should recover a txn for unsigned sweep recoveries', async function () {
764
+ const res = await basecoin.recover({
765
+ bitgoKey: resources_1.wrwUser.bitgoKey,
766
+ recoveryDestination: destAddr,
767
+ });
768
+ res.should.not.be.empty();
769
+ res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
770
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
771
+ const tx = new lib_1.Transaction(basecoin);
772
+ tx.fromRawTransaction(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
773
+ const txJson = tx.toJson();
774
+ const fee = Number(tx.explainTransaction().fee.fee);
775
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
776
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
777
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
778
+ should.deepEqual(txJson.inputs[1].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
779
+ should.deepEqual(txJson.outputs[0].address, destAddr);
780
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_2.value);
781
+ });
782
+ });
783
+ describe('Build Consolidation Recoveries:', () => {
784
+ const baseAddr = resources_1.consolidationWrwUser.walletAddress0;
785
+ const sandBox = sinon.createSandbox();
786
+ beforeEach(function () {
787
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
788
+ callBack
789
+ .withArgs('address_info', {
790
+ _addresses: [resources_1.consolidationWrwUser.walletAddress1],
791
+ })
792
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
793
+ callBack
794
+ .withArgs('address_info', {
795
+ _addresses: [resources_1.consolidationWrwUser.walletAddress2],
796
+ })
797
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
798
+ callBack
799
+ .withArgs('address_info', {
800
+ _addresses: [resources_1.consolidationWrwUser.walletAddress3],
801
+ })
802
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO2);
803
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
804
+ });
805
+ afterEach(function () {
806
+ sandBox.restore();
807
+ });
808
+ it('should build signed consolidation recoveries', async function () {
809
+ const res = await basecoin.recoverConsolidations({
810
+ userKey: resources_1.consolidationWrwUser.userKey,
811
+ backupKey: resources_1.consolidationWrwUser.backupKey,
812
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
813
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
814
+ startingScanIndex: 1,
815
+ endingScanIndex: 4,
816
+ });
817
+ res.should.not.be.empty();
818
+ res.transactions.length.should.equal(2);
819
+ res.lastScanIndex.should.equal(3);
820
+ const txn1 = res.transactions[0];
821
+ const tx1 = new lib_1.Transaction(basecoin);
822
+ tx1.fromRawTransaction(txn1.serializedTx);
823
+ const txJson1 = tx1.toJson();
824
+ const fee1 = Number(tx1.explainTransaction().fee.fee);
825
+ should.deepEqual(txJson1.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
826
+ should.deepEqual(txJson1.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
827
+ should.deepEqual(txJson1.outputs[0].address, baseAddr);
828
+ should.deepEqual(Number(txJson1.outputs[0].amount) + fee1, resources_1.testnetUTXO.UTXO_1.value);
829
+ const txn2 = res.transactions[1];
830
+ const tx2 = new lib_1.Transaction(basecoin);
831
+ tx2.fromRawTransaction(txn2.serializedTx);
832
+ const txJson2 = tx2.toJson();
833
+ const fee2 = Number(tx2.explainTransaction().fee.fee);
834
+ should.deepEqual(txJson2.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
835
+ should.deepEqual(txJson2.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
836
+ should.deepEqual(txJson2.outputs[0].address, baseAddr);
837
+ should.deepEqual(Number(txJson2.outputs[0].amount) + fee2, resources_1.testnetUTXO.UTXO_2.value);
838
+ });
839
+ it('should skip building consolidate transaction if balance is equal to zero', async function () {
840
+ await basecoin
841
+ .recoverConsolidations({
842
+ userKey: resources_1.consolidationWrwUser.userKey,
843
+ backupKey: resources_1.consolidationWrwUser.backupKey,
844
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
845
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
846
+ startingScanIndex: 1,
847
+ endingScanIndex: 2,
848
+ })
849
+ .should.rejectedWith('Did not find an address with funds to recover.');
850
+ });
851
+ it('should throw if startingScanIndex is not ge to 1', async () => {
852
+ await basecoin
853
+ .recoverConsolidations({
854
+ userKey: resources_1.consolidationWrwUser.userKey,
855
+ backupKey: resources_1.consolidationWrwUser.backupKey,
856
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
857
+ startingScanIndex: -1,
858
+ })
859
+ .should.be.rejectedWith('Invalid starting or ending index to scan for addresses. startingScanIndex: -1, endingScanIndex: 19.');
860
+ });
861
+ it('should throw if scan factor is too high', async () => {
862
+ await basecoin
863
+ .recoverConsolidations({
864
+ userKey: resources_1.consolidationWrwUser.userKey,
865
+ backupKey: resources_1.consolidationWrwUser.backupKey,
866
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
867
+ startingScanIndex: 1,
868
+ endingScanIndex: 300,
869
+ })
870
+ .should.be.rejectedWith('Invalid starting or ending index to scan for addresses. startingScanIndex: 1, endingScanIndex: 300.');
871
+ });
872
+ it('should build unsigned consolidation recoveries', async function () {
873
+ const res = await basecoin.recoverConsolidations({
874
+ userKey: resources_1.consolidationWrwUser.userKey,
875
+ backupKey: resources_1.consolidationWrwUser.backupKey,
876
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
877
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
878
+ startingScanIndex: 1,
879
+ endingScanIndex: 4,
880
+ });
881
+ res.should.not.be.empty();
882
+ res.transactions.length.should.equal(2);
883
+ });
884
+ it('should build unsigned consolidation recoveries for WRW (ADA only) and assert build response', async function () {
885
+ const res = await basecoin.recoverConsolidations({
886
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
887
+ startingScanIndex: 1,
888
+ endingScanIndex: 4,
889
+ });
890
+ res.should.not.be.empty();
891
+ res.txRequests.length.should.equal(2);
892
+ // Assert first consolidation txRequest structure
893
+ const txRequest1 = res.txRequests[0];
894
+ txRequest1.transactions.length.should.equal(1);
895
+ const unsignedTx1 = txRequest1.transactions[0].unsignedTx;
896
+ unsignedTx1.should.hasOwnProperty('serializedTx');
897
+ unsignedTx1.should.hasOwnProperty('parsedTx');
898
+ unsignedTx1.should.hasOwnProperty('coinSpecific');
899
+ // Deserialize and verify inputs/outputs
900
+ const tx1 = new lib_1.Transaction(basecoin);
901
+ tx1.fromRawTransaction(unsignedTx1.serializedTx);
902
+ const txJson1 = tx1.toJson();
903
+ const fee1 = Number(tx1.explainTransaction().fee.fee);
904
+ should.deepEqual(txJson1.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
905
+ should.deepEqual(txJson1.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
906
+ should.deepEqual(txJson1.outputs[0].address, baseAddr);
907
+ should.deepEqual(Number(txJson1.outputs[0].amount) + fee1, resources_1.testnetUTXO.UTXO_1.value);
908
+ // parsedTx inputs/outputs must be present and carry correct address
909
+ const parsedTx1Inputs = unsignedTx1.parsedTx.inputs;
910
+ parsedTx1Inputs.length.should.equal(1);
911
+ should.deepEqual(parsedTx1Inputs[0].address, resources_1.consolidationWrwUser.walletAddress2);
912
+ const parsedTx1Outputs = unsignedTx1.parsedTx.outputs;
913
+ parsedTx1Outputs.length.should.be.greaterThan(0);
914
+ should.deepEqual(parsedTx1Outputs[0].address, baseAddr);
915
+ // Assert second consolidation txRequest structure
916
+ const txRequest2 = res.txRequests[1];
917
+ const unsignedTx2 = txRequest2.transactions[0].unsignedTx;
918
+ unsignedTx2.should.hasOwnProperty('serializedTx');
919
+ const tx2 = new lib_1.Transaction(basecoin);
920
+ tx2.fromRawTransaction(unsignedTx2.serializedTx);
921
+ const txJson2 = tx2.toJson();
922
+ const fee2 = Number(tx2.explainTransaction().fee.fee);
923
+ should.deepEqual(txJson2.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
924
+ should.deepEqual(txJson2.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
925
+ should.deepEqual(txJson2.outputs[0].address, baseAddr);
926
+ should.deepEqual(Number(txJson2.outputs[0].amount) + fee2, resources_1.testnetUTXO.UTXO_2.value);
927
+ // lastScanIndex must be set in coinSpecific of the last txRequest
928
+ const lastCoinSpecific = unsignedTx2.coinSpecific;
929
+ lastCoinSpecific.should.hasOwnProperty('lastScanIndex');
930
+ lastCoinSpecific.lastScanIndex.should.equal(3);
931
+ });
932
+ it('should build unsigned consolidation recoveries for WRW (ADA + Token) and assert build response', async function () {
933
+ // Override walletAddress2 to return ADA+Token UTXOs
934
+ sandBox.restore();
935
+ const callBack2 = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
936
+ callBack2
937
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress1] })
938
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
939
+ callBack2
940
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress2] })
941
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
942
+ callBack2
943
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress3] })
944
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
945
+ callBack2.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
946
+ const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
947
+ const tokenEncodedAssetName = '5741544552';
948
+ const tokenQuantity = '111';
949
+ const minADAForToken = 1500000;
950
+ const res = await basecoin.recoverConsolidations({
951
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
952
+ startingScanIndex: 1,
953
+ endingScanIndex: 4,
954
+ });
955
+ res.should.not.be.empty();
956
+ res.txRequests.length.should.equal(1);
957
+ const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
958
+ unsignedTx.should.hasOwnProperty('serializedTx');
959
+ const tx = new lib_1.Transaction(basecoin);
960
+ tx.fromRawTransaction(unsignedTx.serializedTx);
961
+ const txJson = tx.toJson();
962
+ // Two inputs: ADA UTXO + Token UTXO
963
+ txJson.inputs.length.should.equal(2);
964
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
965
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_TOKEN.tx_hash);
966
+ // Two outputs: token output (with multiAssets) + pure ADA change to base address
967
+ txJson.outputs.length.should.equal(2);
968
+ const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
969
+ should.exist(tokenOutput);
970
+ should.deepEqual(tokenOutput.address, baseAddr);
971
+ should.deepEqual(Number(tokenOutput.amount), minADAForToken);
972
+ const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
973
+ const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
974
+ tokenOutput.multiAssets
975
+ .get_asset(expectedPolicyId, expectedAssetName)
976
+ .to_str()
977
+ .should.equal(tokenQuantity);
978
+ const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
979
+ should.exist(adaOutput);
980
+ should.deepEqual(adaOutput.address, baseAddr);
981
+ const fee = Number(tx.explainTransaction().fee.fee);
982
+ const totalBalance = resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_TOKEN.value;
983
+ should.deepEqual(Number(adaOutput.amount), totalBalance - minADAForToken - fee);
984
+ // parsedTx inputs must carry multiAssets for the token UTXO
985
+ const parsedTxInputs = unsignedTx.parsedTx.inputs;
986
+ parsedTxInputs.length.should.equal(1);
987
+ should.deepEqual(parsedTxInputs[0].address, resources_1.consolidationWrwUser.walletAddress2);
988
+ should.exist(parsedTxInputs[0].multiAssets);
989
+ parsedTxInputs[0].multiAssets.length.should.equal(1);
990
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].policy_id, tokenPolicyId);
991
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].asset_name, tokenEncodedAssetName);
992
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].quantity, tokenQuantity);
993
+ // parsedTx outputs must carry multiAssets for the token output
994
+ const parsedTxOutputs = unsignedTx.parsedTx.outputs;
995
+ const parsedTokenOutput = parsedTxOutputs.find((o) => o.multiAssets !== undefined);
996
+ should.exist(parsedTokenOutput);
997
+ parsedTokenOutput.multiAssets.length.should.equal(1);
998
+ should.deepEqual(parsedTokenOutput.multiAssets[0].policy_id, tokenPolicyId);
999
+ should.deepEqual(parsedTokenOutput.multiAssets[0].asset_name, tokenEncodedAssetName);
1000
+ should.deepEqual(parsedTokenOutput.multiAssets[0].quantity, tokenQuantity);
1001
+ // pure ADA output must not have multiAssets
1002
+ const parsedAdaOutput = parsedTxOutputs.find((o) => o.multiAssets === undefined);
1003
+ should.exist(parsedAdaOutput);
1004
+ // lastScanIndex in coinSpecific of the last txRequest
1005
+ unsignedTx.coinSpecific.should.hasOwnProperty('lastScanIndex');
1006
+ unsignedTx.coinSpecific.lastScanIndex.should.equal(3);
1007
+ });
1008
+ it('should throw error if all addresses have balance less than 1 ADA', async function () {
1009
+ sandBox.restore();
1010
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1011
+ callBack.withArgs('address_info', sinon.match.has('_addresses')).resolves({
1012
+ status: 200,
1013
+ body: [
1014
+ {
1015
+ balance: 500000,
1016
+ utxo_set: [
1017
+ {
1018
+ tx_hash: '8df8d41207980f9e21de698bd5d6c395c39e420f7de27f8539052dd34e3a28d6',
1019
+ tx_index: 0,
1020
+ value: 500000,
1021
+ },
1022
+ ],
1023
+ },
1024
+ ],
1025
+ });
1026
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1027
+ await basecoin
1028
+ .recoverConsolidations({
1029
+ userKey: resources_1.consolidationWrwUser.userKey,
1030
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1031
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1032
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1033
+ startingScanIndex: 1,
1034
+ endingScanIndex: 4,
1035
+ })
1036
+ .should.be.rejectedWith('Did not find an address with funds to recover.');
1037
+ });
1038
+ it('should build even if single address has no funds', async function () {
1039
+ const res = await basecoin.recoverConsolidations({
1040
+ userKey: resources_1.consolidationWrwUser.userKey,
1041
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1042
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1043
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1044
+ startingScanIndex: 1,
1045
+ endingScanIndex: 4,
1046
+ });
1047
+ res.should.not.be.empty();
1048
+ res.transactions.length.should.equal(2);
1049
+ });
1050
+ it('should build even if single address has insufficient funds', async function () {
1051
+ const res = await basecoin.recoverConsolidations({
1052
+ userKey: resources_1.consolidationWrwUser.userKey,
1053
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1054
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1055
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1056
+ startingScanIndex: 1,
1057
+ endingScanIndex: 4,
1058
+ });
1059
+ res.should.not.be.empty();
1060
+ res.transactions.length.should.equal(2);
1061
+ });
1062
+ });
1063
+ describe('Recover Transactions Failure:', () => {
1064
+ const destAddr = resources_1.address.address2;
1065
+ const sandBox = sinon.createSandbox();
1066
+ afterEach(function () {
1067
+ sandBox.restore();
1068
+ });
1069
+ it('should fail to recover due to not finding an address with funds', async function () {
1070
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1071
+ callBack
1072
+ .withArgs('address_info', sinon.match.has('_addresses'))
1073
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
1074
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1075
+ await basecoin
1076
+ .recover({
1077
+ userKey: resources_1.wrwUser.userKey,
1078
+ backupKey: resources_1.wrwUser.backupKey,
1079
+ bitgoKey: resources_1.wrwUser.bitgoKey,
1080
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
1081
+ recoveryDestination: destAddr,
1082
+ })
1083
+ .should.rejectedWith('Did not find address with funds to recover.');
1084
+ sandBox.assert.calledOnce(basecoin.getDataFromNode);
1085
+ });
1086
+ it('should fail to recover due to not having more than 1 ADA in funds', async function () {
1087
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1088
+ callBack
1089
+ .withArgs('address_info', sinon.match.has('_addresses'))
1090
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneSmallUTXO);
1091
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1092
+ await basecoin
1093
+ .recover({
1094
+ userKey: resources_1.wrwUser.userKey,
1095
+ backupKey: resources_1.wrwUser.backupKey,
1096
+ bitgoKey: resources_1.wrwUser.bitgoKey,
1097
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
1098
+ recoveryDestination: destAddr,
1099
+ })
1100
+ .should.rejectedWith('Insufficient funds to recover, minimum required is 1 ADA plus fees, got 834455 fees: 165545');
1101
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
1102
+ });
1103
+ });
1104
+ describe('Verify wallet address (isWalletAddress):', () => {
1105
+ const commonKeychain = 'ed312d0db4615688219c43231eb4b98d5883c0b44bcfef1956290555995ad68ef7c22917b4a8b69183864b83cc7028655cd7a70ef76d6948d809a15050054840';
1106
+ it('should verify a valid wallet address at index 0', async function () {
1107
+ const keychains = [
1108
+ {
1109
+ id: '1',
1110
+ commonKeychain: commonKeychain,
1111
+ type: 'tss',
1112
+ source: 'user',
1113
+ },
1114
+ {
1115
+ id: '2',
1116
+ commonKeychain: commonKeychain,
1117
+ type: 'tss',
1118
+ source: 'backup',
1119
+ },
1120
+ {
1121
+ id: '3',
1122
+ commonKeychain: commonKeychain,
1123
+ type: 'tss',
1124
+ source: 'bitgo',
1125
+ },
1126
+ ];
1127
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1128
+ const isValid = await basecoin.isWalletAddress({
1129
+ address,
1130
+ keychains,
1131
+ index: 0,
1132
+ });
1133
+ isValid.should.equal(true);
1134
+ });
1135
+ it('should fail to verify an address with wrong index', async function () {
1136
+ const keychains = [
1137
+ {
1138
+ id: '1',
1139
+ commonKeychain: commonKeychain,
1140
+ type: 'tss',
1141
+ source: 'user',
1142
+ },
1143
+ {
1144
+ id: '2',
1145
+ commonKeychain: commonKeychain,
1146
+ type: 'tss',
1147
+ source: 'backup',
1148
+ },
1149
+ {
1150
+ id: '3',
1151
+ commonKeychain: commonKeychain,
1152
+ type: 'tss',
1153
+ source: 'bitgo',
1154
+ },
1155
+ ];
1156
+ const isValid = await basecoin.isWalletAddress({
1157
+ address: 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq',
1158
+ keychains,
1159
+ index: 2,
1160
+ });
1161
+ isValid.should.equal(false);
1162
+ });
1163
+ it('should fail to verify a random address not from wallet', async function () {
1164
+ const keychains = [
1165
+ {
1166
+ id: '1',
1167
+ commonKeychain: commonKeychain,
1168
+ type: 'tss',
1169
+ source: 'user',
1170
+ },
1171
+ {
1172
+ id: '2',
1173
+ commonKeychain: commonKeychain,
1174
+ type: 'tss',
1175
+ source: 'backup',
1176
+ },
1177
+ {
1178
+ id: '3',
1179
+ commonKeychain: commonKeychain,
1180
+ type: 'tss',
1181
+ source: 'bitgo',
1182
+ },
1183
+ ];
1184
+ // Use a random valid ADA address not from this wallet
1185
+ const randomAddress = 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f';
1186
+ const isValid = await basecoin.isWalletAddress({
1187
+ address: randomAddress,
1188
+ keychains,
1189
+ index: 0,
1190
+ });
1191
+ isValid.should.equal(false);
1192
+ });
1193
+ it('should throw error for invalid address format', async function () {
1194
+ const keychains = [
1195
+ {
1196
+ id: '1',
1197
+ commonKeychain: commonKeychain,
1198
+ type: 'tss',
1199
+ source: 'user',
1200
+ },
1201
+ {
1202
+ id: '2',
1203
+ commonKeychain: commonKeychain,
1204
+ type: 'tss',
1205
+ source: 'backup',
1206
+ },
1207
+ {
1208
+ id: '3',
1209
+ commonKeychain: commonKeychain,
1210
+ type: 'tss',
1211
+ source: 'bitgo',
1212
+ },
1213
+ ];
1214
+ const invalidAddress = 'not_a_valid_address';
1215
+ await basecoin
1216
+ .isWalletAddress({
1217
+ address: invalidAddress,
1218
+ keychains,
1219
+ index: 0,
1220
+ })
1221
+ .should.be.rejectedWith('Invalid Cardano Address: not_a_valid_address');
1222
+ });
1223
+ it('should throw error when keychains are missing', async function () {
1224
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1225
+ await basecoin
1226
+ .isWalletAddress({
1227
+ address,
1228
+ keychains: [],
1229
+ index: 0,
1230
+ })
1231
+ .should.be.rejectedWith('missing required param keychains');
1232
+ });
1233
+ it('should throw error when commonKeychain is missing', async function () {
1234
+ const keychains = [
1235
+ {
1236
+ id: '1',
1237
+ type: 'tss',
1238
+ source: 'user',
1239
+ // commonKeychain is missing
1240
+ },
1241
+ ];
1242
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1243
+ await basecoin
1244
+ .isWalletAddress({
1245
+ address,
1246
+ keychains,
1247
+ index: 0,
1248
+ })
1249
+ .should.be.rejectedWith('missing required param commonKeychain');
1250
+ });
1251
+ it('should throw error when keychains have mismatched commonKeychains', async function () {
1252
+ const keychains = [
1253
+ {
1254
+ id: '1',
1255
+ commonKeychain: commonKeychain,
1256
+ type: 'tss',
1257
+ source: 'user',
1258
+ },
1259
+ {
1260
+ id: '2',
1261
+ commonKeychain: 'differentKeychain1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
1262
+ type: 'tss',
1263
+ source: 'backup',
1264
+ },
1265
+ ];
1266
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1267
+ await basecoin
1268
+ .isWalletAddress({
1269
+ address,
1270
+ keychains,
1271
+ index: 0,
1272
+ })
1273
+ .should.be.rejectedWith('all keychains must have the same commonKeychain for MPC coins');
1274
+ });
1275
+ it('should verify address when derivedFromParentWithSeed is present', async function () {
1276
+ const derivedFromParentWithSeed = 'testDerivationSeed123';
1277
+ const keychains = [
1278
+ {
1279
+ id: '1',
1280
+ commonKeychain: commonKeychain,
1281
+ derivedFromParentWithSeed: derivedFromParentWithSeed,
1282
+ type: 'tss',
1283
+ source: 'user',
1284
+ },
1285
+ {
1286
+ id: '2',
1287
+ commonKeychain: commonKeychain,
1288
+ derivedFromParentWithSeed: derivedFromParentWithSeed,
1289
+ type: 'tss',
1290
+ source: 'backup',
1291
+ },
1292
+ {
1293
+ id: '3',
1294
+ commonKeychain: commonKeychain,
1295
+ derivedFromParentWithSeed: derivedFromParentWithSeed,
1296
+ type: 'tss',
1297
+ source: 'bitgo',
1298
+ },
1299
+ ];
1300
+ const { address: expectedAddress } = await basecoin.getAdaAddressAndAccountId({
1301
+ bitgoKey: commonKeychain,
1302
+ index: 0,
1303
+ seed: derivedFromParentWithSeed,
1304
+ });
1305
+ const isValid = await basecoin.isWalletAddress({
1306
+ address: expectedAddress,
1307
+ keychains,
1308
+ index: 0,
1309
+ });
1310
+ isValid.should.equal(true);
1311
+ });
1312
+ it('should fail verification when derivedFromParentWithSeed is missing but address was created with seed', async function () {
1313
+ const derivedFromParentWithSeed = 'testDerivationSeed123';
1314
+ const { address: addressWithSeed } = await basecoin.getAdaAddressAndAccountId({
1315
+ bitgoKey: commonKeychain,
1316
+ index: 0,
1317
+ seed: derivedFromParentWithSeed,
1318
+ });
1319
+ const keychainsWithoutSeed = [
1320
+ {
1321
+ id: '1',
1322
+ commonKeychain: commonKeychain,
1323
+ type: 'tss',
1324
+ source: 'user',
1325
+ },
1326
+ {
1327
+ id: '2',
1328
+ commonKeychain: commonKeychain,
1329
+ type: 'tss',
1330
+ source: 'backup',
1331
+ },
1332
+ {
1333
+ id: '3',
1334
+ commonKeychain: commonKeychain,
1335
+ type: 'tss',
1336
+ source: 'bitgo',
1337
+ },
1338
+ ];
1339
+ const isValid = await basecoin.isWalletAddress({
1340
+ address: addressWithSeed,
1341
+ keychains: keychainsWithoutSeed,
1342
+ index: 0,
1343
+ });
1344
+ isValid.should.equal(false);
1345
+ });
1346
+ });
1347
+ describe('Verify token consolidation transaction:', () => {
1348
+ it('should fail to verify a spoofed token consolidation transaction with incorrect address', async () => {
1349
+ const consolidationTx = {
1350
+ txRequestId: '4fdd0cae-2563-43b1-b5cf-94865158ca10',
1351
+ walletId: '63068ed4efa63a000877f02fd4b0fa6d',
1352
+ txHex: '84a400818258204bd0f991c1532cffe31d4a10db492b43175ec326765b6b29ceee598df2b61f470001818258390087379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c87379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c1a05f359ff021a00028701031a024972e1a10081825820bbacb13431b99208e6e8cdbf710147feaf06a39d71565e60b411ce9e4fa3f137584001a4ab8236563f69ff309e5786e8f39c629ed57676c692159cb2e0494c9e663355384c13c749d04c17a80ba2a45cc127df480fc64a43199a772f11acd5b14a0ff5f6',
1353
+ feeInfo: {
1354
+ fee: 10000,
1355
+ feeString: '10000',
1356
+ },
1357
+ txInfo: {
1358
+ inputs: [
1359
+ {
1360
+ address: '8iLa26KSbdpBUzNK7uYq8FvyuyA5h4k4erDHsDcPbHus',
1361
+ value: 2.0173228e10,
1362
+ valueString: '20173228000',
1363
+ },
1364
+ {
1365
+ address: '8P2kX7Tyh9eS3RKdaBhqbEtQGAX58DXzL7mhDQABGX2d',
1366
+ value: 10000,
1367
+ valueString: '10000',
1368
+ },
1369
+ ],
1370
+ minerFee: '10000',
1371
+ outputs: [
1372
+ {
1373
+ address: 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f',
1374
+ coinName: 'tada:usdt',
1375
+ enterprise: {
1376
+ $oid: '5553ba8ae7a5c77006719661',
1377
+ },
1378
+ enterprises: [
1379
+ {
1380
+ $oid: '5553ba8ae7a5c77006719661',
1381
+ },
1382
+ ],
1383
+ value: 2.0173228e10,
1384
+ valueString: '20173228000',
1385
+ wallet: {
1386
+ $oid: '62f4c3720d92c50008257eb5',
1387
+ },
1388
+ walletType: 'hot',
1389
+ wallets: [
1390
+ {
1391
+ $oid: '62f4c3720d92c50008257eb5',
1392
+ },
1393
+ ],
1394
+ },
1395
+ ],
1396
+ payGoFee: '0',
1397
+ spendAmount: '20173228000',
1398
+ spendAmounts: [
1399
+ {
1400
+ amountString: '20173228000',
1401
+ coinName: 'tada:usdt',
1402
+ },
1403
+ ],
1404
+ type: 'Send',
1405
+ },
1406
+ consolidateId: '6712d7fda6de4906d658c04aebbf8f9b',
1407
+ coin: 'tada',
1408
+ };
1409
+ // Mock the wallet with a different address than the transaction's output
1410
+ const mockedWallet = {
1411
+ coinSpecific: () => {
1412
+ return {
1413
+ rootAddress: 'addr_test1qqnnvptrc3rec64q2n9jh572ncu5wvdtt8uvg4g3aj96s5dwu9nj70mlahzglm9939uevupsmj8dcdqv25d5n5r8vw8sn7prey',
1414
+ };
1415
+ },
1416
+ };
1417
+ await basecoin
1418
+ .verifyTransaction({
1419
+ txParams: {},
1420
+ txPrebuild: consolidationTx,
1421
+ wallet: mockedWallet,
1422
+ verification: {
1423
+ consolidationToBaseAddress: true,
1424
+ },
1425
+ })
1426
+ .should.be.rejectedWith('tx outputs does not match with expected address');
1427
+ });
1428
+ });
1429
+ });
1430
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2FkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUgsaUNBQWtDO0FBQ2xDLG1DQUFxQztBQUNyQyw2Q0FBK0I7QUFDL0IsbURBQStEO0FBQy9ELGlEQUF3RDtBQUN4RCw0Q0FZc0I7QUFDdEIsMENBQTRCO0FBQzVCLHNGQUF3RTtBQUN4RSxtQ0FBK0M7QUFDL0MsdUNBQTRDO0FBQzVDLDBFQUFrRjtBQUNsRixvREFBNEI7QUFDNUIsbURBQXNEO0FBQ3RELGdEQUF3QjtBQUV4QixRQUFRLENBQUMsS0FBSyxFQUFFO0lBQ2QsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3ZCLE1BQU0sU0FBUyxHQUFHLEdBQUcsR0FBRyxRQUFRLENBQUM7SUFDakMsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksUUFBUSxDQUFDO0lBQ2IsSUFBSSxhQUFhLENBQUM7SUFDbEIsSUFBSSxXQUFXLENBQUM7SUFFaEIsTUFBTSxVQUFVLEdBQUc7UUFDakIsS0FBSyxFQUFFLGlCQUFLLENBQUMsVUFBVTtRQUN2QixNQUFNLEVBQUUsRUFBRTtLQUNYLENBQUM7SUFFRixNQUFNLFFBQVEsR0FBRztRQUNmLFVBQVUsRUFBRTtZQUNWO2dCQUNFLE9BQU8sRUFBRSxpQkFBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPO2dCQUNyQyxNQUFNLEVBQUUsU0FBUzthQUNsQjtZQUNEO2dCQUNFLE9BQU8sRUFBRSxpQkFBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPO2dCQUNyQyxNQUFNLEVBQUUsV0FBVzthQUNwQjtTQUNGO0tBQ0YsQ0FBQztJQUVGLE1BQU0sc0JBQXNCLEdBQUc7UUFDN0IsWUFBWSxFQUFFLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxLQUFL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QkFDRCxJQUFJLEVBQUUsTUFBTTtpQkFDYjtnQkFDRCxhQUFhLEVBQUUsa0NBQWtDO2dCQUNqRCxJQUFJLEVBQUUsTUFBTTthQUNiLENBQUM7WUFFRix5RUFBeUU7WUFDekUsTUFBTSxZQUFZLEdBQUc7Z0JBQ25CLFlBQVksRUFBRSxHQUFHLEVBQUU7b0JBQ2pCLE9BQU87d0JBQ0wsV0FBVyxFQUNULDhHQUE4RztxQkFDakgsQ0FBQztnQkFDSixDQUFDO2FBQ0YsQ0FBQztZQUVGLE1BQU0sUUFBUTtpQkFDWCxpQkFBaUIsQ0FBQztnQkFDakIsUUFBUSxFQUFFLEVBQUU7Z0JBQ1osVUFBVSxFQUFFLGVBQWU7Z0JBQzNCLE1BQU0sRUFBRSxZQUFZO2dCQUNwQixZQUFZLEVBQUU7b0JBQ1osMEJBQTBCLEVBQUUsSUFBSTtpQkFDakM7YUFDRixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDL0UsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuXG5pbXBvcnQgc2hvdWxkID0gcmVxdWlyZSgnc2hvdWxkJyk7XG5pbXBvcnQgeyByYW5kb21CeXRlcyB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvQVBJLCBlbmNyeXB0IH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWFwaSc7XG5pbXBvcnQge1xuICBhZGRyZXNzLFxuICBjb25zb2xpZGF0aW9uV3J3VXNlcixcbiAgZW5kcG9pbnRSZXNwb25zZXMsXG4gIGVudGVycHJpc2VBY2NvdW50cyBhcyBhY2NvdW50cyxcbiAgb3ZjUmVzcG9uc2UsXG4gIG92Y1Jlc3BvbnNlMixcbiAgcHJpdmF0ZUtleXMsXG4gIHB1YmxpY0tleXMsXG4gIHJhd1R4LFxuICB0ZXN0bmV0VVRYTyxcbiAgd3J3VXNlcixcbn0gZnJvbSAnLi4vcmVzb3VyY2VzJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCAqIGFzIENhcmRhbm9XYXNtIGZyb20gJ0BlbXVyZ28vY2FyZGFuby1zZXJpYWxpemF0aW9uLWxpYi1ub2RlanMnO1xuaW1wb3J0IHsgQWRhLCBLZXlQYWlyLCBUYWRhIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vc3JjL2xpYic7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblR5cGUgfSBmcm9tICcuLi8uLi8uLi9zZGstY29yZS9zcmMvYWNjb3VudC1saWIvYmFzZUNvaW4vZW51bSc7XG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBjb21tb24sIFdhbGxldCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuXG5kZXNjcmliZSgnQURBJywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBjb2luTmFtZSA9ICdhZGEnO1xuICBjb25zdCB0Y29pbk5hbWUgPSAndCcgKyBjb2luTmFtZTtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBiYXNlY29pbjtcbiAgbGV0IG5ld1R4UHJlYnVpbGQ7XG4gIGxldCBuZXdUeFBhcmFtcztcblxuICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgIHR4SGV4OiByYXdUeC51bnNpZ25lZFR4LFxuICAgIHR4SW5mbzoge30sXG4gIH07XG5cbiAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgcmVjaXBpZW50czogW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiByYXdUeC5vdXRwdXRBZGRyZXNzMS5hZGRyZXNzLFxuICAgICAgICBhbW91bnQ6ICc1MDAwMDAwJyxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6IHJhd1R4Lm91dHB1dEFkZHJlc3MyLmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogJzI0ODMyOTE1MCcsXG4gICAgICB9LFxuICAgIF0sXG4gIH07XG5cbiAgY29uc3QgdHJhbnNhY3Rpb25FeHBsYW5hdGlvbiA9IHtcbiAgICBkaXNwbGF5T3JkZXI6IFsnaWQnLCAnb3V0cHV0QW1vdW50JywgJ2NoYW5nZUFtb3VudCcsICdvdXRwdXRzJywgJ2NoYW5nZU91dHB1dHMnLCAnZmVlJywgJ3R5cGUnXSxcbiAgICBpZDogJ2Y0OGY2ZWEwZjc1ZjNmOTQyODU1Y2MwZWRmMjllODFlMWUwNzI0ZTc1ZjVkYjhhMTU3NWIxNjZmYjIwMjE3NmMnLFxuICAgIG91dHB1dHM6IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczpcbiAgICAgICAgICAnYWRkcl90ZXN0MXFxbm52cHRyYzNyZWM2NHEybjlqaDU3Mm5jdTV3dmR0dDh1dmc0ZzNhajk2czVkd3U5bmo3MG1sYWh6Z2xtOTkzOXVldnVwc21qOGRjZHF2MjVkNW41cjh2dzhzbjdwcmV5JyxcbiAgICAgICAgYW1vdW50OiAnNzgyMzEyMScsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBhZGRyZXNzOiAnYWRkcl90ZXN0MXZyOHJha202NnJjZnY0ZmN4cXlrZzVsZjB5djdsc3lrOW12YXB4MzY5anB2dGNnZmN1azdmJyxcbiAgICAgICAgYW1vdW50OiAnMTMwNDE3MjknLFxuICAgICAgfSxcbiAgICBdLFxuICAgIG91dHB1dEFtb3VudDogJzIwODY0ODUwJyxcbiAgICBjaGFuZ2VPdXRwdXRzOiBbXSxcbiAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICBmZWU6IHsgZmVlOiAnMTY3MTczJyB9LFxuICAgIHR5cGU6ICdUcmFuc2ZlcicsXG4gICAgY2VydGlmaWNhdGVzOiBbXSxcbiAgICB3aXRoZHJhd2FsczogW10sXG4gICAgcGxlZGdlRGV0YWlsczogdW5kZWZpbmVkLFxuICB9O1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKGNvaW5OYW1lLCBBZGEuY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJpdGdvLnNhZmVSZWdpc3Rlcih0Y29pbk5hbWUsIFRhZGEuY3JlYXRlSW5zdGFuY2UpO1xuICAgIGJhc2Vjb2luID0gYml0Z28uY29pbih0Y29pbk5hbWUpO1xuICAgIG5ld1R4UHJlYnVpbGQgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gXy5jbG9uZURlZXAodHhQcmVidWlsZCk7XG4gICAgfTtcbiAgICBuZXdUeFBhcmFtcyA9ICgpID0+IHtcbiAgICAgIHJldHVybiBfLmNsb25lRGVlcCh0eFBhcmFtcyk7XG4gICAgfTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBpbnN0YW50aWF0ZSB0aGUgY29pbicsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgbG9jYWxCYXNlY29pbiA9IGJpdGdvLmNvaW4odGNvaW5OYW1lKTtcbiAgICBsb2NhbEJhc2Vjb2luLnNob3VsZC5iZS5hbi5pbnN0YW5jZW9mKFRhZGEpO1xuICAgIGxvY2FsQmFzZWNvaW4uZ2V0Q2hhaW4oKS5zaG91bGQuZXF1YWwodGNvaW5OYW1lKTtcbiAgICBsb2NhbEJhc2Vjb2luLmdldEZ1bGxOYW1lKCkuc2hvdWxkLmVxdWFsKCdUZXN0bmV0IEFkYScpO1xuXG4gICAgbG9jYWxCYXNlY29pbiA9IGJpdGdvLmNvaW4oY29pbk5hbWUpO1xuICAgIGxvY2FsQmFzZWNvaW4uc2hvdWxkLmJlLmFuLmluc3RhbmNlb2YoQWRhKTtcbiAgICBsb2NhbEJhc2Vjb2luLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKGNvaW5OYW1lKTtcbiAgICBsb2NhbEJhc2Vjb2luLmdldEZ1bGxOYW1lKCkuc2hvdWxkLmVxdWFsKCdDYXJkYW5vIEFEQScpO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2lnbiBNZXNzYWdlJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgYmUgcGVyZm9ybWVkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qga2V5UGFpciA9IG5ldyBLZXlQYWlyKCk7XG4gICAgICBjb25zdCBtZXNzYWdlVG9TaWduID0gQnVmZmVyLmZyb20ocmFuZG9tQnl0ZXMoMzIpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBiYXNlY29pbi5zaWduTWVzc2FnZShrZXlQYWlyLmdldEtleXMoKSwgbWVzc2FnZVRvU2lnbik7XG4gICAgICBrZXlQYWlyLnZlcmlmeVNpZ25hdHVyZShtZXNzYWdlVG9TaWduLCBVaW50OEFycmF5LmZyb20oc2lnbmF0dXJlKSkuc2hvdWxkLmVxdWFscyhmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgd2l0aCBtaXNzaW5nIHByaXZhdGUga2V5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qga2V5UGFpciA9IG5ldyBLZXlQYWlyKHtcbiAgICAgICAgcHViOiAnNzc4ODMyN2M2OTVkY2E0YjNlNjQ5YTBkYjQ1YmMzZTcwM2EyYzY3NDI4ZmNlMzYwZTYxODAwY2M0MjQ4ZjRmNycsXG4gICAgICB9KS5nZXRLZXlzKCk7XG4gICAgICBjb25zdCBtZXNzYWdlVG9TaWduID0gQnVmZmVyLmZyb20ocmFuZG9tQnl0ZXMoMzIpKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBhd2FpdCBiYXNlY29pbi5zaWduTWVzc2FnZShrZXlQYWlyLCBtZXNzYWdlVG9TaWduKS5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIGtleSBwYWlyIG9wdGlvbnMnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1NpZ24gdHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBzaWduIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnbmVkID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiByYXdUeC51bnNpZ25lZFR4MixcbiAgICAgICAgfSxcbiAgICAgICAgcHViczogW3B1YmxpY0tleXMucHViS2V5MV0sXG4gICAgICAgIHBydjogcHJpdmF0ZUtleXMucHJ2S2V5NCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkLnR4SGV4LnNob3VsZC5lcXVhbChyYXdUeC5zaWduZWRUeDIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHNpZ24gdHJhbnNhY3Rpb24gd2l0aCBhbiBpbnZhbGlkIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IHJhd1R4LnVuc2lnbmVkVHgyLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcHViczogW3B1YmxpY0tleXMucHViS2V5MV0sXG4gICAgICAgICAgcHJ2OiBwcml2YXRlS2V5cy5wcnZLZXkyLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGUubWVzc2FnZSwgJ1ByaXZhdGUga2V5IGNhbm5vdCBzaWduIHRoZSB0cmFuc2FjdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGJ1aWxkIHRyYW5zYWN0aW9uIHdpdGggbWlzc2luZyBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiByYXdUeC51bnNpZ25lZFR4LFxuICAgICAgICAgICAga2V5OiBhY2NvdW50cy5hY2NvdW50MS5wdWJsaWNLZXksXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwcnY6IGFjY291bnRzLmFjY291bnQxLnNlY3JldEtleSxcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHNob3VsZC5ub3RFcXVhbChlLCBudWxsKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0dlbmVyYXRlIHdhbGxldCBrZXkgcGFpcjogJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUga2V5IHBhaXInLCAoKSA9PiB7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcigpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrcC5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQcnYoa3AucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleSBwYWlyIGZyb20gc2VlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHNlZWQgPSBCdWZmZXIuZnJvbSgnOWQ2MWIxOWRlZmZkNWE2MGJhODQ0YWY0OTJlYzJjYzQ0NDQ5YzU2OTdiMzI2OTE5NzAzYmFjMDMxY2FlN2Y2MCcsICdoZXgnKTtcbiAgICAgIGNvbnN0IGtwID0gYmFzZWNvaW4uZ2VuZXJhdGVLZXlQYWlyKHNlZWQpO1xuICAgICAgYmFzZWNvaW4uaXNWYWxpZFB1YihrcC5wdWIpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQcnYoa3AucHJ2KS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWZXJpZnkgdHJhbnNhY3Rpb246ICcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHVuc2lnbmVkIHRyYW5zYWN0aW9uIGluIGhleCBlbmNvZGluZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgdmVyaWZpY2F0aW9uIH0pO1xuICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3VjY2VlZCB0byB2ZXJpZnkgc2lnbmVkIHRyYW5zYWN0aW9uIGluIGhleCBlbmNvZGluZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7XG4gICAgICAgIHR4SGV4OiByYXdUeC5zaWduZWRUeCxcbiAgICAgICAgdHhJbmZvOiB7fSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIGNvbnN0IHZlcmlmaWNhdGlvbiA9IHt9O1xuXG4gICAgICBjb25zdCBpc1RyYW5zYWN0aW9uVmVyaWZpZWQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB2ZXJpZmljYXRpb24gfSk7XG4gICAgICBpc1RyYW5zYWN0aW9uVmVyaWZpZWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSB0cmFuc2FjdGlvbnMgd2hlbiBoYXZlIGRpZmZlcmVudCByZWNpcGllbnRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IG5ld1R4UHJlYnVpbGQoKTtcblxuICAgICAgY29uc3QgdHhQYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnOWY3YjA2NzVkYjU5ZDE5YjRiZDljOGM3MmVhYWJiYTc1YTk4NjNkMDJiMzAxMTViOGIzYzNjYTVjMjBmMDI1NCcsXG4gICAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICc5ZjdiMDY3NWRiNTlkMTliNGJkOWM4YzcyZWFhYmJhNzVhOTg2M2QwMmIzMDExNWI4YjNjM2NhNWMyMGYwMjU0JyxcbiAgICAgICAgICAgIGFtb3VudDogJzIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHZlcmlmaWNhdGlvbiB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnY2Fubm90IGZpbmQgcmVjaXBpZW50IGluIGV4cGVjdGVkIG91dHB1dCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgd2hlbiBpbnB1dCBgcmVjaXBpZW50c2AgaXMgYWJzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB2YWxpZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCB9KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmeSB3aGVuIHR4SGV4IGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICB0eFBhcmFtcy5yZWNpcGllbnRzID0gdW5kZWZpbmVkO1xuICAgICAgY29uc3QgdHhQcmVidWlsZCA9IHt9O1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSlcbiAgICAgICAgLnNob3VsZC5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcmVxdWlyZWQgdHggcHJlYnVpbGQgcHJvcGVydHkgdHhIZXgnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc3VjY2VlZCB0byB2ZXJpZnkgdHJhbnNhY3Rpb25zIHdoZW4gcmVjaXBpZW50cyBoYXMgZXh0cmEgZGF0YScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICB0eFBhcmFtcy5kYXRhID0gJ2RhdGEnO1xuXG4gICAgICBjb25zdCB2YWxpZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCB9KTtcbiAgICAgIHZhbGlkVHJhbnNhY3Rpb24uc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBjb25zb2xpZGF0aW9uIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY29uc29saWRhdGlvblR4ID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogJzFiNWM3OWM1LWFiN2MtNGY0Ny05MTJiLWRlNmE5NWZiMDc3OScsXG4gICAgICAgIHdhbGxldElkOiAnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJyxcbiAgICAgICAgdHhIZXg6XG4gICAgICAgICAgJzg0YTQwMDgxODI1ODIwZGI0NmM3Yzc2ZWE1NGZlYzJjYTBhMmY5NGI3N2EyMzg5MzFhOGRjZTIzODdjOTlhMTJiMDhkZDhhYWMyMWM0ZjAwMDE4MTgyNTgzOTAwNDYwMWZjMDE2YWMzODU4MDkxNmQzNTIwYmM3NmI2NTkyOTgxNTYwMDg3MzhkMzQ3YWE5MzE0MmY0NjAxZmMwMTZhYzM4NTgwOTE2ZDM1MjBiYzc2YjY1OTI5ODE1NjAwODczOGQzNDdhYTkzMTQyZjFhM2I5ODQzNTcwMjFhMDAwMjg2YTkwMzFhMDYwZTM3ZWVhMGY1ZjYnLFxuICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgZmVlOiAxNjU1NDUsXG4gICAgICAgICAgZmVlU3RyaW5nOiAnMTY1NTQ1JyxcbiAgICAgICAgfSxcbiAgICAgICAgdHhJbmZvOiB7XG4gICAgICAgICAgbWluZXJGZWU6ICcxNjU1NDUnLFxuICAgICAgICAgIHNwZW5kQW1vdW50OiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICBzcGVuZEFtb3VudHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY29pbk5hbWU6ICd0YWRhJyxcbiAgICAgICAgICAgICAgYW1vdW50U3RyaW5nOiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBwYXlHb0ZlZTogJzAnLFxuICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWRkcmVzczpcbiAgICAgICAgICAgICAgICAnYWRkcl90ZXN0MXFwcnFybHFwZHRwY3RxeTNkNTZqcDBya2tldmpucTJrcXpybjM1Njg0MmYzZ3Q2eHE4N3F6Nmtyc2txZnptZjR5ejc4ZGRqZTl4cTR2cXk4OHJmNTAyNW56c2hzamRtZzJzJyxcbiAgICAgICAgICAgICAgdmFsdWU6IDk5OTgzNDQ1NSxcbiAgICAgICAgICAgICAgd2FsbGV0OiAnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJyxcbiAgICAgICAgICAgICAgd2FsbGV0czogWyc2NGZhMzFhOTRkYjY1YTAwMDdjOTY5MWInXSxcbiAgICAgICAgICAgICAgZW50ZXJwcmlzZTogJzYyY2M1OWI3Mjc0NDNhMDAwNzA4OTAzMycsXG4gICAgICAgICAgICAgIGVudGVycHJpc2VzOiBbJzYyY2M1OWI3Mjc0NDNhMDAwNzA4OTAzMyddLFxuICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYScsXG4gICAgICAgICAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgICAgICAgICB3YWxsZXRUeXBlczogWydob3QnXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBpbnB1dHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwMDAwMDAsXG4gICAgICAgICAgICAgIGFkZHJlc3M6XG4gICAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcWx6eGZsN3RsZ3A5OTl4NGE3MzM0cGNoeWNwa2s3MnB5a3JzcjNtcnlsM3lqNnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc3ZwZ2w4dycsXG4gICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnMTAwMDAwMDAwMCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdHlwZTogJzAnLFxuICAgICAgICB9LFxuICAgICAgICBjb25zb2xpZGF0ZUlkOiAnNjhiOWZjMTg1NTgwMDZhYWI1Mzc4NTYxNWZlYTdjMjgnLFxuICAgICAgICBjb2luOiAndGFkYScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBtb2NrZWRXYWxsZXQgPSB7XG4gICAgICAgIGNvaW5TcGVjaWZpYzogKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByb290QWRkcmVzczpcbiAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcHJxcmxxcGR0cGN0cXkzZDU2anAwcmtrZXZqbnEya3F6cm4zNTY4NDJmM2d0NnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc2pkbWcycycsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGlzVmVyaWZpZWQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHt9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IGNvbnNvbGlkYXRpb25UeCxcbiAgICAgICAgICB3YWxsZXQ6IG1vY2tlZFdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHtcbiAgICAgICAgICAgIGNvbnNvbGlkYXRpb25Ub0Jhc2VBZGRyZXNzOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBpc1ZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgYXNzZXJ0LmZhaWwoJ1RyYW5zYWN0aW9uIHNob3VsZCBwYXNzIHZlcmlmaWNhdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBzcG9uc29yZWQgY29uc29saWRhdGlvbiB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNvbnNvbGlkYXRpb25UeCA9IHtcbiAgICAgICAgdHhSZXF1ZXN0SWQ6ICcxYjVjNzljNS1hYjdjLTRmNDctOTEyYi1kZTZhOTVmYjA3NzknLFxuICAgICAgICB3YWxsZXRJZDogJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYicsXG4gICAgICAgIHR4SGV4OlxuICAgICAgICAgICc4NGE0MDA4MjgyNTgyMDIyN2Y2NWQyMGFjNmU0OTYwMmQ3OWM2MjNjNTE5MTFlYWQ4MjQyMzVlMDFlYjJhMWU3ZTMzYTcyZjA3NDdjYmIwMDgyNTgyMDIyN2Y2NWQyMGFjNmU0OTYwMmQ3OWM2MjNjNTE5MTFlYWQ4MjQyMzVlMDFlYjJhMWU3ZTMzYTcyZjA3NDdjYmIwMjAxODI4MjU4MzkwMDIyMDk4MjcwYTVjMTljOWZiNzA2ZGNlMGU3ZTQ1NjZiMjM0ZWM1ZjAwMTA2MjNjZDYzZjE5OGFkMjIwOTgyNzBhNWMxOWM5ZmI3MDZkY2UwZTdlNDU2NmIyMzRlYzVmMDAxMDYyM2NkNjNmMTk4YWQxYTAwOTg5NjgwODI1ODFkNjBjZjkwZjlmYjAyYzg4YmFkM2M1Mjk0ZDkwNTg3NDU4YzRmMTYwYTJkYjI2YmE4YWYzZGEyNTViMTFhMDVkNDJmYjgwMjFhMDAwMmE0OTEwMzFhMDZkOGMwNDhhMGY1ZjYnLFxuICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgZmVlOiAxNjU1NDUsXG4gICAgICAgICAgZmVlU3RyaW5nOiAnMTY1NTQ1JyxcbiAgICAgICAgfSxcbiAgICAgICAgdHhJbmZvOiB7XG4gICAgICAgICAgbWluZXJGZWU6ICcxNjU1NDUnLFxuICAgICAgICAgIHNwZW5kQW1vdW50OiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICBzcGVuZEFtb3VudHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY29pbk5hbWU6ICd0YWRhJyxcbiAgICAgICAgICAgICAgYW1vdW50U3RyaW5nOiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBwYXlHb0ZlZTogJzAnLFxuICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWRkcmVzczpcbiAgICAgICAgICAgICAgICAnYWRkcl90ZXN0MXFwcnFybHFwZHRwY3RxeTNkNTZqcDBya2tldmpucTJrcXpybjM1Njg0MmYzZ3Q2eHE4N3F6Nmtyc2txZnptZjR5ejc4ZGRqZTl4cTR2cXk4OHJmNTAyNW56c2hzamRtZzJzJyxcbiAgICAgICAgICAgICAgdmFsdWU6IDk5OTgzNDQ1NSxcbiAgICAgICAgICAgICAgd2FsbGV0OiAnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJyxcbiAgICAgICAgICAgICAgd2FsbGV0czogWyc2NGZhMzFhOTRkYjY1YTAwMDdjOTY5MWInXSxcbiAgICAgICAgICAgICAgZW50ZXJwcmlzZTogJzYyY2M1OWI3Mjc0NDNhMDAwNzA4OTAzMycsXG4gICAgICAgICAgICAgIGVudGVycHJpc2VzOiBbJzYyY2M1OWI3Mjc0NDNhMDAwNzA4OTAzMyddLFxuICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYScsXG4gICAgICAgICAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgICAgICAgICB3YWxsZXRUeXBlczogWydob3QnXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBpbnB1dHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwMDAwMDAsXG4gICAgICAgICAgICAgIGFkZHJlc3M6XG4gICAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcWx6eGZsN3RsZ3A5OTl4NGE3MzM0cGNoeWNwa2s3MnB5a3JzcjNtcnlsM3lqNnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc3ZwZ2w4dycsXG4gICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnMTAwMDAwMDAwMCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdHlwZTogJzAnLFxuICAgICAgICAgIGZlZUFkZHJlc3M6ICdhZGRyX3Rlc3QxdnI4ZXA3MG1xdHlnaHRmdTIyMmRqcHY4Z2t4eTc5czI5a2V4aDI5MDhrMzl0dmdlMDJkNWonLFxuICAgICAgICB9LFxuICAgICAgICBjb25zb2xpZGF0ZUlkOiAnNjhiOWZjMTg1NTgwMDZhYWI1Mzc4NTYxNWZlYTdjMjgnLFxuICAgICAgICBjb2luOiAndGFkYScsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBtb2NrZWRXYWxsZXQgPSB7XG4gICAgICAgIGNvaW5TcGVjaWZpYzogKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByb290QWRkcmVzczpcbiAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcTNxbnFuczVocWVlOGFocW13d3BlbHkyZTRqeG5rOTdxcXN2ZzdkdjBjZTN0ZnpweHA4cGZ3cG5qMG13cGt1dXJuN2c0bnR5ZDh2dHVxcHFjM3U2Y2wzbnprc3ZnZ3U4MicsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGlzVmVyaWZpZWQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHt9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IGNvbnNvbGlkYXRpb25UeCxcbiAgICAgICAgICB3YWxsZXQ6IG1vY2tlZFdhbGxldCxcbiAgICAgICAgICB2ZXJpZmljYXRpb246IHtcbiAgICAgICAgICAgIGNvbnNvbGlkYXRpb25Ub0Jhc2VBZGRyZXNzOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBpc1ZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgYXNzZXJ0LmZhaWwoJ1RyYW5zYWN0aW9uIHNob3VsZCBwYXNzIHZlcmlmaWNhdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHNpZ24gYSBzcG9vZmVkIGNvbnNvbGlkYXRpb24gdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBTZXQgdXAgd2FsbGV0IGRhdGFcbiAgICAgIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgICAgIGlkOiAnNWIzNDI1MmYxYmYzNDk5MzBlMzQwMjBhMDAwMDAwMDAnLFxuICAgICAgICBjb2luOiAndGFkYScsXG4gICAgICAgIGtleXM6IFtcbiAgICAgICAgICAnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc1MDAwMDAwMDAnLFxuICAgICAgICAgICc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzYwMDAwMDAwMCcsXG4gICAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NzAwMDAwMDAwJyxcbiAgICAgICAgXSxcbiAgICAgICAgY29pblNwZWNpZmljOiB7XG4gICAgICAgICAgcm9vdEFkZHJlc3M6XG4gICAgICAgICAgICAnYWRkcl90ZXN0MXFwcnFybHFwZHRwY3RxeTNkNTZqcDBya2tldmpucTJrcXpybjM1Njg0MmYzZ3Q2eHE4N3F6Nmtyc2txZnptZjR5ejc4ZGRqZTl4cTR2cXk4OHJmNTAyNW56c2hzamRtZzJzJyxcbiAgICAgICAgfSxcbiAgICAgICAgbXVsdGlzaWdUeXBlOiAndHNzJyxcbiAgICAgIH07XG4gICAgICBjb25zdCBmYWtlUHJ2ID0gZW5jcnlwdCgncGFzc3dvcmQnLCAncHJ2Jyk7XG5cbiAgICAgIGNvbnN0IHdhbGxldE9iaiA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2Vjb2luLCB3YWxsZXREYXRhKTtcbiAgICAgIGNvbnN0IGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1snbW9jayddLnVyaTtcblxuICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgLmdldCgnL2FwaS92Mi90YWRhL2tleS81YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzUwMDAwMDAwMCcpXG4gICAgICAgIC5yZXBseSgyMDAsIFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBlbmNyeXB0ZWRQcnY6IGZha2VQcnYsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG5cbiAgICAgIC8vIE1vY2sgdGhlIEFQSSByZXNwb25zZSBmb3IgYnVpbGRBY2NvdW50Q29uc29saWRhdGlvbnNcbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KCcvYXBpL3YyL3RhZGEvd2FsbGV0LzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwL2NvbnNvbGlkYXRlQWNjb3VudC9idWlsZCcpXG4gICAgICAgIC5yZXBseSgyMDAsIFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eFJlcXVlc3RJZDogJzFiNWM3OWM1LWFiN2MtNGY0Ny05MTJiLWRlNmE5NWZiMDc3OScsXG4gICAgICAgICAgICB3YWxsZXRJZDogJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYicsXG4gICAgICAgICAgICB0eEhleDpcbiAgICAgICAgICAgICAgJzg0YTQwMDgxODI1ODIwZGI0NmM3Yzc2ZWE1NGZlYzJjYTBhMmY5NGI3N2EyMzg5MzFhOGRjZTIzODdjOTlhMTJiMDhkZDhhYWMyMWM0ZjAxMDE4MjgyNTgxZDYwMzNjMzc4Y2VlNDFiMmUxNWFjODQ4ZjdmNmYxZDJmNzgxNTVhYjEyZDkzYjcxM2RlODk4ZDg1NWYxYTAwOTg5NjgwODI1ODM5MDA0NjAxZmMwMTZhYzM4NTgwOTE2ZDM1MjBiYzc2YjY1OTI5ODE1NjAwODczOGQzNDdhYTkzMTQyZjQ2MDFmYzAxNmFjMzg1ODA5MTZkMzUyMGJjNzZiNjU5Mjk4MTU2MDA4NzM4ZDM0N2FhOTMxNDJmMWIwMDAwMDAwMjE3YWNlYmU5MDIxYTAwMDI4ZGI1MDMxYTA2MGUzYjQxYTBmNWY2JyxcbiAgICAgICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICAgICAgZmVlOiAxNjU1NDUsXG4gICAgICAgICAgICAgIGZlZVN0cmluZzogJzE2NTU0NScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHhJbmZvOiB7XG4gICAgICAgICAgICAgIG1pbmVyRmVlOiAnMTY1NTQ1JyxcbiAgICAgICAgICAgICAgc3BlbmRBbW91bnQ6ICc5OTk4MzQ0NTUnLFxuICAgICAgICAgICAgICBzcGVuZEFtb3VudHM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBjb2luTmFtZTogJ3RhZGEnLFxuICAgICAgICAgICAgICAgICAgYW1vdW50U3RyaW5nOiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICBwYXlHb0ZlZTogJzAnLFxuICAgICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgYWRkcmVzczpcbiAgICAgICAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcHJxcmxxcGR0cGN0cXkzZDU2anAwcmtrZXZqbnEya3F6cm4zNTY4NDJmM2d0NnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc2pkbWcycycsXG4gICAgICAgICAgICAgICAgICB2YWx1ZTogOTk5ODM0NDU1LFxuICAgICAgICAgICAgICAgICAgd2FsbGV0OiAnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJyxcbiAgICAgICAgICAgICAgICAgIHdhbGxldHM6IFsnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJ10sXG4gICAgICAgICAgICAgICAgICBlbnRlcnByaXNlOiAnNjJjYzU5YjcyNzQ0M2EwMDA3MDg5MDMzJyxcbiAgICAgICAgICAgICAgICAgIGVudGVycHJpc2VzOiBbJzYyY2M1OWI3Mjc0NDNhMDAwNzA4OTAzMyddLFxuICAgICAgICAgICAgICAgICAgdmFsdWVTdHJpbmc6ICc5OTk4MzQ0NTUnLFxuICAgICAgICAgICAgICAgICAgY29pbk5hbWU6ICd0YWRhJyxcbiAgICAgICAgICAgICAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgICAgICAgICAgICAgd2FsbGV0VHlwZXM6IFsnaG90J10sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgaW5wdXRzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwMDAwMDAsXG4gICAgICAgICAgICAgICAgICBhZGRyZXNzOlxuICAgICAgICAgICAgICAgICAgICAnYWRkcl90ZXN0MXFxbHp4Zmw3dGxncDk5OXg0YTczMzRwY2h5Y3BrazcycHlrcnNyM21yeWwzeWo2eHE4N3F6Nmtyc2txZnptZjR5ejc4ZGRqZTl4cTR2cXk4OHJmNTAyNW56c2hzdnBnbDh3JyxcbiAgICAgICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnMTAwMDAwMDAwMCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgdHlwZTogJzAnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2OGI5ZmMxODU1ODAwNmFhYjUzNzg1NjE1ZmVhN2MyOCcsXG4gICAgICAgICAgICBjb2luOiAndGFkYScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG5cbiAgICAgIC8vIENhbGwgdGhlIGZ1bmN0aW9uIHRvIHRlc3RcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgYXdhaXQgd2FsbGV0T2JqLnNlbmRBY2NvdW50Q29uc29saWRhdGlvbnMoe1xuICAgICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogJ3Bhc3N3b3JkJyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG1lc3NhZ2U6ICd0eCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgYWRkcmVzcycsXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFeHBsYWluIFRyYW5zYWN0aW9uczonLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBleHBsYWluIGFuIHVuc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwbGFpbmVkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHJhd1R4LnVuc2lnbmVkVHgyLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjb25zb2xlLmxvZyhleHBsYWluZWRUcmFuc2FjdGlvbik7XG4gICAgICBleHBsYWluZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHRyYW5zYWN0aW9uRXhwbGFuYXRpb24pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGV4cGxhaW4gdHJhbnNhY3Rpb24gd2l0aCBtaXNzaW5nIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDoge30sXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGVycm9yLm1lc3NhZ2UsICdJbnZhbGlkIHRyYW5zYWN0aW9uJyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gZXhwbGFpbiB0cmFuc2FjdGlvbiB3aXRoIHdyb25nIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGJhc2Vjb2luLmV4cGxhaW5UcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6ICdpbnZhbGlkVHhIZXgnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGVycm9yLm1lc3NhZ2UsICdJbnZhbGlkIHRyYW5zYWN0aW9uJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdQYXJzZSBSYXcgVHJhbnNhY3Rpb25zJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcGFyc2Ugc3Rha2luZyBwbGVkZ2UgdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmF3VHgudW5zaWduZWROZXdQbGVkZ2VUeCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdQbGVkZ2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBzdGFraW5nIGFjdGl2YXRpb24gdHgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmF3VHgudW5zaWduZWRTdGFraW5nQWN0aXZlVHgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBzdGFraW5nIGRlYWN0aXZhdGlvbiB0eCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbihyYXdUeC51bnNpZ25lZFN0YWtpbmdEZWFjdGl2ZVR4KTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlYWN0aXZhdGUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGFyc2UgVHJhbnNhY3Rpb25zOicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHBhcnNlIGFuIHVuc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyc2VkVHJhbnNhY3Rpb24gPSBhd2FpdCBiYXNlY29pbi5wYXJzZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiByYXdUeC51bnNpZ25lZFR4MixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBwYXJzZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHRyYW5zYWN0aW9uRXhwbGFuYXRpb24pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhIHNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcnNlZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4ucGFyc2VUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogcmF3VHguc2lnbmVkVHgyLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIHBhcnNlZFRyYW5zYWN0aW9uLnNob3VsZC5kZWVwRXF1YWwodHJhbnNhY3Rpb25FeHBsYW5hdGlvbik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgcGFyc2UgYSBzaWduZWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24gd2hlbiBleHBsYWluVHJhbnNhY3Rpb24gcmVzcG9uc2UgaXMgdW5kZWZpbmVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3R1YiA9IHNpbm9uLnN0dWIoQWRhLnByb3RvdHlwZSwgJ2V4cGxhaW5UcmFuc2FjdGlvbicpO1xuICAgICAgc3R1Yi5yZXNvbHZlcyh1bmRlZmluZWQpO1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnBhcnNlVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiByYXdUeC5zaWduZWRUeCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgICAgc3R1Yi5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWNvdmVyIFRyYW5zYWN0aW9uczonLCAoKSA9PiB7XG4gICAgY29uc3QgZGVzdEFkZHIgPSBhZGRyZXNzLmFkZHJlc3MyO1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgbGV0IGNhbGxCYWNrOiBzaW5vbi5TaW5vblN0dWI7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxCYWNrID0gc2FuZEJveC5zdHViKEFkYS5wcm90b3R5cGUsICdnZXREYXRhRnJvbU5vZGUnIGFzIGtleW9mIEFkYSk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHtcbiAgICAgICAgICBfYWRkcmVzc2VzOiBbd3J3VXNlci53YWxsZXRBZGRyZXNzMF0sXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8pO1xuICAgICAgY2FsbEJhY2sud2l0aEFyZ3MoJ3RpcCcpLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLnRpcEluZm9SZXNwb25zZSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZEJveC5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRha2UgT1ZDIG91dHB1dCBhbmQgZ2VuZXJhdGUgYSBzaWduZWQgc3dlZXAgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSBvdmNSZXNwb25zZTtcbiAgICAgIGNvbnN0IHJlY292ZXJ5VHhuID0gYXdhaXQgYmFzZWNvaW4uY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24ocGFyYW1zKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1swXS5zZXJpYWxpemVkVHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnODRhNDAwODE4MjU4MjA0YmQwZjk5MWMxNTMyY2ZmZTMxZDRhMTBkYjQ5MmI0MzE3NWVjMzI2NzY1YjZiMjljZWVlNTk4ZGYyYjYxZjQ3MDAwMTgxODI1ODM5MDA4NzM3OWViYzU1MzNlYmU2MjE5NjNjOTE1YzNjYmM1ZjA4NTM3ZmNkY2E0YWY4ZjhhZTA4ZWQ0Yzg3Mzc5ZWJjNTUzM2ViZTYyMTk2M2M5MTVjM2NiYzVmMDg1MzdmY2RjYTRhZjhmOGFlMDhlZDRjMWEwNWYzNTlmZjAyMWEwMDAyODcwMTAzMWEwMjQ5NzJlMWExMDA4MTgyNTgyMGJiYWNiMTM0MzFiOTkyMDhlNmU4Y2RiZjcxMDE0N2ZlYWYwNmEzOWQ3MTU2NWU2MGI0MTFjZTllNGZhM2YxMzc1ODQwMDFhNGFiODIzNjU2M2Y2OWZmMzA5ZTU3ODZlOGYzOWM2MjllZDU3Njc2YzY5MjE1OWNiMmUwNDk0YzllNjYzMzU1Mzg0YzEzYzc0OWQwNGMxN2E4MGJhMmE0NWNjMTI3ZGY0ODBmYzY0YTQzMTk5YTc3MmYxMWFjZDViMTRhMGZmNWY2J1xuICAgICAgKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1swXS5zY2FuSW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgICAgcmVjb3ZlcnlUeG4ubGFzdFNjYW5JbmRleC5zaG91bGQuZXF1YWwoMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRha2UgY29uc29saWRhdGlvbiBPVkMgb3V0cHV0IGFuZCBnZW5lcmF0ZSBtdWx0aXBsZSBzaWduZWQgc3dlZXAgdHJhbnNhY3Rpb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyYW1zID0gb3ZjUmVzcG9uc2UyO1xuICAgICAgY29uc3QgcmVjb3ZlcnlUeG4gPSBhd2FpdCBiYXNlY29pbi5jcmVhdGVCcm9hZGNhc3RhYmxlU3dlZXBUcmFuc2FjdGlvbihwYXJhbXMpO1xuICAgICAgcmVjb3ZlcnlUeG4udHJhbnNhY3Rpb25zWzBdLnNlcmlhbGl6ZWRUeC5zaG91bGQuZXF1YWwoXG4gICAgICAgICc4NGE0MDA4MTgyNTgyMDNlNjJlNWVlOGIxMjAxMmM0Yjk0OWY5Nzc3YjcyMTY1MjM5YmIyMTQ2YWU4YjA3OGI0ZDFjNWNhOGQzMTY4ZTMwMDAxODE4MjU4MzkwMGJhZjU1ZWJjZjlhZGExYjhlY2IxNjQwODgwZmJhNTRkMjgxNzY5MGYxMmIzYTEwNmFmZDA4MDA0YmFmNTVlYmNmOWFkYTFiOGVjYjE2NDA4ODBmYmE1NGQyODE3NjkwZjEyYjNhMTA2YWZkMDgwMDQxYTAwOTYwZjdmMDIxYTAwMDI4NzAxMDMxYTAyNTBmN2VhYTEwMDgxODI1ODIwNTAwZTBkNzI1YTViYTNhMzA2ZGEzNTAzZGZlNTdiOGExNDA2OGEwOWI2MWIzNmVjMDY4ZmNmOGNmNWMzOTFkZTU4NDBjODM2Y2U2ZDMyNjJkNTY1NDcwNmVhMDY3MjE1MjJkM2I3NWY2ZDU0NTI0NTA0N2E3YmU3NDYzNjI5ZDg4YjNmNDI2NGI5OTVmNTkxZGY1MmJkZmZjZjA5ZGExZTZhYjllODhkZTM3MTRjNmUyZWMxOTYxNzg2Y2YxYzU4NmEwN2Y1ZjYnXG4gICAgICApO1xuICAgICAgcmVjb3ZlcnlUeG4udHJhbnNhY3Rpb25zWzBdLnNjYW5JbmRleC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMV0uc2VyaWFsaXplZFR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzg0YTQwMDgxODI1ODIwMjljMTBhY2YwZTA4Zjk1MjMzMjVjODgyNDM1NjVhZjZiMzIyNzQ5OTIxODljMTE1MzkwM2M0MTBiZWQ3YzJjNzAwMDE4MTgyNTgzOTAwYmFmNTVlYmNmOWFkYTFiOGVjYjE2NDA4ODBmYmE1NGQyODE3NjkwZjEyYjNhMTA2YWZkMDgwMDRiYWY1NWViY2Y5YWRhMWI4ZWNiMTY0MDg4MGZiYTU0ZDI4MTc2OTBmMTJiM2ExMDZhZmQwODAwNDFhMDA5NjBmN2YwMjFhMDAwMjg3MDEwMzFhMDI1MGY3ZWFhMTAwODE4MjU4MjA2Mjc3MGIyMjRiZDMxNGJjNTI2ZmJkNmE5NGU5MDgyZmI2NDU4YzQyNWU2ZTA5YmFkNzQwMDRkZDg5N2U5NjIzNTg0MDM4NDI1NDRmMmZmMjhiZTA1NGViN2M3OTk3YmMzMDNiMWUyNTFlYjEzYTQxODAyYzgyMzE4ZTU5MmJiMjRlYWEzMTk3YzQ1MGU3OTdjYzg1NTlmMDM1NmNkNWNkZDFhYjVlYjgwYzUxNzNlMzRlOWUxZDE3Mzc1MzNhODk1MjBjZjVmNidcbiAgICAgICk7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMV0uc2NhbkluZGV4LnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1syXS5zZXJpYWxpemVkVHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnODRhNDAwODE4MjU4MjBkZDE0MGYxMzNkODY1ZTFiYjU2NDJlNzA4ZmU2ODViZjc2MDFkNzFkMGM5OTUxMWU1ZDU1MmRhN2Y4YmQxMGZmMDAwMTgxODI1ODM5MDBiYWY1NWViY2Y5YWRhMWI4ZWNiMTY0MDg4MGZiYTU0ZDI4MTc2OTBmMTJiM2ExMDZhZmQwODAwNGJhZjU1ZWJjZjlhZGExYjhlY2IxNjQwODgwZmJhNTRkMjgxNzY5MGYxMmIzYTEwNmFmZDA4MDA0MWEwMDk2MGY3ZjAyMWEwMDAyODcwMTAzMWEwMjUwZjdlYWExMDA4MTgyNTgyMDUzYjRiYjc0YWEzOGFkZDQ1OGRhZmM4MTUzZjBhYTgyNjZhY2FkNTkzMjJiODc3Y2E5YzIzYzVkMzg3Mzc3OWQ1ODQwZTk0Y2U3ODk2OTU3ZDA5NGM2YmFmYmYyZWMxMGRmNWViYjBmMWQyYTI3YTdlMzFmMmQ0NWM1MzFmYjY4N2VkZDZjNGQzM2Y4ZTliOTljNzY5MmI2ZmFjNmQ4Mzk5YmQ4ZmQ0NzY0MWJhYWU5YmJiNjlmNTE4ZDQyYWQxMTcxMGFmNWY2J1xuICAgICAgKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1syXS5zY2FuSW5kZXguc2hvdWxkLmVxdWFsKDMpO1xuICAgICAgcmVjb3ZlcnlUeG4udHJhbnNhY3Rpb25zWzNdLnNlcmlhbGl6ZWRUeC5zaG91bGQuZXF1YWwoXG4gICAgICAgICc4NGE0MDA4MTgyNTgyMDE1YTFkNmRiNWQzZjU5MmFhMWNkYTE4NWI2MzU5Y2EwZTI5MjFjM2M1MTk1OWY2NDIyMmE2YjdkOTVkMzM5MjMwMDAxODE4MjU4MzkwMGJhZjU1ZWJjZjlhZGExYjhlY2IxNjQwODgwZmJhNTRkMjgxNzY5MGYxMmIzYTEwNmFmZDA4MDA0YmFmNTVlYmNmOWFkYTFiOGVjYjE2NDA4ODBmYmE1NGQyODE3NjkwZjEyYjNhMTA2YWZkMDgwMDQxYTAwOTYwZjdmMDIxYTAwMDI4NzAxMDMxYTAyNTBmN2VhYTEwMDgxODI1ODIwNjAwZjg2Y2EyMmQ2NzBmMGE5OTBhZGU0ZTg4MmMwNWU2NTQzNDMyNjM0OTQ3MzVhMzE1MTdkZTA4MTk2NzY3MzU4NDBmZTE5OWY4ZTI0N2E0Y2ZhYmZlYjRmOWNiNTc0YWEzNTczOWEwYWE5ODg2MGVlMGE4NWQ3MjBjNGFiNGZlY2ZhYzdiNDUwNGRmMzEwYjNlNGJlYTA0NzExZjYwNjUyZDRhOGNmNWViNDE4MTcyOTNiOGQyOTk3N2ZlNjk1ZjcwNGY1ZjYnXG4gICAgICApO1xuICAgICAgcmVjb3ZlcnlUeG4udHJhbnNhY3Rpb25zWzNdLnNjYW5JbmRleC5zaG91bGQuZXF1YWwoNCk7XG4gICAgICByZWNvdmVyeVR4bi5sYXN0U2NhbkluZGV4LnNob3VsZC5lcXVhbCgyMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgYSB0eG4gZm9yIG5vbi1iaXRnbyByZWNvdmVyaWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IHdyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiB3cndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IHdyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdEFkZHIsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHNhbmRCb3guYXNzZXJ0LmNhbGxlZFR3aWNlKGJhc2Vjb2luLmdldERhdGFGcm9tTm9kZSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbihyZXMuc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgY29uc3QgZmVlID0gTnVtYmVyKHR4LmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5vdXRwdXRzWzBdLmFkZHJlc3MsIGRlc3RBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHR4SnNvbi5vdXRwdXRzWzBdLmFtb3VudCkgKyBmZWUsIHRlc3RuZXRVVFhPLlVUWE9fMS52YWx1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgYSB0eG4gZm9yIHVuc2lnbmVkIHN3ZWVwIHJlY292ZXJpZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgYml0Z29LZXk6IHdyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHNhbmRCb3guYXNzZXJ0LmNhbGxlZFR3aWNlKGJhc2Vjb2luLmdldERhdGFGcm9tTm9kZSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbihyZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICBjb25zdCBmZWUgPSBOdW1iZXIodHguZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1swXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLm91dHB1dHNbMF0uYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIodHhKc29uLm91dHB1dHNbMF0uYW1vdW50KSArIGZlZSwgdGVzdG5ldFVUWE8uVVRYT18xLnZhbHVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBBREEgcGx1cyB0b2tlbiBVVFhPcyAtIHRva2VuIGFuZCBBREEgYm90aCBhcHBlYXIgaW4gb3V0cHV0cyAodW5zaWduZWQgc3dlZXApJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7IF9hZGRyZXNzZXM6IFt3cndVc2VyLndhbGxldEFkZHJlc3MwXSB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5BREFBbmRUb2tlblVUWE9zKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHggPSByZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeDtcbiAgICAgIHVuc2lnbmVkVHguc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcblxuICAgICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24oYmFzZWNvaW4pO1xuICAgICAgdHguZnJvbVJhd1RyYW5zYWN0aW9uKHVuc2lnbmVkVHguc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgICB0eEpzb24uaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1sxXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT19UT0tFTi50eF9oYXNoKTtcblxuICAgICAgdHhKc29uLm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcblxuICAgICAgY29uc3QgdG9rZW5Qb2xpY3lJZCA9ICcyNTMzY2NhNmViNDIwNzZlMTQ0ZTlmMjc3MmMzOTBkZWNlOWZjZTE3M2JjMzhjNzIyOTRiMzkyNCc7XG4gICAgICBjb25zdCB0b2tlbkVuY29kZWRBc3NldE5hbWUgPSAnNTc0MTU0NDU1Mic7XG4gICAgICBjb25zdCB0b2tlblF1YW50aXR5ID0gJzExMSc7XG4gICAgICBjb25zdCBtaW5BREFGb3JUb2tlbiA9IDE1MDAwMDA7XG5cbiAgICAgIGNvbnN0IHRva2VuT3V0cHV0ID0gdHhKc29uLm91dHB1dHMuZmluZCgobykgPT4gby5tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIHNob3VsZC5leGlzdCh0b2tlbk91dHB1dCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHRva2VuT3V0cHV0IS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0b2tlbk91dHB1dCEuYW1vdW50KSwgbWluQURBRm9yVG9rZW4pO1xuICAgICAgY29uc3QgZXhwZWN0ZWRQb2xpY3lJZCA9IENhcmRhbm9XYXNtLlNjcmlwdEhhc2guZnJvbV9ieXRlcyhCdWZmZXIuZnJvbSh0b2tlblBvbGljeUlkLCAnaGV4JykpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRBc3NldE5hbWUgPSBDYXJkYW5vV2FzbS5Bc3NldE5hbWUubmV3KEJ1ZmZlci5mcm9tKHRva2VuRW5jb2RlZEFzc2V0TmFtZSwgJ2hleCcpKTtcbiAgICAgICh0b2tlbk91dHB1dCEubXVsdGlBc3NldHMgYXMgQ2FyZGFub1dhc20uTXVsdGlBc3NldClcbiAgICAgICAgLmdldF9hc3NldChleHBlY3RlZFBvbGljeUlkLCBleHBlY3RlZEFzc2V0TmFtZSlcbiAgICAgICAgLnRvX3N0cigpXG4gICAgICAgIC5zaG91bGQuZXF1YWwodG9rZW5RdWFudGl0eSk7XG5cbiAgICAgIGNvbnN0IGFkYU91dHB1dCA9IHR4SnNvbi5vdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgPT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QoYWRhT3V0cHV0KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoYWRhT3V0cHV0IS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBjb25zdCBmZWUgPSBOdW1iZXIodHguZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBjb25zdCB0b3RhbEJhbGFuY2UgPSB0ZXN0bmV0VVRYTy5VVFhPXzEudmFsdWUgKyB0ZXN0bmV0VVRYTy5VVFhPX1RPS0VOLnZhbHVlO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIoYWRhT3V0cHV0IS5hbW91bnQpLCB0b3RhbEJhbGFuY2UgLSBtaW5BREFGb3JUb2tlbiAtIGZlZSk7XG5cbiAgICAgIGNvbnN0IGV4cGxhaW5lZCA9IHR4LmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuICAgICAgY29uc3QgZXhwbGFpbmVkVG9rZW5PdXRwdXQgPSBleHBsYWluZWQub3V0cHV0cy5maW5kKChvKSA9PiBvLmFtb3VudCA9PT0gbWluQURBRm9yVG9rZW4udG9TdHJpbmcoKSk7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwbGFpbmVkVG9rZW5PdXRwdXQpO1xuXG4gICAgICAvLyBpbnB1dHMgYW5kIG91dHB1dHMgaW4gcGFyc2VkVHggc2hvdWxkIGNhcnJ5IG11bHRpQXNzZXRzXG4gICAgICBjb25zdCBwYXJzZWRUeElucHV0cyA9IHJlcy50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnBhcnNlZFR4LmlucHV0cyBhcyB7XG4gICAgICAgIGFkZHJlc3M6IHN0cmluZztcbiAgICAgICAgdmFsdWVTdHJpbmc6IHN0cmluZztcbiAgICAgICAgbXVsdGlBc3NldHM/OiB7IHBvbGljeV9pZDogc3RyaW5nOyBhc3NldF9uYW1lOiBzdHJpbmc7IHF1YW50aXR5OiBzdHJpbmcgfVtdO1xuICAgICAgfVtdO1xuICAgICAgcGFyc2VkVHhJbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHNob3VsZC5leGlzdChwYXJzZWRUeElucHV0c1swXS5tdWx0aUFzc2V0cyk7XG4gICAgICBwYXJzZWRUeElucHV0c1swXS5tdWx0aUFzc2V0cyEubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMhWzBdLnBvbGljeV9pZCwgdG9rZW5Qb2xpY3lJZCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFR4SW5wdXRzWzBdLm11bHRpQXNzZXRzIVswXS5hc3NldF9uYW1lLCB0b2tlbkVuY29kZWRBc3NldE5hbWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeElucHV0c1swXS5tdWx0aUFzc2V0cyFbMF0ucXVhbnRpdHksIHRva2VuUXVhbnRpdHkpO1xuXG4gICAgICBjb25zdCBwYXJzZWRUeE91dHB1dHMgPSByZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5vdXRwdXRzIGFzIHtcbiAgICAgICAgYWRkcmVzczogc3RyaW5nO1xuICAgICAgICB2YWx1ZVN0cmluZzogc3RyaW5nO1xuICAgICAgICBtdWx0aUFzc2V0cz86IHsgcG9saWN5X2lkOiBzdHJpbmc7IGFzc2V0X25hbWU6IHN0cmluZzsgcXVhbnRpdHk6IHN0cmluZyB9W107XG4gICAgICB9W107XG4gICAgICBjb25zdCBwYXJzZWRUb2tlbk91dHB1dCA9IHBhcnNlZFR4T3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzICE9PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZFRva2VuT3V0cHV0KTtcbiAgICAgIHBhcnNlZFRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyEubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIVswXS5wb2xpY3lfaWQsIHRva2VuUG9saWN5SWQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUb2tlbk91dHB1dCEubXVsdGlBc3NldHMhWzBdLmFzc2V0X25hbWUsIHRva2VuRW5jb2RlZEFzc2V0TmFtZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyFbMF0ucXVhbnRpdHksIHRva2VuUXVhbnRpdHkpO1xuICAgICAgLy8gcHVyZSBBREEgb3V0cHV0IHNob3VsZCBub3QgaGF2ZSBtdWx0aUFzc2V0c1xuICAgICAgY29uc3QgcGFyc2VkQWRhT3V0cHV0ID0gcGFyc2VkVHhPdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgPT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkQWRhT3V0cHV0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBBREEgcGx1cyB0b2tlbiBVVFhPcyAtIHRva2VuIGFuZCBBREEgYm90aCBhcHBlYXIgaW4gb3V0cHV0cyAoc2lnbmVkKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgeyBfYWRkcmVzc2VzOiBbd3J3VXNlci53YWxsZXRBZGRyZXNzMF0gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuQURBQW5kVG9rZW5VVFhPcyk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiB3cndVc2VyLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogd3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiB3cndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbihyZXMuc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgICB0eEpzb24uaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1sxXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT19UT0tFTi50eF9oYXNoKTtcblxuICAgICAgLy8gZXhwZWN0IDIgb3V0cHV0czogb25lIHRva2VuIG91dHB1dCArIG9uZSBBREEgY2hhbmdlIG91dHB1dCwgYm90aCBhdCBkZXN0QWRkclxuICAgICAgdHhKc29uLm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcblxuICAgICAgY29uc3QgdG9rZW5Qb2xpY3lJZCA9ICcyNTMzY2NhNmViNDIwNzZlMTQ0ZTlmMjc3MmMzOTBkZWNlOWZjZTE3M2JjMzhjNzIyOTRiMzkyNCc7XG4gICAgICBjb25zdCB0b2tlbkVuY29kZWRBc3NldE5hbWUgPSAnNTc0MTU0NDU1Mic7XG4gICAgICBjb25zdCB0b2tlblF1YW50aXR5ID0gJzExMSc7XG4gICAgICBjb25zdCBtaW5BREFGb3JUb2tlbiA9IDE1MDAwMDA7XG5cbiAgICAgIGNvbnN0IHRva2VuT3V0cHV0ID0gdHhKc29uLm91dHB1dHMuZmluZCgobykgPT4gby5tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIHNob3VsZC5leGlzdCh0b2tlbk91dHB1dCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHRva2VuT3V0cHV0IS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0b2tlbk91dHB1dCEuYW1vdW50KSwgbWluQURBRm9yVG9rZW4pO1xuICAgICAgY29uc3QgZXhwZWN0ZWRQb2xpY3lJZCA9IENhcmRhbm9XYXNtLlNjcmlwdEhhc2guZnJvbV9ieXRlcyhCdWZmZXIuZnJvbSh0b2tlblBvbGljeUlkLCAnaGV4JykpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRBc3NldE5hbWUgPSBDYXJkYW5vV2FzbS5Bc3NldE5hbWUubmV3KEJ1ZmZlci5mcm9tKHRva2VuRW5jb2RlZEFzc2V0TmFtZSwgJ2hleCcpKTtcbiAgICAgICh0b2tlbk91dHB1dCEubXVsdGlBc3NldHMgYXMgQ2FyZGFub1dhc20uTXVsdGlBc3NldClcbiAgICAgICAgLmdldF9hc3NldChleHBlY3RlZFBvbGljeUlkLCBleHBlY3RlZEFzc2V0TmFtZSlcbiAgICAgICAgLnRvX3N0cigpXG4gICAgICAgIC5zaG91bGQuZXF1YWwodG9rZW5RdWFudGl0eSk7XG5cbiAgICAgIGNvbnN0IGFkYU91dHB1dCA9IHR4SnNvbi5vdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgPT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QoYWRhT3V0cHV0KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoYWRhT3V0cHV0IS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBjb25zdCBmZWUgPSBOdW1iZXIodHguZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBjb25zdCB0b3RhbEJhbGFuY2UgPSB0ZXN0bmV0VVRYTy5VVFhPXzEudmFsdWUgKyB0ZXN0bmV0VVRYTy5VVFhPX1RPS0VOLnZhbHVlO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIoYWRhT3V0cHV0IS5hbW91bnQpLCB0b3RhbEJhbGFuY2UgLSBtaW5BREFGb3JUb2tlbiAtIGZlZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWNvdmVyIFRyYW5zYWN0aW9ucyBNdWx0aXBsZSBVVFhPOicsICgpID0+IHtcbiAgICBjb25zdCBkZXN0QWRkciA9IGFkZHJlc3MuYWRkcmVzczI7XG4gICAgY29uc3Qgc2FuZEJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY2FsbEJhY2sgPSBzYW5kQm94LnN0dWIoQWRhLnByb3RvdHlwZSwgJ2dldERhdGFGcm9tTm9kZScgYXMga2V5b2YgQWRhKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywge1xuICAgICAgICAgIF9hZGRyZXNzZXM6IFt3cndVc2VyLndhbGxldEFkZHJlc3MwXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuVHdvVVRYTyk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygndGlwJykucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMudGlwSW5mb1Jlc3BvbnNlKTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVjb3ZlciBhIHR4biBmb3Igbm9uLWJpdGdvIHJlY292ZXJpZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogd3J3VXNlci51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IHdyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogd3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogd3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbGVkVHdpY2UoYmFzZWNvaW4uZ2V0RGF0YUZyb21Ob2RlKTtcblxuICAgICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24oYmFzZWNvaW4pO1xuICAgICAgdHguZnJvbVJhd1RyYW5zYWN0aW9uKHJlcy5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICBjb25zdCBmZWUgPSBOdW1iZXIodHguZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1swXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1sxXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18yLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzFdLnRyYW5zYWN0aW9uX2luZGV4LCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaW5kZXgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24ub3V0cHV0c1swXS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0eEpzb24ub3V0cHV0c1swXS5hbW91bnQpICsgZmVlLCB0ZXN0bmV0VVRYTy5VVFhPXzEudmFsdWUgKyB0ZXN0bmV0VVRYTy5VVFhPXzIudmFsdWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciB1bnNpZ25lZCBzd2VlcCByZWNvdmVyaWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRUd2ljZShiYXNlY29pbi5nZXREYXRhRnJvbU5vZGUpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgY29uc3QgZmVlID0gTnVtYmVyKHR4LmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMV0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMi50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1sxXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18yLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLm91dHB1dHNbMF0uYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIodHhKc29uLm91dHB1dHNbMF0uYW1vdW50KSArIGZlZSwgdGVzdG5ldFVUWE8uVVRYT18xLnZhbHVlICsgdGVzdG5ldFVUWE8uVVRYT18yLnZhbHVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0J1aWxkIENvbnNvbGlkYXRpb24gUmVjb3ZlcmllczonLCAoKSA9PiB7XG4gICAgY29uc3QgYmFzZUFkZHIgPSBjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRBZGRyZXNzMDtcbiAgICBjb25zdCBzYW5kQm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7XG4gICAgICAgICAgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MxXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuWmVyb1VUWE8pO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7XG4gICAgICAgICAgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MyXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuT25lVVRYTyk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHtcbiAgICAgICAgICBfYWRkcmVzc2VzOiBbY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczNdLFxuICAgICAgICB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5PbmVVVFhPMik7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygndGlwJykucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMudGlwSW5mb1Jlc3BvbnNlKTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgc2lnbmVkIGNvbnNvbGlkYXRpb24gcmVjb3ZlcmllcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgIHVzZXJLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogY29uc29saWRhdGlvbldyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogY29uc29saWRhdGlvbldyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IGNvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDQsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMudHJhbnNhY3Rpb25zLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICByZXMubGFzdFNjYW5JbmRleC5zaG91bGQuZXF1YWwoMyk7XG4gICAgICBjb25zdCB0eG4xID0gcmVzLnRyYW5zYWN0aW9uc1swXTtcbiAgICAgIGNvbnN0IHR4MSA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eDEuZnJvbVJhd1RyYW5zYWN0aW9uKHR4bjEuc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbjEgPSB0eDEudG9Kc29uKCk7XG4gICAgICBjb25zdCBmZWUxID0gTnVtYmVyKHR4MS5leHBsYWluVHJhbnNhY3Rpb24oKS5mZWUuZmVlKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMS5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMS5pbnB1dHNbMF0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjEub3V0cHV0c1swXS5hZGRyZXNzLCBiYXNlQWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0eEpzb24xLm91dHB1dHNbMF0uYW1vdW50KSArIGZlZTEsIHRlc3RuZXRVVFhPLlVUWE9fMS52YWx1ZSk7XG5cbiAgICAgIGNvbnN0IHR4bjIgPSByZXMudHJhbnNhY3Rpb25zWzFdO1xuICAgICAgY29uc3QgdHgyID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4Mi5mcm9tUmF3VHJhbnNhY3Rpb24odHhuMi5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uMiA9IHR4Mi50b0pzb24oKTtcbiAgICAgIGNvbnN0IGZlZTIgPSBOdW1iZXIodHgyLmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24yLmlucHV0c1swXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18yLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24yLmlucHV0c1swXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18yLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMi5vdXRwdXRzWzBdLmFkZHJlc3MsIGJhc2VBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHR4SnNvbjIub3V0cHV0c1swXS5hbW91bnQpICsgZmVlMiwgdGVzdG5ldFVUWE8uVVRYT18yLnZhbHVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2tpcCBidWlsZGluZyBjb25zb2xpZGF0ZSB0cmFuc2FjdGlvbiBpZiBiYWxhbmNlIGlzIGVxdWFsIHRvIHplcm8nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgICB1c2VyS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogY29uc29saWRhdGlvbldyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICAgIGVuZGluZ1NjYW5JbmRleDogMixcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5yZWplY3RlZFdpdGgoJ0RpZCBub3QgZmluZCBhbiBhZGRyZXNzIHdpdGggZnVuZHMgdG8gcmVjb3Zlci4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgc3RhcnRpbmdTY2FuSW5kZXggaXMgbm90IGdlIHRvIDEnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgICB1c2VyS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogY29uc29saWRhdGlvbldyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogLTEsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICdJbnZhbGlkIHN0YXJ0aW5nIG9yIGVuZGluZyBpbmRleCB0byBzY2FuIGZvciBhZGRyZXNzZXMuIHN0YXJ0aW5nU2NhbkluZGV4OiAtMSwgZW5kaW5nU2NhbkluZGV4OiAxOS4nXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGlmIHNjYW4gZmFjdG9yIGlzIHRvbyBoaWdoJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogY29uc29saWRhdGlvbldyd1VzZXIuYml0Z29LZXksXG4gICAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgICAgZW5kaW5nU2NhbkluZGV4OiAzMDAsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICdJbnZhbGlkIHN0YXJ0aW5nIG9yIGVuZGluZyBpbmRleCB0byBzY2FuIGZvciBhZGRyZXNzZXMuIHN0YXJ0aW5nU2NhbkluZGV4OiAxLCBlbmRpbmdTY2FuSW5kZXg6IDMwMC4nXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHVuc2lnbmVkIGNvbnNvbGlkYXRpb24gcmVjb3ZlcmllcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgIHVzZXJLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogY29uc29saWRhdGlvbldyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogY29uc29saWRhdGlvbldyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IGNvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDQsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMudHJhbnNhY3Rpb25zLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHVuc2lnbmVkIGNvbnNvbGlkYXRpb24gcmVjb3ZlcmllcyBmb3IgV1JXIChBREEgb25seSkgYW5kIGFzc2VydCBidWlsZCByZXNwb25zZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50eFJlcXVlc3RzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG5cbiAgICAgIC8vIEFzc2VydCBmaXJzdCBjb25zb2xpZGF0aW9uIHR4UmVxdWVzdCBzdHJ1Y3R1cmVcbiAgICAgIGNvbnN0IHR4UmVxdWVzdDEgPSByZXMudHhSZXF1ZXN0c1swXTtcbiAgICAgIHR4UmVxdWVzdDEudHJhbnNhY3Rpb25zLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBjb25zdCB1bnNpZ25lZFR4MSA9IHR4UmVxdWVzdDEudHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICB1bnNpZ25lZFR4MS5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuICAgICAgdW5zaWduZWRUeDEuc2hvdWxkLmhhc093blByb3BlcnR5KCdwYXJzZWRUeCcpO1xuICAgICAgdW5zaWduZWRUeDEuc2hvdWxkLmhhc093blByb3BlcnR5KCdjb2luU3BlY2lmaWMnKTtcblxuICAgICAgLy8gRGVzZXJpYWxpemUgYW5kIHZlcmlmeSBpbnB1dHMvb3V0cHV0c1xuICAgICAgY29uc3QgdHgxID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4MS5mcm9tUmF3VHJhbnNhY3Rpb24odW5zaWduZWRUeDEuc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbjEgPSB0eDEudG9Kc29uKCk7XG4gICAgICBjb25zdCBmZWUxID0gTnVtYmVyKHR4MS5leHBsYWluVHJhbnNhY3Rpb24oKS5mZWUuZmVlKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMS5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMS5pbnB1dHNbMF0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjEub3V0cHV0c1swXS5hZGRyZXNzLCBiYXNlQWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0eEpzb24xLm91dHB1dHNbMF0uYW1vdW50KSArIGZlZTEsIHRlc3RuZXRVVFhPLlVUWE9fMS52YWx1ZSk7XG5cbiAgICAgIC8vIHBhcnNlZFR4IGlucHV0cy9vdXRwdXRzIG11c3QgYmUgcHJlc2VudCBhbmQgY2FycnkgY29ycmVjdCBhZGRyZXNzXG4gICAgICBjb25zdCBwYXJzZWRUeDFJbnB1dHMgPSB1bnNpZ25lZFR4MS5wYXJzZWRUeC5pbnB1dHM7XG4gICAgICBwYXJzZWRUeDFJbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVHgxSW5wdXRzWzBdLmFkZHJlc3MsIGNvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MyKTtcbiAgICAgIGNvbnN0IHBhcnNlZFR4MU91dHB1dHMgPSB1bnNpZ25lZFR4MS5wYXJzZWRUeC5vdXRwdXRzO1xuICAgICAgcGFyc2VkVHgxT3V0cHV0cy5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeDFPdXRwdXRzWzBdLmFkZHJlc3MsIGJhc2VBZGRyKTtcblxuICAgICAgLy8gQXNzZXJ0IHNlY29uZCBjb25zb2xpZGF0aW9uIHR4UmVxdWVzdCBzdHJ1Y3R1cmVcbiAgICAgIGNvbnN0IHR4UmVxdWVzdDIgPSByZXMudHhSZXF1ZXN0c1sxXTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHgyID0gdHhSZXF1ZXN0Mi50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeDtcbiAgICAgIHVuc2lnbmVkVHgyLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG5cbiAgICAgIGNvbnN0IHR4MiA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eDIuZnJvbVJhd1RyYW5zYWN0aW9uKHVuc2lnbmVkVHgyLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24yID0gdHgyLnRvSnNvbigpO1xuICAgICAgY29uc3QgZmVlMiA9IE51bWJlcih0eDIuZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjIuaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjIuaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2luZGV4LCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaW5kZXgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24yLm91dHB1dHNbMF0uYWRkcmVzcywgYmFzZUFkZHIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIodHhKc29uMi5vdXRwdXRzWzBdLmFtb3VudCkgKyBmZWUyLCB0ZXN0bmV0VVRYTy5VVFhPXzIudmFsdWUpO1xuXG4gICAgICAvLyBsYXN0U2NhbkluZGV4IG11c3QgYmUgc2V0IGluIGNvaW5TcGVjaWZpYyBvZiB0aGUgbGFzdCB0eFJlcXVlc3RcbiAgICAgIGNvbnN0IGxhc3RDb2luU3BlY2lmaWMgPSB1bnNpZ25lZFR4Mi5jb2luU3BlY2lmaWM7XG4gICAgICBsYXN0Q29pblNwZWNpZmljLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnbGFzdFNjYW5JbmRleCcpO1xuICAgICAgbGFzdENvaW5TcGVjaWZpYy5sYXN0U2NhbkluZGV4LnNob3VsZC5lcXVhbCgzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgdW5zaWduZWQgY29uc29saWRhdGlvbiByZWNvdmVyaWVzIGZvciBXUlcgKEFEQSArIFRva2VuKSBhbmQgYXNzZXJ0IGJ1aWxkIHJlc3BvbnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gT3ZlcnJpZGUgd2FsbGV0QWRkcmVzczIgdG8gcmV0dXJuIEFEQStUb2tlbiBVVFhPc1xuICAgICAgc2FuZEJveC5yZXN0b3JlKCk7XG4gICAgICBjb25zdCBjYWxsQmFjazIgPSBzYW5kQm94LnN0dWIoQWRhLnByb3RvdHlwZSwgJ2dldERhdGFGcm9tTm9kZScgYXMga2V5b2YgQWRhKTtcbiAgICAgIGNhbGxCYWNrMlxuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MxXSB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5aZXJvVVRYTyk7XG4gICAgICBjYWxsQmFjazJcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7IF9hZGRyZXNzZXM6IFtjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRBZGRyZXNzMl0gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuQURBQW5kVG9rZW5VVFhPcyk7XG4gICAgICBjYWxsQmFjazJcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7IF9hZGRyZXNzZXM6IFtjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRBZGRyZXNzM10gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuWmVyb1VUWE8pO1xuICAgICAgY2FsbEJhY2syLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCB0b2tlblBvbGljeUlkID0gJzI1MzNjY2E2ZWI0MjA3NmUxNDRlOWYyNzcyYzM5MGRlY2U5ZmNlMTczYmMzOGM3MjI5NGIzOTI0JztcbiAgICAgIGNvbnN0IHRva2VuRW5jb2RlZEFzc2V0TmFtZSA9ICc1NzQxNTQ0NTUyJztcbiAgICAgIGNvbnN0IHRva2VuUXVhbnRpdHkgPSAnMTExJztcbiAgICAgIGNvbnN0IG1pbkFEQUZvclRva2VuID0gMTUwMDAwMDtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgYml0Z29LZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJpdGdvS2V5LFxuICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgZW5kaW5nU2NhbkluZGV4OiA0LFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnR4UmVxdWVzdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgY29uc3QgdW5zaWduZWRUeCA9IHJlcy50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4O1xuICAgICAgdW5zaWduZWRUeC5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24odW5zaWduZWRUeC5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG5cbiAgICAgIC8vIFR3byBpbnB1dHM6IEFEQSBVVFhPICsgVG9rZW4gVVRYT1xuICAgICAgdHhKc29uLmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMV0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fVE9LRU4udHhfaGFzaCk7XG5cbiAgICAgIC8vIFR3byBvdXRwdXRzOiB0b2tlbiBvdXRwdXQgKHdpdGggbXVsdGlBc3NldHMpICsgcHVyZSBBREEgY2hhbmdlIHRvIGJhc2UgYWRkcmVzc1xuICAgICAgdHhKc29uLm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIGNvbnN0IHRva2VuT3V0cHV0ID0gdHhKc29uLm91dHB1dHMuZmluZCgobykgPT4gby5tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIHNob3VsZC5leGlzdCh0b2tlbk91dHB1dCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHRva2VuT3V0cHV0IS5hZGRyZXNzLCBiYXNlQWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0b2tlbk91dHB1dCEuYW1vdW50KSwgbWluQURBRm9yVG9rZW4pO1xuICAgICAgY29uc3QgZXhwZWN0ZWRQb2xpY3lJZCA9IENhcmRhbm9XYXNtLlNjcmlwdEhhc2guZnJvbV9ieXRlcyhCdWZmZXIuZnJvbSh0b2tlblBvbGljeUlkLCAnaGV4JykpO1xuICAgICAgY29uc3QgZXhwZWN0ZWRBc3NldE5hbWUgPSBDYXJkYW5vV2FzbS5Bc3NldE5hbWUubmV3KEJ1ZmZlci5mcm9tKHRva2VuRW5jb2RlZEFzc2V0TmFtZSwgJ2hleCcpKTtcbiAgICAgICh0b2tlbk91dHB1dCEubXVsdGlBc3NldHMgYXMgQ2FyZGFub1dhc20uTXVsdGlBc3NldClcbiAgICAgICAgLmdldF9hc3NldChleHBlY3RlZFBvbGljeUlkLCBleHBlY3RlZEFzc2V0TmFtZSlcbiAgICAgICAgLnRvX3N0cigpXG4gICAgICAgIC5zaG91bGQuZXF1YWwodG9rZW5RdWFudGl0eSk7XG5cbiAgICAgIGNvbnN0IGFkYU91dHB1dCA9IHR4SnNvbi5vdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgPT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QoYWRhT3V0cHV0KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoYWRhT3V0cHV0IS5hZGRyZXNzLCBiYXNlQWRkcik7XG4gICAgICBjb25zdCBmZWUgPSBOdW1iZXIodHguZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBjb25zdCB0b3RhbEJhbGFuY2UgPSB0ZXN0bmV0VVRYTy5VVFhPXzEudmFsdWUgKyB0ZXN0bmV0VVRYTy5VVFhPX1RPS0VOLnZhbHVlO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIoYWRhT3V0cHV0IS5hbW91bnQpLCB0b3RhbEJhbGFuY2UgLSBtaW5BREFGb3JUb2tlbiAtIGZlZSk7XG5cbiAgICAgIC8vIHBhcnNlZFR4IGlucHV0cyBtdXN0IGNhcnJ5IG11bHRpQXNzZXRzIGZvciB0aGUgdG9rZW4gVVRYT1xuICAgICAgY29uc3QgcGFyc2VkVHhJbnB1dHMgPSB1bnNpZ25lZFR4LnBhcnNlZFR4LmlucHV0cyBhcyB7XG4gICAgICAgIGFkZHJlc3M6IHN0cmluZztcbiAgICAgICAgdmFsdWVTdHJpbmc6IHN0cmluZztcbiAgICAgICAgbXVsdGlBc3NldHM/OiB7IHBvbGljeV9pZDogc3RyaW5nOyBhc3NldF9uYW1lOiBzdHJpbmc7IHF1YW50aXR5OiBzdHJpbmcgfVtdO1xuICAgICAgfVtdO1xuICAgICAgcGFyc2VkVHhJbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVHhJbnB1dHNbMF0uYWRkcmVzcywgY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczIpO1xuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZFR4SW5wdXRzWzBdLm11bHRpQXNzZXRzKTtcbiAgICAgIHBhcnNlZFR4SW5wdXRzWzBdLm11bHRpQXNzZXRzIS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeElucHV0c1swXS5tdWx0aUFzc2V0cyFbMF0ucG9saWN5X2lkLCB0b2tlblBvbGljeUlkKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMhWzBdLmFzc2V0X25hbWUsIHRva2VuRW5jb2RlZEFzc2V0TmFtZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFR4SW5wdXRzWzBdLm11bHRpQXNzZXRzIVswXS5xdWFudGl0eSwgdG9rZW5RdWFudGl0eSk7XG5cbiAgICAgIC8vIHBhcnNlZFR4IG91dHB1dHMgbXVzdCBjYXJyeSBtdWx0aUFzc2V0cyBmb3IgdGhlIHRva2VuIG91dHB1dFxuICAgICAgY29uc3QgcGFyc2VkVHhPdXRwdXRzID0gdW5zaWduZWRUeC5wYXJzZWRUeC5vdXRwdXRzIGFzIHtcbiAgICAgICAgYWRkcmVzczogc3RyaW5nO1xuICAgICAgICB2YWx1ZVN0cmluZzogc3RyaW5nO1xuICAgICAgICBtdWx0aUFzc2V0cz86IHsgcG9saWN5X2lkOiBzdHJpbmc7IGFzc2V0X25hbWU6IHN0cmluZzsgcXVhbnRpdHk6IHN0cmluZyB9W107XG4gICAgICB9W107XG4gICAgICBjb25zdCBwYXJzZWRUb2tlbk91dHB1dCA9IHBhcnNlZFR4T3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzICE9PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZFRva2VuT3V0cHV0KTtcbiAgICAgIHBhcnNlZFRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyEubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIVswXS5wb2xpY3lfaWQsIHRva2VuUG9saWN5SWQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUb2tlbk91dHB1dCEubXVsdGlBc3NldHMhWzBdLmFzc2V0X25hbWUsIHRva2VuRW5jb2RlZEFzc2V0TmFtZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyFbMF0ucXVhbnRpdHksIHRva2VuUXVhbnRpdHkpO1xuICAgICAgLy8gcHVyZSBBREEgb3V0cHV0IG11c3Qgbm90IGhhdmUgbXVsdGlBc3NldHNcbiAgICAgIGNvbnN0IHBhcnNlZEFkYU91dHB1dCA9IHBhcnNlZFR4T3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzID09PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZEFkYU91dHB1dCk7XG5cbiAgICAgIC8vIGxhc3RTY2FuSW5kZXggaW4gY29pblNwZWNpZmljIG9mIHRoZSBsYXN0IHR4UmVxdWVzdFxuICAgICAgdW5zaWduZWRUeC5jb2luU3BlY2lmaWMuc2hvdWxkLmhhc093blByb3BlcnR5KCdsYXN0U2NhbkluZGV4Jyk7XG4gICAgICB1bnNpZ25lZFR4LmNvaW5TcGVjaWZpYy5sYXN0U2NhbkluZGV4LnNob3VsZC5lcXVhbCgzKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgYWxsIGFkZHJlc3NlcyBoYXZlIGJhbGFuY2UgbGVzcyB0aGFuIDEgQURBJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgc2FuZEJveC5yZXN0b3JlKCk7XG4gICAgICBjb25zdCBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2sud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHNpbm9uLm1hdGNoLmhhcygnX2FkZHJlc3NlcycpKS5yZXNvbHZlcyh7XG4gICAgICAgIHN0YXR1czogMjAwLFxuICAgICAgICBib2R5OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYmFsYW5jZTogNTAwMDAwLFxuICAgICAgICAgICAgdXR4b19zZXQ6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6ICc4ZGY4ZDQxMjA3OTgwZjllMjFkZTY5OGJkNWQ2YzM5NWMzOWU0MjBmN2RlMjdmODUzOTA1MmRkMzRlM2EyOGQ2JyxcbiAgICAgICAgICAgICAgICB0eF9pbmRleDogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogNTAwMDAwLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygndGlwJykucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMudGlwSW5mb1Jlc3BvbnNlKTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogY29uc29saWRhdGlvbldyd1VzZXIuYml0Z29LZXksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDQsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdEaWQgbm90IGZpbmQgYW4gYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXIuJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGV2ZW4gaWYgc2luZ2xlIGFkZHJlc3MgaGFzIG5vIGZ1bmRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgZXZlbiBpZiBzaW5nbGUgYWRkcmVzcyBoYXMgaW5zdWZmaWNpZW50IGZ1bmRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXIgVHJhbnNhY3Rpb25zIEZhaWx1cmU6JywgKCkgPT4ge1xuICAgIGNvbnN0IGRlc3RBZGRyID0gYWRkcmVzcy5hZGRyZXNzMjtcbiAgICBjb25zdCBzYW5kQm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHJlY292ZXIgZHVlIHRvIG5vdCBmaW5kaW5nIGFuIGFkZHJlc3Mgd2l0aCBmdW5kcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKEFkYS5wcm90b3R5cGUsICdnZXREYXRhRnJvbU5vZGUnIGFzIGtleW9mIEFkYSk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHNpbm9uLm1hdGNoLmhhcygnX2FkZHJlc3NlcycpKVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5aZXJvVVRYTyk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygndGlwJykucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMudGlwSW5mb1Jlc3BvbnNlKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB3cndVc2VyLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiB3cndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogd3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiB3cndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdEFkZHIsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQucmVqZWN0ZWRXaXRoKCdEaWQgbm90IGZpbmQgYWRkcmVzcyB3aXRoIGZ1bmRzIHRvIHJlY292ZXIuJyk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRPbmNlKGJhc2Vjb2luLmdldERhdGFGcm9tTm9kZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gcmVjb3ZlciBkdWUgdG8gbm90IGhhdmluZyBtb3JlIHRoYW4gMSBBREEgaW4gZnVuZHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCBzaW5vbi5tYXRjaC5oYXMoJ19hZGRyZXNzZXMnKSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuT25lU21hbGxVVFhPKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IHdyd1VzZXIudXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IHdyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ0luc3VmZmljaWVudCBmdW5kcyB0byByZWNvdmVyLCBtaW5pbXVtIHJlcXVpcmVkIGlzIDEgQURBIHBsdXMgZmVlcywgZ290IDgzNDQ1NSBmZWVzOiAxNjU1NDUnXG4gICAgICAgICk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRUd2ljZShiYXNlY29pbi5nZXREYXRhRnJvbU5vZGUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IHdhbGxldCBhZGRyZXNzIChpc1dhbGxldEFkZHJlc3MpOicsICgpID0+IHtcbiAgICBjb25zdCBjb21tb25LZXljaGFpbiA9XG4gICAgICAnZWQzMTJkMGRiNDYxNTY4ODIxOWM0MzIzMWViNGI5OGQ1ODgzYzBiNDRiY2ZlZjE5NTYyOTA1NTU5OTVhZDY4ZWY3YzIyOTE3YjRhOGI2OTE4Mzg2NGI4M2NjNzAyODY1NWNkN2E3MGVmNzZkNjk0OGQ4MDlhMTUwNTAwNTQ4NDAnO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCB3YWxsZXQgYWRkcmVzcyBhdCBpbmRleCAwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgc291cmNlOiAndXNlcicsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzInLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICczJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgc291cmNlOiAnYml0Z28nLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgY29uc3QgYWRkcmVzcyA9XG4gICAgICAgICdhZGRyX3Rlc3QxcXp2bWF6bXBnZmhqeXBwd2xzdzI5empqd2F6Y3NmazYyejl6djV2c3YyNHAwd3llaDY5a3pzbjB5Z3p6YWxxdTUyOTl5YTY5M3FuZDU1eTJ5ZWdlcWM0Mno3dXEwZ2UycHEnO1xuICAgICAgY29uc3QgaXNWYWxpZCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3MsXG4gICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgaW5kZXg6IDAsXG4gICAgICB9KTtcblxuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmVyaWZ5IGFuIGFkZHJlc3Mgd2l0aCB3cm9uZyBpbmRleCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcyJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAnYmFja3VwJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMycsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICBhZGRyZXNzOlxuICAgICAgICAgICdhZGRyX3Rlc3QxcXp2bWF6bXBnZmhqeXBwd2xzdzI5empqd2F6Y3NmazYyejl6djV2c3YyNHAwd3llaDY5a3pzbjB5Z3p6YWxxdTUyOTl5YTY5M3FuZDU1eTJ5ZWdlcWM0Mno3dXEwZ2UycHEnLFxuICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiAyLFxuICAgICAgfSk7XG5cbiAgICAgIGlzVmFsaWQuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byB2ZXJpZnkgYSByYW5kb20gYWRkcmVzcyBub3QgZnJvbSB3YWxsZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXljaGFpbnMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICd1c2VyJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMicsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzMnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiaXRnbycgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICAvLyBVc2UgYSByYW5kb20gdmFsaWQgQURBIGFkZHJlc3Mgbm90IGZyb20gdGhpcyB3YWxsZXRcbiAgICAgIGNvbnN0IHJhbmRvbUFkZHJlc3MgPSAnYWRkcl90ZXN0MXZyOHJha202NnJjZnY0ZmN4cXlrZzVsZjB5djdsc3lrOW12YXB4MzY5anB2dGNnZmN1azdmJztcblxuICAgICAgY29uc3QgaXNWYWxpZCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3M6IHJhbmRvbUFkZHJlc3MsXG4gICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgaW5kZXg6IDAsXG4gICAgICB9KTtcblxuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBhZGRyZXNzIGZvcm1hdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcyJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAnYmFja3VwJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMycsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGludmFsaWRBZGRyZXNzID0gJ25vdF9hX3ZhbGlkX2FkZHJlc3MnO1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAuaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgICBhZGRyZXNzOiBpbnZhbGlkQWRkcmVzcyxcbiAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIENhcmRhbm8gQWRkcmVzczogbm90X2FfdmFsaWRfYWRkcmVzcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIGtleWNoYWlucyBhcmUgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPVxuICAgICAgICAnYWRkcl90ZXN0MXF6dm1hem1wZ2ZoanlwcHdsc3cyOXpqandhemNzZms2Mno5enY1dnN2MjRwMHd5ZWg2OWt6c24weWd6emFscXU1Mjk5eWE2OTNxbmQ1NXkyeWVnZXFjNDJ6N3VxMGdlMnBxJztcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgICBrZXljaGFpbnM6IFtdLFxuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyByZXF1aXJlZCBwYXJhbSBrZXljaGFpbnMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBjb21tb25LZXljaGFpbiBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICd1c2VyJyBhcyBjb25zdCxcbiAgICAgICAgICAvLyBjb21tb25LZXljaGFpbiBpcyBtaXNzaW5nXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBhZGRyZXNzID1cbiAgICAgICAgJ2FkZHJfdGVzdDFxenZtYXptcGdmaGp5cHB3bHN3Mjl6amp3YXpjc2ZrNjJ6OXp2NXZzdjI0cDB3eWVoNjlrenNuMHlnenphbHF1NTI5OXlhNjkzcW5kNTV5MnllZ2VxYzQyejd1cTBnZTJwcSc7XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICAgIGFkZHJlc3MsXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnbWlzc2luZyByZXF1aXJlZCBwYXJhbSBjb21tb25LZXljaGFpbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIGtleWNoYWlucyBoYXZlIG1pc21hdGNoZWQgY29tbW9uS2V5Y2hhaW5zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAndXNlcicgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzInLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiAnZGlmZmVyZW50S2V5Y2hhaW4xMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmJyxcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgY29uc3QgYWRkcmVzcyA9XG4gICAgICAgICdhZGRyX3Rlc3QxcXp2bWF6bXBnZmhqeXBwd2xzdzI5empqd2F6Y3NmazYyejl6djV2c3YyNHAwd3llaDY5a3pzbjB5Z3p6YWxxdTUyOTl5YTY5M3FuZDU1eTJ5ZWdlcWM0Mno3dXEwZ2UycHEnO1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAuaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgICBhZGRyZXNzLFxuICAgICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2FsbCBrZXljaGFpbnMgbXVzdCBoYXZlIHRoZSBzYW1lIGNvbW1vbktleWNoYWluIGZvciBNUEMgY29pbnMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGFkZHJlc3Mgd2hlbiBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkIGlzIHByZXNlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkID0gJ3Rlc3REZXJpdmF0aW9uU2VlZDEyMyc7XG5cbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIGRlcml2ZWRGcm9tUGFyZW50V2l0aFNlZWQ6IGRlcml2ZWRGcm9tUGFyZW50V2l0aFNlZWQsXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAndXNlcicgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzInLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkOiBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzMnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkOiBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IHsgYWRkcmVzczogZXhwZWN0ZWRBZGRyZXNzIH0gPSBhd2FpdCAoYmFzZWNvaW4gYXMgYW55KS5nZXRBZGFBZGRyZXNzQW5kQWNjb3VudElkKHtcbiAgICAgICAgYml0Z29LZXk6IGNvbW1vbktleWNoYWluLFxuICAgICAgICBpbmRleDogMCxcbiAgICAgICAgc2VlZDogZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgYWRkcmVzczogZXhwZWN0ZWRBZGRyZXNzLFxuICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgfSk7XG5cbiAgICAgIGlzVmFsaWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHZlcmlmaWNhdGlvbiB3aGVuIGRlcml2ZWRGcm9tUGFyZW50V2l0aFNlZWQgaXMgbWlzc2luZyBidXQgYWRkcmVzcyB3YXMgY3JlYXRlZCB3aXRoIHNlZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkID0gJ3Rlc3REZXJpdmF0aW9uU2VlZDEyMyc7XG4gICAgICBjb25zdCB7IGFkZHJlc3M6IGFkZHJlc3NXaXRoU2VlZCB9ID0gYXdhaXQgKGJhc2Vjb2luIGFzIGFueSkuZ2V0QWRhQWRkcmVzc0FuZEFjY291bnRJZCh7XG4gICAgICAgIGJpdGdvS2V5OiBjb21tb25LZXljaGFpbixcbiAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgIHNlZWQ6IGRlcml2ZWRGcm9tUGFyZW50V2l0aFNlZWQsXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qga2V5Y2hhaW5zV2l0aG91dFNlZWQgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICd1c2VyJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMicsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzMnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiaXRnbycgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgYWRkcmVzczogYWRkcmVzc1dpdGhTZWVkLFxuICAgICAgICBrZXljaGFpbnM6IGtleWNoYWluc1dpdGhvdXRTZWVkLFxuICAgICAgICBpbmRleDogMCxcbiAgICAgIH0pO1xuXG4gICAgICBpc1ZhbGlkLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWZXJpZnkgdG9rZW4gY29uc29saWRhdGlvbiB0cmFuc2FjdGlvbjonLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHZlcmlmeSBhIHNwb29mZWQgdG9rZW4gY29uc29saWRhdGlvbiB0cmFuc2FjdGlvbiB3aXRoIGluY29ycmVjdCBhZGRyZXNzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY29uc29saWRhdGlvblR4ID0ge1xuICAgICAgICB0eFJlcXVlc3RJZDogJzRmZGQwY2FlLTI1NjMtNDNiMS1iNWNmLTk0ODY1MTU4Y2ExMCcsXG4gICAgICAgIHdhbGxldElkOiAnNjMwNjhlZDRlZmE2M2EwMDA4NzdmMDJmZDRiMGZhNmQnLFxuICAgICAgICB0eEhleDpcbiAgICAgICAgICAnODRhNDAwODE4MjU4MjA0YmQwZjk5MWMxNTMyY2ZmZTMxZDRhMTBkYjQ5MmI0MzE3NWVjMzI2NzY1YjZiMjljZWVlNTk4ZGYyYjYxZjQ3MDAwMTgxODI1ODM5MDA4NzM3OWViYzU1MzNlYmU2MjE5NjNjOTE1YzNjYmM1ZjA4NTM3ZmNkY2E0YWY4ZjhhZTA4ZWQ0Yzg3Mzc5ZWJjNTUzM2ViZTYyMTk2M2M5MTVjM2NiYzVmMDg1MzdmY2RjYTRhZjhmOGFlMDhlZDRjMWEwNWYzNTlmZjAyMWEwMDAyODcwMTAzMWEwMjQ5NzJlMWExMDA4MTgyNTgyMGJiYWNiMTM0MzFiOTkyMDhlNmU4Y2RiZjcxMDE0N2ZlYWYwNmEzOWQ3MTU2NWU2MGI0MTFjZTllNGZhM2YxMzc1ODQwMDFhNGFiODIzNjU2M2Y2OWZmMzA5ZTU3ODZlOGYzOWM2MjllZDU3Njc2YzY5MjE1OWNiMmUwNDk0YzllNjYzMzU1Mzg0YzEzYzc0OWQwNGMxN2E4MGJhMmE0NWNjMTI3ZGY0ODBmYzY0YTQzMTk5YTc3MmYxMWFjZDViMTRhMGZmNWY2JyxcbiAgICAgICAgZmVlSW5mbzoge1xuICAgICAgICAgIGZlZTogMTAwMDAsXG4gICAgICAgICAgZmVlU3RyaW5nOiAnMTAwMDAnLFxuICAgICAgICB9LFxuICAgICAgICB0eEluZm86IHtcbiAgICAgICAgICBpbnB1dHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWRkcmVzczogJzhpTGEyNktTYmRwQlV6Tks3dVlxOEZ2eXV5QTVoNGs0ZXJESHNEY1BiSHVzJyxcbiAgICAgICAgICAgICAgdmFsdWU6IDIuMDE3MzIyOGUxMCxcbiAgICAgICAgICAgICAgdmFsdWVTdHJpbmc6ICcyMDE3MzIyODAwMCcsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhZGRyZXNzOiAnOFAya1g3VHloOWVTM1JLZGFCaHFiRXRRR0FYNThEWHpMN21oRFFBQkdYMmQnLFxuICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnMTAwMDAnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIG1pbmVyRmVlOiAnMTAwMDAnLFxuICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWRkcmVzczogJ2FkZHJfdGVzdDF2cjhyYWttNjZyY2Z2NGZjeHF5a2c1bGYweXY3bHN5azltdmFweDM2OWpwdnRjZ2ZjdWs3ZicsXG4gICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYTp1c2R0JyxcbiAgICAgICAgICAgICAgZW50ZXJwcmlzZToge1xuICAgICAgICAgICAgICAgICRvaWQ6ICc1NTUzYmE4YWU3YTVjNzcwMDY3MTk2NjEnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBlbnRlcnByaXNlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICRvaWQ6ICc1NTUzYmE4YWU3YTVjNzcwMDY3MTk2NjEnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHZhbHVlOiAyLjAxNzMyMjhlMTAsXG4gICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnMjAxNzMyMjgwMDAnLFxuICAgICAgICAgICAgICB3YWxsZXQ6IHtcbiAgICAgICAgICAgICAgICAkb2lkOiAnNjJmNGMzNzIwZDkyYzUwMDA4MjU3ZWI1JyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgd2FsbGV0VHlwZTogJ2hvdCcsXG4gICAgICAgICAgICAgIHdhbGxldHM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAkb2lkOiAnNjJmNGMzNzIwZDkyYzUwMDA4MjU3ZWI1JyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHBheUdvRmVlOiAnMCcsXG4gICAgICAgICAgc3BlbmRBbW91bnQ6ICcyMDE3MzIyODAwMCcsXG4gICAgICAgICAgc3BlbmRBbW91bnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFtb3VudFN0cmluZzogJzIwMTczMjI4MDAwJyxcbiAgICAgICAgICAgICAgY29pbk5hbWU6ICd0YWRhOnVzZHQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHR5cGU6ICdTZW5kJyxcbiAgICAgICAgfSxcbiAgICAgICAgY29uc29saWRhdGVJZDogJzY3MTJkN2ZkYTZkZTQ5MDZkNjU4YzA0YWViYmY4ZjliJyxcbiAgICAgICAgY29pbjogJ3RhZGEnLFxuICAgICAgfTtcblxuICAgICAgLy8gTW9jayB0aGUgd2FsbGV0IHdpdGggYSBkaWZmZXJlbnQgYWRkcmVzcyB0aGFuIHRoZSB0cmFuc2FjdGlvbidzIG91dHB1dFxuICAgICAgY29uc3QgbW9ja2VkV2FsbGV0ID0ge1xuICAgICAgICBjb2luU3BlY2lmaWM6ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm9vdEFkZHJlc3M6XG4gICAgICAgICAgICAgICdhZGRyX3Rlc3QxcXFubnZwdHJjM3JlYzY0cTJuOWpoNTcybmN1NXd2ZHR0OHV2ZzRnM2FqOTZzNWR3dTluajcwbWxhaHpnbG05OTM5dWV2dXBzbWo4ZGNkcXYyNWQ1bjVyOHZ3OHNuN3ByZXknLFxuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7fSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBjb25zb2xpZGF0aW9uVHgsXG4gICAgICAgICAgd2FsbGV0OiBtb2NrZWRXYWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7XG4gICAgICAgICAgICBjb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzczogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgndHggb3V0cHV0cyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIGFkZHJlc3MnKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==