@bitgo-beta/sdk-coin-ada 2.3.14-beta.202 → 2.3.14-beta.2021

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/src/ada.d.ts +22 -14
  2. package/dist/src/ada.d.ts.map +1 -1
  3. package/dist/src/ada.js +168 -76
  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 +31 -7
  35. package/dist/src/lib/transaction.d.ts.map +1 -1
  36. package/dist/src/lib/transaction.js +112 -17
  37. package/dist/src/lib/transactionBuilder.d.ts +122 -3
  38. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  39. package/dist/src/lib/transactionBuilder.js +517 -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 +1704 -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/plutusPledgeBuilder.d.ts +2 -0
  86. package/dist/test/unit/plutusPledgeBuilder.d.ts.map +1 -0
  87. package/dist/test/unit/plutusPledgeBuilder.js +162 -0
  88. package/dist/test/unit/stakingClaimRewardsBuilder.d.ts +2 -0
  89. package/dist/test/unit/stakingClaimRewardsBuilder.d.ts.map +1 -0
  90. package/dist/test/unit/stakingClaimRewardsBuilder.js +70 -0
  91. package/dist/test/unit/stakingPledgeBuilder.d.ts +2 -0
  92. package/dist/test/unit/stakingPledgeBuilder.d.ts.map +1 -0
  93. package/dist/test/unit/stakingPledgeBuilder.js +141 -0
  94. package/dist/test/unit/stakingWithdrawBuilder.d.ts +2 -0
  95. package/dist/test/unit/stakingWithdrawBuilder.d.ts.map +1 -0
  96. package/dist/test/unit/stakingWithdrawBuilder.js +167 -0
  97. package/dist/test/unit/tokenWithdrawal.d.ts +2 -0
  98. package/dist/test/unit/tokenWithdrawal.d.ts.map +1 -0
  99. package/dist/test/unit/tokenWithdrawal.js +959 -0
  100. package/dist/test/unit/transaction.d.ts +2 -0
  101. package/dist/test/unit/transaction.d.ts.map +1 -0
  102. package/dist/test/unit/transaction.js +100 -0
  103. package/dist/test/unit/transactionBuilder.d.ts +2 -0
  104. package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
  105. package/dist/test/unit/transactionBuilder.js +545 -0
  106. package/dist/test/unit/utils.d.ts +2 -0
  107. package/dist/test/unit/utils.d.ts.map +1 -0
  108. package/dist/test/unit/utils.js +138 -0
  109. package/dist/test/unit/voteDelegationBuilder.d.ts +2 -0
  110. package/dist/test/unit/voteDelegationBuilder.d.ts.map +1 -0
  111. package/dist/test/unit/voteDelegationBuilder.js +96 -0
  112. package/dist/tsconfig.tsbuildinfo +1 -0
  113. package/package.json +18 -13
  114. package/.eslintignore +0 -5
  115. package/.mocharc.yml +0 -8
  116. package/CHANGELOG.md +0 -510
@@ -0,0 +1,1704 @@
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 tweetnacl_1 = __importDefault(require("tweetnacl"));
44
+ const crypto_1 = require("crypto");
45
+ const sinon = __importStar(require("sinon"));
46
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
47
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
48
+ const resources_1 = require("../resources");
49
+ const _ = __importStar(require("lodash"));
50
+ const CardanoWasm = __importStar(require("@emurgo/cardano-serialization-lib-nodejs"));
51
+ const src_1 = require("../../src");
52
+ const lib_1 = require("../../src/lib");
53
+ const enum_1 = require("../../../sdk-core/src/account-lib/baseCoin/enum");
54
+ const assert_1 = __importDefault(require("assert"));
55
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
56
+ const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
57
+ const nock_1 = __importDefault(require("nock"));
58
+ describe('ADA', function () {
59
+ const coinName = 'ada';
60
+ const tcoinName = 't' + coinName;
61
+ let bitgo;
62
+ let basecoin;
63
+ let newTxPrebuild;
64
+ let newTxParams;
65
+ const txPrebuild = {
66
+ txHex: resources_1.rawTx.unsignedTx,
67
+ txInfo: {},
68
+ };
69
+ const txParams = {
70
+ recipients: [
71
+ {
72
+ address: resources_1.rawTx.outputAddress1.address,
73
+ amount: '5000000',
74
+ },
75
+ {
76
+ address: resources_1.rawTx.outputAddress2.address,
77
+ amount: '248329150',
78
+ },
79
+ ],
80
+ };
81
+ const transactionExplanation = {
82
+ displayOrder: ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'],
83
+ id: 'f48f6ea0f75f3f942855cc0edf29e81e1e0724e75f5db8a1575b166fb202176c',
84
+ outputs: [
85
+ {
86
+ address: 'addr_test1qqnnvptrc3rec64q2n9jh572ncu5wvdtt8uvg4g3aj96s5dwu9nj70mlahzglm9939uevupsmj8dcdqv25d5n5r8vw8sn7prey',
87
+ amount: '7823121',
88
+ },
89
+ {
90
+ address: 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f',
91
+ amount: '13041729',
92
+ },
93
+ ],
94
+ outputAmount: '20864850',
95
+ changeOutputs: [],
96
+ changeAmount: '0',
97
+ fee: { fee: '167173' },
98
+ type: 'Transfer',
99
+ certificates: [],
100
+ withdrawals: [],
101
+ pledgeDetails: undefined,
102
+ };
103
+ before(function () {
104
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
105
+ bitgo.initializeTestVars();
106
+ bitgo.safeRegister(coinName, src_1.Ada.createInstance);
107
+ bitgo.safeRegister(tcoinName, src_1.Tada.createInstance);
108
+ basecoin = bitgo.coin(tcoinName);
109
+ newTxPrebuild = () => {
110
+ return _.cloneDeep(txPrebuild);
111
+ };
112
+ newTxParams = () => {
113
+ return _.cloneDeep(txParams);
114
+ };
115
+ });
116
+ it('should instantiate the coin', function () {
117
+ let localBasecoin = bitgo.coin(tcoinName);
118
+ localBasecoin.should.be.an.instanceof(src_1.Tada);
119
+ localBasecoin.getChain().should.equal(tcoinName);
120
+ localBasecoin.getFullName().should.equal('Testnet Ada');
121
+ localBasecoin = bitgo.coin(coinName);
122
+ localBasecoin.should.be.an.instanceof(src_1.Ada);
123
+ localBasecoin.getChain().should.equal(coinName);
124
+ localBasecoin.getFullName().should.equal('Cardano ADA');
125
+ });
126
+ describe('Sign Message', () => {
127
+ it('should be performed', async () => {
128
+ const keyPair = new src_1.KeyPair();
129
+ const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
130
+ const signature = await basecoin.signMessage(keyPair.getKeys(), messageToSign);
131
+ keyPair.verifySignature(messageToSign, Uint8Array.from(signature)).should.equals(false);
132
+ });
133
+ it('should fail with missing private key', async () => {
134
+ const keyPair = new src_1.KeyPair({
135
+ pub: '7788327c695dca4b3e649a0db45bc3e703a2c67428fce360e61800cc4248f4f7',
136
+ }).getKeys();
137
+ const messageToSign = Buffer.from((0, crypto_1.randomBytes)(32)).toString('hex');
138
+ await basecoin.signMessage(keyPair, messageToSign).should.be.rejectedWith('Invalid key pair options');
139
+ });
140
+ });
141
+ describe('Sign transaction', () => {
142
+ it('should sign transaction', async function () {
143
+ const signed = await basecoin.signTransaction({
144
+ txPrebuild: {
145
+ txHex: resources_1.rawTx.unsignedTx2,
146
+ },
147
+ pubs: [resources_1.publicKeys.pubKey1],
148
+ prv: resources_1.privateKeys.prvKey4,
149
+ });
150
+ signed.txHex.should.equal(resources_1.rawTx.signedTx2);
151
+ });
152
+ it('should fail to sign transaction with an invalid key', async function () {
153
+ try {
154
+ await basecoin.signTransaction({
155
+ txPrebuild: {
156
+ txHex: resources_1.rawTx.unsignedTx2,
157
+ },
158
+ pubs: [resources_1.publicKeys.pubKey1],
159
+ prv: resources_1.privateKeys.prvKey2,
160
+ });
161
+ }
162
+ catch (e) {
163
+ should.equal(e.message, 'Private key cannot sign the transaction');
164
+ }
165
+ });
166
+ it('should fail to build transaction with missing params', async function () {
167
+ try {
168
+ await basecoin.signTransaction({
169
+ txPrebuild: {
170
+ txHex: resources_1.rawTx.unsignedTx,
171
+ key: resources_1.enterpriseAccounts.account1.publicKey,
172
+ },
173
+ prv: resources_1.enterpriseAccounts.account1.secretKey,
174
+ });
175
+ }
176
+ catch (e) {
177
+ should.notEqual(e, null);
178
+ }
179
+ });
180
+ });
181
+ describe('Generate wallet key pair: ', () => {
182
+ it('should generate key pair', () => {
183
+ const kp = basecoin.generateKeyPair();
184
+ basecoin.isValidPub(kp.pub).should.equal(true);
185
+ basecoin.isValidPrv(kp.prv).should.equal(true);
186
+ });
187
+ it('should generate key pair from seed', () => {
188
+ const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex');
189
+ const kp = basecoin.generateKeyPair(seed);
190
+ basecoin.isValidPub(kp.pub).should.equal(true);
191
+ basecoin.isValidPrv(kp.prv).should.equal(true);
192
+ });
193
+ });
194
+ describe('Verify transaction: ', () => {
195
+ it('should succeed to verify unsigned transaction in hex encoding', async () => {
196
+ const txParams = newTxParams();
197
+ const txPrebuild = newTxPrebuild();
198
+ const verification = {};
199
+ const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
200
+ isTransactionVerified.should.equal(true);
201
+ });
202
+ it('should succeed to verify signed transaction in hex encoding', async () => {
203
+ const txPrebuild = {
204
+ txHex: resources_1.rawTx.signedTx,
205
+ txInfo: {},
206
+ };
207
+ const txParams = newTxParams();
208
+ const verification = {};
209
+ const isTransactionVerified = await basecoin.verifyTransaction({ txParams, txPrebuild, verification });
210
+ isTransactionVerified.should.equal(true);
211
+ });
212
+ it('should fail verify transactions when have different recipients', async () => {
213
+ const txPrebuild = newTxPrebuild();
214
+ const txParams = {
215
+ recipients: [
216
+ {
217
+ address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
218
+ amount: '1000000000000000000000000',
219
+ },
220
+ {
221
+ address: '9f7b0675db59d19b4bd9c8c72eaabba75a9863d02b30115b8b3c3ca5c20f0254',
222
+ amount: '2000000000000000000000000',
223
+ },
224
+ ],
225
+ };
226
+ const verification = {};
227
+ await basecoin
228
+ .verifyTransaction({ txParams, txPrebuild, verification })
229
+ .should.be.rejectedWith('cannot find recipient in expected output');
230
+ });
231
+ it('should verify when input `recipients` is absent', async function () {
232
+ const txParams = newTxParams();
233
+ txParams.recipients = undefined;
234
+ const txPrebuild = newTxPrebuild();
235
+ const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
236
+ validTransaction.should.equal(true);
237
+ });
238
+ it('should fail verify when txHex is invalid', async function () {
239
+ const txParams = newTxParams();
240
+ txParams.recipients = undefined;
241
+ const txPrebuild = {};
242
+ await basecoin
243
+ .verifyTransaction({ txParams, txPrebuild })
244
+ .should.rejectedWith('missing required tx prebuild property txHex');
245
+ });
246
+ it('should succeed to verify transactions when recipients has extra data', async function () {
247
+ const txPrebuild = newTxPrebuild();
248
+ const txParams = newTxParams();
249
+ txParams.data = 'data';
250
+ const validTransaction = await basecoin.verifyTransaction({ txParams, txPrebuild });
251
+ validTransaction.should.equal(true);
252
+ });
253
+ it('should verify a valid consolidation transaction', async () => {
254
+ const consolidationTx = {
255
+ txRequestId: '1b5c79c5-ab7c-4f47-912b-de6a95fb0779',
256
+ walletId: '64fa31a94db65a0007c9691b',
257
+ txHex: '84a40081825820db46c7c76ea54fec2ca0a2f94b77a238931a8dce2387c99a12b08dd8aac21c4f000181825839004601fc016ac38580916d3520bc76b659298156008738d347aa93142f4601fc016ac38580916d3520bc76b659298156008738d347aa93142f1a3b984357021a000286a9031a060e37eea0f5f6',
258
+ feeInfo: {
259
+ fee: 165545,
260
+ feeString: '165545',
261
+ },
262
+ txInfo: {
263
+ minerFee: '165545',
264
+ spendAmount: '999834455',
265
+ spendAmounts: [
266
+ {
267
+ coinName: 'tada',
268
+ amountString: '999834455',
269
+ },
270
+ ],
271
+ payGoFee: '0',
272
+ outputs: [
273
+ {
274
+ address: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
275
+ value: 999834455,
276
+ wallet: '64fa31a94db65a0007c9691b',
277
+ wallets: ['64fa31a94db65a0007c9691b'],
278
+ enterprise: '62cc59b727443a0007089033',
279
+ enterprises: ['62cc59b727443a0007089033'],
280
+ valueString: '999834455',
281
+ coinName: 'tada',
282
+ walletType: 'hot',
283
+ walletTypes: ['hot'],
284
+ },
285
+ ],
286
+ inputs: [
287
+ {
288
+ value: 1000000000,
289
+ address: 'addr_test1qqlzxfl7tlgp999x4a7334pchycpkk72pykrsr3mryl3yj6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsvpgl8w',
290
+ valueString: '1000000000',
291
+ },
292
+ ],
293
+ type: '0',
294
+ },
295
+ consolidateId: '68b9fc18558006aab53785615fea7c28',
296
+ coin: 'tada',
297
+ };
298
+ const mockedWallet = {
299
+ coinSpecific: () => {
300
+ return {
301
+ rootAddress: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
302
+ };
303
+ },
304
+ };
305
+ try {
306
+ const isVerified = await basecoin.verifyTransaction({
307
+ txParams: {},
308
+ txPrebuild: consolidationTx,
309
+ wallet: mockedWallet,
310
+ verification: {
311
+ consolidationToBaseAddress: true,
312
+ },
313
+ });
314
+ isVerified.should.equal(true);
315
+ }
316
+ catch (e) {
317
+ assert_1.default.fail('Transaction should pass verification');
318
+ }
319
+ });
320
+ it('should verify a valid sponsored consolidation transaction', async () => {
321
+ const consolidationTx = {
322
+ txRequestId: '1b5c79c5-ab7c-4f47-912b-de6a95fb0779',
323
+ walletId: '64fa31a94db65a0007c9691b',
324
+ txHex: '84a40082825820227f65d20ac6e49602d79c623c51911ead824235e01eb2a1e7e33a72f0747cbb00825820227f65d20ac6e49602d79c623c51911ead824235e01eb2a1e7e33a72f0747cbb0201828258390022098270a5c19c9fb706dce0e7e4566b234ec5f0010623cd63f198ad22098270a5c19c9fb706dce0e7e4566b234ec5f0010623cd63f198ad1a0098968082581d60cf90f9fb02c88bad3c5294d90587458c4f160a2db26ba8af3da255b11a05d42fb8021a0002a491031a06d8c048a0f5f6',
325
+ feeInfo: {
326
+ fee: 165545,
327
+ feeString: '165545',
328
+ },
329
+ txInfo: {
330
+ minerFee: '165545',
331
+ spendAmount: '999834455',
332
+ spendAmounts: [
333
+ {
334
+ coinName: 'tada',
335
+ amountString: '999834455',
336
+ },
337
+ ],
338
+ payGoFee: '0',
339
+ outputs: [
340
+ {
341
+ address: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
342
+ value: 999834455,
343
+ wallet: '64fa31a94db65a0007c9691b',
344
+ wallets: ['64fa31a94db65a0007c9691b'],
345
+ enterprise: '62cc59b727443a0007089033',
346
+ enterprises: ['62cc59b727443a0007089033'],
347
+ valueString: '999834455',
348
+ coinName: 'tada',
349
+ walletType: 'hot',
350
+ walletTypes: ['hot'],
351
+ },
352
+ ],
353
+ inputs: [
354
+ {
355
+ value: 1000000000,
356
+ address: 'addr_test1qqlzxfl7tlgp999x4a7334pchycpkk72pykrsr3mryl3yj6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsvpgl8w',
357
+ valueString: '1000000000',
358
+ },
359
+ ],
360
+ type: '0',
361
+ feeAddress: 'addr_test1vr8ep70mqtyghtfu222djpv8gkxy79s29kexh2908k39tvge02d5j',
362
+ },
363
+ consolidateId: '68b9fc18558006aab53785615fea7c28',
364
+ coin: 'tada',
365
+ };
366
+ const mockedWallet = {
367
+ coinSpecific: () => {
368
+ return {
369
+ rootAddress: 'addr_test1qq3qnqns5hqee8ahqmwwpely2e4jxnk97qqsvg7dv0ce3tfzpxp8pfwpnj0mwpkuurn7g4ntyd8vtuqpqc3u6cl3nzksvggu82',
370
+ };
371
+ },
372
+ };
373
+ try {
374
+ const isVerified = await basecoin.verifyTransaction({
375
+ txParams: {},
376
+ txPrebuild: consolidationTx,
377
+ wallet: mockedWallet,
378
+ verification: {
379
+ consolidationToBaseAddress: true,
380
+ },
381
+ });
382
+ isVerified.should.equal(true);
383
+ }
384
+ catch (e) {
385
+ assert_1.default.fail('Transaction should pass verification');
386
+ }
387
+ });
388
+ it('should fail to sign a spoofed consolidation transaction', async function () {
389
+ // Set up wallet data
390
+ const walletData = {
391
+ id: '5b34252f1bf349930e34020a00000000',
392
+ coin: 'tada',
393
+ keys: [
394
+ '5b3424f91bf349930e34017500000000',
395
+ '5b3424f91bf349930e34017600000000',
396
+ '5b3424f91bf349930e34017700000000',
397
+ ],
398
+ coinSpecific: {
399
+ rootAddress: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
400
+ },
401
+ multisigType: 'tss',
402
+ };
403
+ const fakePrv = await (0, sdk_api_1.encrypt)('password', 'prv');
404
+ const walletObj = new sdk_core_1.Wallet(bitgo, basecoin, walletData);
405
+ const bgUrl = sdk_core_1.common.Environments['mock'].uri;
406
+ (0, nock_1.default)(bgUrl)
407
+ .get('/api/v2/tada/key/5b3424f91bf349930e34017500000000')
408
+ .reply(200, [
409
+ {
410
+ encryptedPrv: fakePrv,
411
+ },
412
+ ]);
413
+ // Mock the API response for buildAccountConsolidations
414
+ (0, nock_1.default)(bgUrl)
415
+ .post('/api/v2/tada/wallet/5b34252f1bf349930e34020a00000000/consolidateAccount/build')
416
+ .reply(200, [
417
+ {
418
+ txRequestId: '1b5c79c5-ab7c-4f47-912b-de6a95fb0779',
419
+ walletId: '64fa31a94db65a0007c9691b',
420
+ txHex: '84a40081825820db46c7c76ea54fec2ca0a2f94b77a238931a8dce2387c99a12b08dd8aac21c4f01018282581d6033c378cee41b2e15ac848f7f6f1d2f78155ab12d93b713de898d855f1a00989680825839004601fc016ac38580916d3520bc76b659298156008738d347aa93142f4601fc016ac38580916d3520bc76b659298156008738d347aa93142f1b0000000217acebe9021a00028db5031a060e3b41a0f5f6',
421
+ feeInfo: {
422
+ fee: 165545,
423
+ feeString: '165545',
424
+ },
425
+ txInfo: {
426
+ minerFee: '165545',
427
+ spendAmount: '999834455',
428
+ spendAmounts: [
429
+ {
430
+ coinName: 'tada',
431
+ amountString: '999834455',
432
+ },
433
+ ],
434
+ payGoFee: '0',
435
+ outputs: [
436
+ {
437
+ address: 'addr_test1qprqrlqpdtpctqy3d56jp0rkkevjnq2kqzrn356842f3gt6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsjdmg2s',
438
+ value: 999834455,
439
+ wallet: '64fa31a94db65a0007c9691b',
440
+ wallets: ['64fa31a94db65a0007c9691b'],
441
+ enterprise: '62cc59b727443a0007089033',
442
+ enterprises: ['62cc59b727443a0007089033'],
443
+ valueString: '999834455',
444
+ coinName: 'tada',
445
+ walletType: 'hot',
446
+ walletTypes: ['hot'],
447
+ },
448
+ ],
449
+ inputs: [
450
+ {
451
+ value: 1000000000,
452
+ address: 'addr_test1qqlzxfl7tlgp999x4a7334pchycpkk72pykrsr3mryl3yj6xq87qz6krskqfzmf4yz78ddje9xq4vqy88rf5025nzshsvpgl8w',
453
+ valueString: '1000000000',
454
+ },
455
+ ],
456
+ type: '0',
457
+ },
458
+ consolidateId: '68b9fc18558006aab53785615fea7c28',
459
+ coin: 'tada',
460
+ },
461
+ ]);
462
+ // Call the function to test
463
+ await assert_1.default.rejects(async () => {
464
+ await walletObj.sendAccountConsolidations({
465
+ walletPassphrase: 'password',
466
+ });
467
+ }, {
468
+ message: 'tx outputs does not match with expected address',
469
+ });
470
+ });
471
+ });
472
+ describe('Explain Transactions:', () => {
473
+ it('should explain an unsigned transfer transaction', async function () {
474
+ const explainedTransaction = await basecoin.explainTransaction({
475
+ txPrebuild: {
476
+ txHex: resources_1.rawTx.unsignedTx2,
477
+ },
478
+ });
479
+ console.log(explainedTransaction);
480
+ explainedTransaction.should.deepEqual(transactionExplanation);
481
+ });
482
+ it('should fail to explain transaction with missing params', async function () {
483
+ try {
484
+ await basecoin.explainTransaction({
485
+ txPrebuild: {},
486
+ });
487
+ }
488
+ catch (error) {
489
+ should.equal(error.message, 'Invalid transaction');
490
+ }
491
+ });
492
+ it('should fail to explain transaction with wrong params', async function () {
493
+ try {
494
+ await basecoin.explainTransaction({
495
+ txPrebuild: {
496
+ txHex: 'invalidTxHex',
497
+ },
498
+ });
499
+ }
500
+ catch (error) {
501
+ should.equal(error.message, 'Invalid transaction');
502
+ }
503
+ });
504
+ });
505
+ describe('Parse Raw Transactions', () => {
506
+ it('should parse staking pledge transaction', function () {
507
+ const tx = new lib_1.Transaction(basecoin);
508
+ tx.fromRawTransaction(resources_1.rawTx.unsignedNewPledgeTx);
509
+ should.equal(tx.type, enum_1.TransactionType.StakingPledge);
510
+ });
511
+ it('should parse staking activation tx', function () {
512
+ const tx = new lib_1.Transaction(basecoin);
513
+ tx.fromRawTransaction(resources_1.rawTx.unsignedStakingActiveTx);
514
+ should.equal(tx.type, enum_1.TransactionType.StakingActivate);
515
+ });
516
+ it('should parse staking deactivation tx', function () {
517
+ const tx = new lib_1.Transaction(basecoin);
518
+ tx.fromRawTransaction(resources_1.rawTx.unsignedStakingDeactiveTx);
519
+ should.equal(tx.type, enum_1.TransactionType.StakingDeactivate);
520
+ });
521
+ });
522
+ describe('Parse Transactions:', () => {
523
+ it('should parse an unsigned transfer transaction', async function () {
524
+ const parsedTransaction = await basecoin.parseTransaction({
525
+ txPrebuild: {
526
+ txHex: resources_1.rawTx.unsignedTx2,
527
+ },
528
+ });
529
+ parsedTransaction.should.deepEqual(transactionExplanation);
530
+ });
531
+ it('should parse a signed transfer transaction', async function () {
532
+ const parsedTransaction = await basecoin.parseTransaction({
533
+ txPrebuild: {
534
+ txHex: resources_1.rawTx.signedTx2,
535
+ },
536
+ });
537
+ parsedTransaction.should.deepEqual(transactionExplanation);
538
+ });
539
+ it('should fail parse a signed transfer transaction when explainTransaction response is undefined', async function () {
540
+ const stub = sinon.stub(src_1.Ada.prototype, 'explainTransaction');
541
+ stub.resolves(undefined);
542
+ await basecoin
543
+ .parseTransaction({
544
+ txPrebuild: {
545
+ txHex: resources_1.rawTx.signedTx,
546
+ },
547
+ })
548
+ .should.be.rejectedWith('Invalid transaction');
549
+ stub.restore();
550
+ });
551
+ });
552
+ describe('Recover Transactions:', () => {
553
+ const destAddr = resources_1.address.address2;
554
+ const sandBox = sinon.createSandbox();
555
+ let callBack;
556
+ beforeEach(function () {
557
+ callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
558
+ callBack
559
+ .withArgs('address_info', {
560
+ _addresses: [resources_1.wrwUser.walletAddress0],
561
+ })
562
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
563
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
564
+ });
565
+ afterEach(function () {
566
+ sandBox.restore();
567
+ });
568
+ it('should take OVC output and generate a signed sweep transaction', async function () {
569
+ const params = resources_1.ovcResponse;
570
+ const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
571
+ recoveryTxn.transactions[0].serializedTx.should.equal('84a400818258204bd0f991c1532cffe31d4a10db492b43175ec326765b6b29ceee598df2b61f470001818258390087379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c87379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c1a05f359ff021a00028701031a024972e1a10081825820bbacb13431b99208e6e8cdbf710147feaf06a39d71565e60b411ce9e4fa3f137584001a4ab8236563f69ff309e5786e8f39c629ed57676c692159cb2e0494c9e663355384c13c749d04c17a80ba2a45cc127df480fc64a43199a772f11acd5b14a0ff5f6');
572
+ recoveryTxn.transactions[0].scanIndex.should.equal(0);
573
+ recoveryTxn.lastScanIndex.should.equal(0);
574
+ });
575
+ it('should take consolidation OVC output and generate multiple signed sweep transactions', async function () {
576
+ const params = resources_1.ovcResponse2;
577
+ const recoveryTxn = await basecoin.createBroadcastableSweepTransaction(params);
578
+ recoveryTxn.transactions[0].serializedTx.should.equal('84a400818258203e62e5ee8b12012c4b949f9777b72165239bb2146ae8b078b4d1c5ca8d3168e300018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa10081825820500e0d725a5ba3a306da3503dfe57b8a14068a09b61b36ec068fcf8cf5c391de5840c836ce6d3262d5654706ea06721522d3b75f6d545245047a7be7463629d88b3f4264b995f591df52bdffcf09da1e6ab9e88de3714c6e2ec1961786cf1c586a07f5f6');
579
+ recoveryTxn.transactions[0].scanIndex.should.equal(1);
580
+ recoveryTxn.transactions[1].serializedTx.should.equal('84a4008182582029c10acf0e08f9523325c88243565af6b32274992189c1153903c410bed7c2c700018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa1008182582062770b224bd314bc526fbd6a94e9082fb6458c425e6e09bad74004dd897e962358403842544f2ff28be054eb7c7997bc303b1e251eb13a41802c82318e592bb24eaa3197c450e797cc8559f0356cd5cdd1ab5eb80c5173e34e9e1d1737533a89520cf5f6');
581
+ recoveryTxn.transactions[1].scanIndex.should.equal(2);
582
+ recoveryTxn.transactions[2].serializedTx.should.equal('84a40081825820dd140f133d865e1bb5642e708fe685bf7601d71d0c99511e5d552da7f8bd10ff00018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa1008182582053b4bb74aa38add458dafc8153f0aa8266acad59322b877ca9c23c5d3873779d5840e94ce7896957d094c6bafbf2ec10df5ebb0f1d2a27a7e31f2d45c531fb687edd6c4d33f8e9b99c7692b6fac6d8399bd8fd47641baae9bbb69f518d42ad11710af5f6');
583
+ recoveryTxn.transactions[2].scanIndex.should.equal(3);
584
+ recoveryTxn.transactions[3].serializedTx.should.equal('84a4008182582015a1d6db5d3f592aa1cda185b6359ca0e2921c3c51959f64222a6b7d95d3392300018182583900baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd08004baf55ebcf9ada1b8ecb1640880fba54d2817690f12b3a106afd080041a00960f7f021a00028701031a0250f7eaa10081825820600f86ca22d670f0a990ade4e882c05e654343263494735a31517de0819676735840fe199f8e247a4cfabfeb4f9cb574aa35739a0aa98860ee0a85d720c4ab4fecfac7b4504df310b3e4bea04711f60652d4a8cf5eb41817293b8d29977fe695f704f5f6');
585
+ recoveryTxn.transactions[3].scanIndex.should.equal(4);
586
+ recoveryTxn.lastScanIndex.should.equal(20);
587
+ });
588
+ it('should recover a txn for non-bitgo recoveries', async function () {
589
+ const res = await basecoin.recover({
590
+ userKey: resources_1.wrwUser.userKey,
591
+ backupKey: resources_1.wrwUser.backupKey,
592
+ bitgoKey: resources_1.wrwUser.bitgoKey,
593
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
594
+ recoveryDestination: destAddr,
595
+ });
596
+ res.should.not.be.empty();
597
+ res.should.hasOwnProperty('serializedTx');
598
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
599
+ const tx = new lib_1.Transaction(basecoin);
600
+ tx.fromRawTransaction(res.serializedTx);
601
+ const txJson = tx.toJson();
602
+ const fee = Number(tx.explainTransaction().fee.fee);
603
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
604
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
605
+ should.deepEqual(txJson.outputs[0].address, destAddr);
606
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value);
607
+ });
608
+ it('should recover a txn for unsigned sweep recoveries', async function () {
609
+ const res = await basecoin.recover({
610
+ bitgoKey: resources_1.wrwUser.bitgoKey,
611
+ recoveryDestination: destAddr,
612
+ });
613
+ res.should.not.be.empty();
614
+ res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
615
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
616
+ const tx = new lib_1.Transaction(basecoin);
617
+ tx.fromRawTransaction(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
618
+ const txJson = tx.toJson();
619
+ const fee = Number(tx.explainTransaction().fee.fee);
620
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
621
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
622
+ should.deepEqual(txJson.outputs[0].address, destAddr);
623
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value);
624
+ });
625
+ it('should recover ADA plus token UTXOs - token and ADA both appear in outputs (unsigned sweep)', async function () {
626
+ callBack
627
+ .withArgs('address_info', { _addresses: [resources_1.wrwUser.walletAddress0] })
628
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
629
+ const res = await basecoin.recover({
630
+ bitgoKey: resources_1.wrwUser.bitgoKey,
631
+ recoveryDestination: destAddr,
632
+ });
633
+ res.should.not.be.empty();
634
+ const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
635
+ unsignedTx.should.hasOwnProperty('serializedTx');
636
+ const tx = new lib_1.Transaction(basecoin);
637
+ tx.fromRawTransaction(unsignedTx.serializedTx);
638
+ const txJson = tx.toJson();
639
+ txJson.inputs.length.should.equal(2);
640
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
641
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_TOKEN.tx_hash);
642
+ txJson.outputs.length.should.equal(2);
643
+ const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
644
+ const tokenEncodedAssetName = '5741544552';
645
+ const tokenQuantity = '111';
646
+ const minADAForToken = 1500000;
647
+ const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
648
+ should.exist(tokenOutput);
649
+ should.deepEqual(tokenOutput.address, destAddr);
650
+ should.deepEqual(Number(tokenOutput.amount), minADAForToken);
651
+ const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
652
+ const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
653
+ tokenOutput.multiAssets
654
+ .get_asset(expectedPolicyId, expectedAssetName)
655
+ .to_str()
656
+ .should.equal(tokenQuantity);
657
+ const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
658
+ should.exist(adaOutput);
659
+ should.deepEqual(adaOutput.address, destAddr);
660
+ const fee = Number(tx.explainTransaction().fee.fee);
661
+ const totalBalance = resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_TOKEN.value;
662
+ should.deepEqual(Number(adaOutput.amount), totalBalance - minADAForToken - fee);
663
+ const explained = tx.explainTransaction();
664
+ const explainedTokenOutput = explained.outputs.find((o) => o.amount === minADAForToken.toString());
665
+ should.exist(explainedTokenOutput);
666
+ // inputs and outputs in parsedTx should carry multiAssets
667
+ const parsedTxInputs = res.txRequests[0].transactions[0].unsignedTx.parsedTx.inputs;
668
+ parsedTxInputs.length.should.equal(1);
669
+ should.exist(parsedTxInputs[0].multiAssets);
670
+ parsedTxInputs[0].multiAssets.length.should.equal(1);
671
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].policy_id, tokenPolicyId);
672
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].asset_name, tokenEncodedAssetName);
673
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].quantity, tokenQuantity);
674
+ const parsedTxOutputs = res.txRequests[0].transactions[0].unsignedTx.parsedTx.outputs;
675
+ const parsedTokenOutput = parsedTxOutputs.find((o) => o.multiAssets !== undefined);
676
+ should.exist(parsedTokenOutput);
677
+ parsedTokenOutput.multiAssets.length.should.equal(1);
678
+ should.deepEqual(parsedTokenOutput.multiAssets[0].policy_id, tokenPolicyId);
679
+ should.deepEqual(parsedTokenOutput.multiAssets[0].asset_name, tokenEncodedAssetName);
680
+ should.deepEqual(parsedTokenOutput.multiAssets[0].quantity, tokenQuantity);
681
+ // pure ADA output should not have multiAssets
682
+ const parsedAdaOutput = parsedTxOutputs.find((o) => o.multiAssets === undefined);
683
+ should.exist(parsedAdaOutput);
684
+ });
685
+ it('should recover ADA plus token UTXOs - token and ADA both appear in outputs (signed)', async function () {
686
+ callBack
687
+ .withArgs('address_info', { _addresses: [resources_1.wrwUser.walletAddress0] })
688
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
689
+ const res = await basecoin.recover({
690
+ userKey: resources_1.wrwUser.userKey,
691
+ backupKey: resources_1.wrwUser.backupKey,
692
+ bitgoKey: resources_1.wrwUser.bitgoKey,
693
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
694
+ recoveryDestination: destAddr,
695
+ });
696
+ res.should.not.be.empty();
697
+ res.should.hasOwnProperty('serializedTx');
698
+ const tx = new lib_1.Transaction(basecoin);
699
+ tx.fromRawTransaction(res.serializedTx);
700
+ const txJson = tx.toJson();
701
+ txJson.inputs.length.should.equal(2);
702
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
703
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_TOKEN.tx_hash);
704
+ // expect 2 outputs: one token output + one ADA change output, both at destAddr
705
+ txJson.outputs.length.should.equal(2);
706
+ const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
707
+ const tokenEncodedAssetName = '5741544552';
708
+ const tokenQuantity = '111';
709
+ const minADAForToken = 1500000;
710
+ const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
711
+ should.exist(tokenOutput);
712
+ should.deepEqual(tokenOutput.address, destAddr);
713
+ should.deepEqual(Number(tokenOutput.amount), minADAForToken);
714
+ const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
715
+ const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
716
+ tokenOutput.multiAssets
717
+ .get_asset(expectedPolicyId, expectedAssetName)
718
+ .to_str()
719
+ .should.equal(tokenQuantity);
720
+ const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
721
+ should.exist(adaOutput);
722
+ should.deepEqual(adaOutput.address, destAddr);
723
+ const fee = Number(tx.explainTransaction().fee.fee);
724
+ const totalBalance = resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_TOKEN.value;
725
+ should.deepEqual(Number(adaOutput.amount), totalBalance - minADAForToken - fee);
726
+ });
727
+ });
728
+ describe('Recover Transactions (MPCv2):', () => {
729
+ const destAddr = resources_1.address.address2;
730
+ const sandBox = sinon.createSandbox();
731
+ const walletPassphrase = resources_1.wrwUser.walletPassphrase;
732
+ let mpcV2UserKey;
733
+ let mpcV2BackupKey;
734
+ let mpcV2CommonKeyChain;
735
+ let mpcV2WalletAddress;
736
+ let mismatchedBitgoKey;
737
+ let mismatchedWalletAddress;
738
+ before(async function () {
739
+ const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
740
+ const [otherUserDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
741
+ mpcV2UserKey = await (0, sdk_api_1.encrypt)(walletPassphrase, userDkg.getReducedKeyShare().toString('base64'));
742
+ mpcV2BackupKey = await (0, sdk_api_1.encrypt)(walletPassphrase, backupDkg.getReducedKeyShare().toString('base64'));
743
+ mpcV2CommonKeyChain = userDkg.getCommonKeychain();
744
+ mismatchedBitgoKey = otherUserDkg.getCommonKeychain();
745
+ mpcV2WalletAddress = (await basecoin.getAdaAddressAndAccountId({ bitgoKey: mpcV2CommonKeyChain, index: 0 }))
746
+ .address;
747
+ mismatchedWalletAddress = (await basecoin.getAdaAddressAndAccountId({ bitgoKey: mismatchedBitgoKey, index: 0 }))
748
+ .address;
749
+ });
750
+ let callBack;
751
+ beforeEach(function () {
752
+ callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
753
+ callBack
754
+ .withArgs('address_info', { _addresses: [mpcV2WalletAddress] })
755
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
756
+ callBack
757
+ .withArgs('address_info', { _addresses: [mismatchedWalletAddress] })
758
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
759
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
760
+ });
761
+ afterEach(function () {
762
+ sandBox.restore();
763
+ });
764
+ it('should route to MPCv2 path for native ADA recovery when keycard is MPCv2', async function () {
765
+ const getTSSSignatureSpy = sandBox.spy(sdk_core_1.EDDSAMethods, 'getTSSSignature');
766
+ const res = await basecoin.recover({
767
+ userKey: mpcV2UserKey,
768
+ backupKey: mpcV2BackupKey,
769
+ bitgoKey: mpcV2CommonKeyChain,
770
+ walletPassphrase,
771
+ recoveryDestination: destAddr,
772
+ });
773
+ res.should.not.be.empty();
774
+ res.should.hasOwnProperty('serializedTx');
775
+ sandBox.assert.notCalled(getTSSSignatureSpy);
776
+ const tx = new lib_1.Transaction(basecoin);
777
+ tx.fromRawTransaction(res.serializedTx);
778
+ const txJson = tx.toJson();
779
+ should.deepEqual(txJson.outputs[0].address, destAddr);
780
+ });
781
+ it('should throw when MPCv2 commonKeyChain does not match bitgoKey', async function () {
782
+ await basecoin
783
+ .recover({
784
+ userKey: mpcV2UserKey,
785
+ backupKey: mpcV2BackupKey,
786
+ bitgoKey: mismatchedBitgoKey,
787
+ walletPassphrase,
788
+ recoveryDestination: destAddr,
789
+ })
790
+ .should.be.rejectedWith('EdDSA MPCv2 recovery: commonKeyChain from keycard does not match bitgoKey');
791
+ });
792
+ it('should call getEddsaSigningMaterial exactly once per recover() call', async function () {
793
+ const getEddsaMaterialSpy = sandBox.spy(basecoin, 'getEddsaSigningMaterial');
794
+ const res = await basecoin.recover({
795
+ userKey: mpcV2UserKey,
796
+ backupKey: mpcV2BackupKey,
797
+ bitgoKey: mpcV2CommonKeyChain,
798
+ walletPassphrase,
799
+ recoveryDestination: destAddr,
800
+ });
801
+ res.should.not.be.empty();
802
+ sandBox.assert.calledOnce(getEddsaMaterialSpy);
803
+ });
804
+ it('should ignore a malformed precomputedMaterial and detect signing material itself (regression: WRW openSSLBytes collision)', async function () {
805
+ // WRW's generic Electron 'recover' IPC handler passes openSSLBytes (an ArrayBuffer)
806
+ // as a second positional argument to every coin's recover(), regardless of whether
807
+ // that coin uses it. Previously this was blindly trusted as precomputedMaterial,
808
+ // producing `JSON.parse(undefined)` -> SyntaxError: "undefined" is not valid JSON.
809
+ const getEddsaMaterialSpy = sandBox.spy(basecoin, 'getEddsaSigningMaterial');
810
+ const res = await basecoin.recover({
811
+ userKey: mpcV2UserKey,
812
+ backupKey: mpcV2BackupKey,
813
+ bitgoKey: mpcV2CommonKeyChain,
814
+ walletPassphrase,
815
+ recoveryDestination: destAddr,
816
+ }, new ArrayBuffer(8));
817
+ res.should.not.be.empty();
818
+ res.should.hasOwnProperty('serializedTx');
819
+ sandBox.assert.calledOnce(getEddsaMaterialSpy);
820
+ });
821
+ it('should route to MPCv1 path when keycard is MPCv1 (regression)', async function () {
822
+ callBack
823
+ .withArgs('address_info', { _addresses: [resources_1.wrwUser.walletAddress0] })
824
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
825
+ const getTSSSignatureSpy = sandBox.spy(sdk_core_1.EDDSAMethods, 'getTSSSignature');
826
+ const res = await basecoin.recover({
827
+ userKey: resources_1.wrwUser.userKey,
828
+ backupKey: resources_1.wrwUser.backupKey,
829
+ bitgoKey: resources_1.wrwUser.bitgoKey,
830
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
831
+ recoveryDestination: destAddr,
832
+ });
833
+ res.should.not.be.empty();
834
+ res.should.hasOwnProperty('serializedTx');
835
+ sandBox.assert.calledOnce(getTSSSignatureSpy);
836
+ });
837
+ it('should produce a cryptographically valid Ed25519 signature', async function () {
838
+ const signRecoverySpy = sandBox.spy(basecoin, 'signAdaMpcV2Recovery');
839
+ await basecoin.recover({
840
+ userKey: mpcV2UserKey,
841
+ backupKey: mpcV2BackupKey,
842
+ bitgoKey: mpcV2CommonKeyChain,
843
+ walletPassphrase,
844
+ recoveryDestination: destAddr,
845
+ });
846
+ const rawSig = await signRecoverySpy.firstCall.returnValue;
847
+ const signablePayload = signRecoverySpy.firstCall.args[0].message;
848
+ const MPC = await sdk_core_1.EDDSAMethods.getInitializedMpcInstance();
849
+ const accountId = MPC.deriveUnhardened(mpcV2CommonKeyChain, 'm/0').slice(0, 64);
850
+ const isValid = tweetnacl_1.default.sign.detached.verify(new Uint8Array(signablePayload), new Uint8Array(rawSig), new Uint8Array(Buffer.from(accountId, 'hex')));
851
+ isValid.should.be.true();
852
+ });
853
+ it('should throw missing userKey when backupKey and walletPassphrase are present but userKey is not', async function () {
854
+ callBack.resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
855
+ await basecoin
856
+ .recover({
857
+ userKey: undefined,
858
+ backupKey: mpcV2BackupKey,
859
+ bitgoKey: mpcV2CommonKeyChain,
860
+ walletPassphrase,
861
+ recoveryDestination: destAddr,
862
+ })
863
+ .should.be.rejectedWith('missing userKey');
864
+ });
865
+ it('should throw missing backupKey when userKey and walletPassphrase are present but backupKey is not', async function () {
866
+ callBack.resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
867
+ await basecoin
868
+ .recover({
869
+ userKey: mpcV2UserKey,
870
+ backupKey: undefined,
871
+ bitgoKey: mpcV2CommonKeyChain,
872
+ walletPassphrase,
873
+ recoveryDestination: destAddr,
874
+ })
875
+ .should.be.rejectedWith('missing backupKey');
876
+ });
877
+ it('should throw a clear error when the MPCv1 backup keycard fails to decrypt', async function () {
878
+ callBack
879
+ .withArgs('address_info', { _addresses: [resources_1.wrwUser.walletAddress0] })
880
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
881
+ await basecoin
882
+ .recover({
883
+ userKey: resources_1.wrwUser.userKey,
884
+ backupKey: 'not-a-valid-encrypted-keycard',
885
+ bitgoKey: resources_1.wrwUser.bitgoKey,
886
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
887
+ recoveryDestination: destAddr,
888
+ })
889
+ .should.be.rejectedWith('Error decrypting backup keychain: invalid password or corrupted key');
890
+ });
891
+ });
892
+ describe('Recover Transactions Multiple UTXO:', () => {
893
+ const destAddr = resources_1.address.address2;
894
+ const sandBox = sinon.createSandbox();
895
+ beforeEach(function () {
896
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
897
+ callBack
898
+ .withArgs('address_info', {
899
+ _addresses: [resources_1.wrwUser.walletAddress0],
900
+ })
901
+ .resolves(resources_1.endpointResponses.addressInfoResponse.TwoUTXO);
902
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
903
+ });
904
+ afterEach(function () {
905
+ sandBox.restore();
906
+ });
907
+ it('should recover a txn for non-bitgo recoveries', async function () {
908
+ const res = await basecoin.recover({
909
+ userKey: resources_1.wrwUser.userKey,
910
+ backupKey: resources_1.wrwUser.backupKey,
911
+ bitgoKey: resources_1.wrwUser.bitgoKey,
912
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
913
+ recoveryDestination: destAddr,
914
+ });
915
+ res.should.not.be.empty();
916
+ res.should.hasOwnProperty('serializedTx');
917
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
918
+ const tx = new lib_1.Transaction(basecoin);
919
+ tx.fromRawTransaction(res.serializedTx);
920
+ const txJson = tx.toJson();
921
+ const fee = Number(tx.explainTransaction().fee.fee);
922
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
923
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
924
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
925
+ should.deepEqual(txJson.inputs[1].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
926
+ should.deepEqual(txJson.outputs[0].address, destAddr);
927
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_2.value);
928
+ });
929
+ it('should recover a txn for unsigned sweep recoveries', async function () {
930
+ const res = await basecoin.recover({
931
+ bitgoKey: resources_1.wrwUser.bitgoKey,
932
+ recoveryDestination: destAddr,
933
+ });
934
+ res.should.not.be.empty();
935
+ res.txRequests[0].transactions[0].unsignedTx.should.hasOwnProperty('serializedTx');
936
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
937
+ const tx = new lib_1.Transaction(basecoin);
938
+ tx.fromRawTransaction(res.txRequests[0].transactions[0].unsignedTx.serializedTx);
939
+ const txJson = tx.toJson();
940
+ const fee = Number(tx.explainTransaction().fee.fee);
941
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
942
+ should.deepEqual(txJson.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
943
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
944
+ should.deepEqual(txJson.inputs[1].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
945
+ should.deepEqual(txJson.outputs[0].address, destAddr);
946
+ should.deepEqual(Number(txJson.outputs[0].amount) + fee, resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_2.value);
947
+ });
948
+ });
949
+ describe('Build Consolidation Recoveries:', () => {
950
+ const baseAddr = resources_1.consolidationWrwUser.walletAddress0;
951
+ const sandBox = sinon.createSandbox();
952
+ beforeEach(function () {
953
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
954
+ callBack
955
+ .withArgs('address_info', {
956
+ _addresses: [resources_1.consolidationWrwUser.walletAddress1],
957
+ })
958
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
959
+ callBack
960
+ .withArgs('address_info', {
961
+ _addresses: [resources_1.consolidationWrwUser.walletAddress2],
962
+ })
963
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
964
+ callBack
965
+ .withArgs('address_info', {
966
+ _addresses: [resources_1.consolidationWrwUser.walletAddress3],
967
+ })
968
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO2);
969
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
970
+ });
971
+ afterEach(function () {
972
+ sandBox.restore();
973
+ });
974
+ it('should build signed consolidation recoveries', async function () {
975
+ const res = await basecoin.recoverConsolidations({
976
+ userKey: resources_1.consolidationWrwUser.userKey,
977
+ backupKey: resources_1.consolidationWrwUser.backupKey,
978
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
979
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
980
+ startingScanIndex: 1,
981
+ endingScanIndex: 4,
982
+ });
983
+ res.should.not.be.empty();
984
+ res.transactions.length.should.equal(2);
985
+ res.lastScanIndex.should.equal(3);
986
+ const txn1 = res.transactions[0];
987
+ const tx1 = new lib_1.Transaction(basecoin);
988
+ tx1.fromRawTransaction(txn1.serializedTx);
989
+ const txJson1 = tx1.toJson();
990
+ const fee1 = Number(tx1.explainTransaction().fee.fee);
991
+ should.deepEqual(txJson1.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
992
+ should.deepEqual(txJson1.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
993
+ should.deepEqual(txJson1.outputs[0].address, baseAddr);
994
+ should.deepEqual(Number(txJson1.outputs[0].amount) + fee1, resources_1.testnetUTXO.UTXO_1.value);
995
+ const txn2 = res.transactions[1];
996
+ const tx2 = new lib_1.Transaction(basecoin);
997
+ tx2.fromRawTransaction(txn2.serializedTx);
998
+ const txJson2 = tx2.toJson();
999
+ const fee2 = Number(tx2.explainTransaction().fee.fee);
1000
+ should.deepEqual(txJson2.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
1001
+ should.deepEqual(txJson2.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
1002
+ should.deepEqual(txJson2.outputs[0].address, baseAddr);
1003
+ should.deepEqual(Number(txJson2.outputs[0].amount) + fee2, resources_1.testnetUTXO.UTXO_2.value);
1004
+ });
1005
+ it('should skip building consolidate transaction if balance is equal to zero', async function () {
1006
+ await basecoin
1007
+ .recoverConsolidations({
1008
+ userKey: resources_1.consolidationWrwUser.userKey,
1009
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1010
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1011
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1012
+ startingScanIndex: 1,
1013
+ endingScanIndex: 2,
1014
+ })
1015
+ .should.rejectedWith('Did not find an address with funds to recover.');
1016
+ });
1017
+ it('should throw if startingScanIndex is not ge to 1', async () => {
1018
+ await basecoin
1019
+ .recoverConsolidations({
1020
+ userKey: resources_1.consolidationWrwUser.userKey,
1021
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1022
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1023
+ startingScanIndex: -1,
1024
+ })
1025
+ .should.be.rejectedWith('Invalid starting or ending index to scan for addresses. startingScanIndex: -1, endingScanIndex: 19.');
1026
+ });
1027
+ it('should throw if scan factor is too high', async () => {
1028
+ await basecoin
1029
+ .recoverConsolidations({
1030
+ userKey: resources_1.consolidationWrwUser.userKey,
1031
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1032
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1033
+ startingScanIndex: 1,
1034
+ endingScanIndex: 300,
1035
+ })
1036
+ .should.be.rejectedWith('Invalid starting or ending index to scan for addresses. startingScanIndex: 1, endingScanIndex: 300.');
1037
+ });
1038
+ it('should build unsigned consolidation recoveries', 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 unsigned consolidation recoveries for WRW (ADA only) and assert build response', async function () {
1051
+ const res = await basecoin.recoverConsolidations({
1052
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1053
+ startingScanIndex: 1,
1054
+ endingScanIndex: 4,
1055
+ });
1056
+ res.should.not.be.empty();
1057
+ res.txRequests.length.should.equal(2);
1058
+ // Assert first consolidation txRequest structure
1059
+ const txRequest1 = res.txRequests[0];
1060
+ txRequest1.transactions.length.should.equal(1);
1061
+ const unsignedTx1 = txRequest1.transactions[0].unsignedTx;
1062
+ unsignedTx1.should.hasOwnProperty('serializedTx');
1063
+ unsignedTx1.should.hasOwnProperty('parsedTx');
1064
+ unsignedTx1.should.hasOwnProperty('coinSpecific');
1065
+ // Deserialize and verify inputs/outputs
1066
+ const tx1 = new lib_1.Transaction(basecoin);
1067
+ tx1.fromRawTransaction(unsignedTx1.serializedTx);
1068
+ const txJson1 = tx1.toJson();
1069
+ const fee1 = Number(tx1.explainTransaction().fee.fee);
1070
+ should.deepEqual(txJson1.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
1071
+ should.deepEqual(txJson1.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_1.tx_index);
1072
+ should.deepEqual(txJson1.outputs[0].address, baseAddr);
1073
+ should.deepEqual(Number(txJson1.outputs[0].amount) + fee1, resources_1.testnetUTXO.UTXO_1.value);
1074
+ // parsedTx inputs/outputs must be present and carry correct address
1075
+ const parsedTx1Inputs = unsignedTx1.parsedTx.inputs;
1076
+ parsedTx1Inputs.length.should.equal(1);
1077
+ should.deepEqual(parsedTx1Inputs[0].address, resources_1.consolidationWrwUser.walletAddress2);
1078
+ const parsedTx1Outputs = unsignedTx1.parsedTx.outputs;
1079
+ parsedTx1Outputs.length.should.be.greaterThan(0);
1080
+ should.deepEqual(parsedTx1Outputs[0].address, baseAddr);
1081
+ // Assert second consolidation txRequest structure
1082
+ const txRequest2 = res.txRequests[1];
1083
+ const unsignedTx2 = txRequest2.transactions[0].unsignedTx;
1084
+ unsignedTx2.should.hasOwnProperty('serializedTx');
1085
+ const tx2 = new lib_1.Transaction(basecoin);
1086
+ tx2.fromRawTransaction(unsignedTx2.serializedTx);
1087
+ const txJson2 = tx2.toJson();
1088
+ const fee2 = Number(tx2.explainTransaction().fee.fee);
1089
+ should.deepEqual(txJson2.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_2.tx_hash);
1090
+ should.deepEqual(txJson2.inputs[0].transaction_index, resources_1.testnetUTXO.UTXO_2.tx_index);
1091
+ should.deepEqual(txJson2.outputs[0].address, baseAddr);
1092
+ should.deepEqual(Number(txJson2.outputs[0].amount) + fee2, resources_1.testnetUTXO.UTXO_2.value);
1093
+ // lastScanIndex must be set in coinSpecific of the last txRequest
1094
+ const lastCoinSpecific = unsignedTx2.coinSpecific;
1095
+ lastCoinSpecific.should.hasOwnProperty('lastScanIndex');
1096
+ lastCoinSpecific.lastScanIndex.should.equal(3);
1097
+ });
1098
+ it('should build unsigned consolidation recoveries for WRW (ADA + Token) and assert build response', async function () {
1099
+ // Override walletAddress2 to return ADA+Token UTXOs
1100
+ sandBox.restore();
1101
+ const callBack2 = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1102
+ callBack2
1103
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress1] })
1104
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
1105
+ callBack2
1106
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress2] })
1107
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ADAAndTokenUTXOs);
1108
+ callBack2
1109
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress3] })
1110
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
1111
+ callBack2.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1112
+ const tokenPolicyId = '2533cca6eb42076e144e9f2772c390dece9fce173bc38c72294b3924';
1113
+ const tokenEncodedAssetName = '5741544552';
1114
+ const tokenQuantity = '111';
1115
+ const minADAForToken = 1500000;
1116
+ const res = await basecoin.recoverConsolidations({
1117
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1118
+ startingScanIndex: 1,
1119
+ endingScanIndex: 4,
1120
+ });
1121
+ res.should.not.be.empty();
1122
+ res.txRequests.length.should.equal(1);
1123
+ const unsignedTx = res.txRequests[0].transactions[0].unsignedTx;
1124
+ unsignedTx.should.hasOwnProperty('serializedTx');
1125
+ const tx = new lib_1.Transaction(basecoin);
1126
+ tx.fromRawTransaction(unsignedTx.serializedTx);
1127
+ const txJson = tx.toJson();
1128
+ // Two inputs: ADA UTXO + Token UTXO
1129
+ txJson.inputs.length.should.equal(2);
1130
+ should.deepEqual(txJson.inputs[0].transaction_id, resources_1.testnetUTXO.UTXO_1.tx_hash);
1131
+ should.deepEqual(txJson.inputs[1].transaction_id, resources_1.testnetUTXO.UTXO_TOKEN.tx_hash);
1132
+ // Two outputs: token output (with multiAssets) + pure ADA change to base address
1133
+ txJson.outputs.length.should.equal(2);
1134
+ const tokenOutput = txJson.outputs.find((o) => o.multiAssets !== undefined);
1135
+ should.exist(tokenOutput);
1136
+ should.deepEqual(tokenOutput.address, baseAddr);
1137
+ should.deepEqual(Number(tokenOutput.amount), minADAForToken);
1138
+ const expectedPolicyId = CardanoWasm.ScriptHash.from_bytes(Buffer.from(tokenPolicyId, 'hex'));
1139
+ const expectedAssetName = CardanoWasm.AssetName.new(Buffer.from(tokenEncodedAssetName, 'hex'));
1140
+ tokenOutput.multiAssets
1141
+ .get_asset(expectedPolicyId, expectedAssetName)
1142
+ .to_str()
1143
+ .should.equal(tokenQuantity);
1144
+ const adaOutput = txJson.outputs.find((o) => o.multiAssets === undefined);
1145
+ should.exist(adaOutput);
1146
+ should.deepEqual(adaOutput.address, baseAddr);
1147
+ const fee = Number(tx.explainTransaction().fee.fee);
1148
+ const totalBalance = resources_1.testnetUTXO.UTXO_1.value + resources_1.testnetUTXO.UTXO_TOKEN.value;
1149
+ should.deepEqual(Number(adaOutput.amount), totalBalance - minADAForToken - fee);
1150
+ // parsedTx inputs must carry multiAssets for the token UTXO
1151
+ const parsedTxInputs = unsignedTx.parsedTx.inputs;
1152
+ parsedTxInputs.length.should.equal(1);
1153
+ should.deepEqual(parsedTxInputs[0].address, resources_1.consolidationWrwUser.walletAddress2);
1154
+ should.exist(parsedTxInputs[0].multiAssets);
1155
+ parsedTxInputs[0].multiAssets.length.should.equal(1);
1156
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].policy_id, tokenPolicyId);
1157
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].asset_name, tokenEncodedAssetName);
1158
+ should.deepEqual(parsedTxInputs[0].multiAssets[0].quantity, tokenQuantity);
1159
+ // parsedTx outputs must carry multiAssets for the token output
1160
+ const parsedTxOutputs = unsignedTx.parsedTx.outputs;
1161
+ const parsedTokenOutput = parsedTxOutputs.find((o) => o.multiAssets !== undefined);
1162
+ should.exist(parsedTokenOutput);
1163
+ parsedTokenOutput.multiAssets.length.should.equal(1);
1164
+ should.deepEqual(parsedTokenOutput.multiAssets[0].policy_id, tokenPolicyId);
1165
+ should.deepEqual(parsedTokenOutput.multiAssets[0].asset_name, tokenEncodedAssetName);
1166
+ should.deepEqual(parsedTokenOutput.multiAssets[0].quantity, tokenQuantity);
1167
+ // pure ADA output must not have multiAssets
1168
+ const parsedAdaOutput = parsedTxOutputs.find((o) => o.multiAssets === undefined);
1169
+ should.exist(parsedAdaOutput);
1170
+ // lastScanIndex in coinSpecific of the last txRequest
1171
+ unsignedTx.coinSpecific.should.hasOwnProperty('lastScanIndex');
1172
+ unsignedTx.coinSpecific.lastScanIndex.should.equal(3);
1173
+ });
1174
+ it('should throw error if all addresses have balance less than 1 ADA', async function () {
1175
+ sandBox.restore();
1176
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1177
+ callBack.withArgs('address_info', sinon.match.has('_addresses')).resolves({
1178
+ status: 200,
1179
+ body: [
1180
+ {
1181
+ balance: 500000,
1182
+ utxo_set: [
1183
+ {
1184
+ tx_hash: '8df8d41207980f9e21de698bd5d6c395c39e420f7de27f8539052dd34e3a28d6',
1185
+ tx_index: 0,
1186
+ value: 500000,
1187
+ },
1188
+ ],
1189
+ },
1190
+ ],
1191
+ });
1192
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1193
+ await basecoin
1194
+ .recoverConsolidations({
1195
+ userKey: resources_1.consolidationWrwUser.userKey,
1196
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1197
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1198
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1199
+ startingScanIndex: 1,
1200
+ endingScanIndex: 4,
1201
+ })
1202
+ .should.be.rejectedWith('Did not find an address with funds to recover.');
1203
+ });
1204
+ it('should build even if single address has no funds', async function () {
1205
+ const res = await basecoin.recoverConsolidations({
1206
+ userKey: resources_1.consolidationWrwUser.userKey,
1207
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1208
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1209
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1210
+ startingScanIndex: 1,
1211
+ endingScanIndex: 4,
1212
+ });
1213
+ res.should.not.be.empty();
1214
+ res.transactions.length.should.equal(2);
1215
+ });
1216
+ it('should build even if single address has insufficient funds', async function () {
1217
+ const res = await basecoin.recoverConsolidations({
1218
+ userKey: resources_1.consolidationWrwUser.userKey,
1219
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1220
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1221
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1222
+ startingScanIndex: 1,
1223
+ endingScanIndex: 4,
1224
+ });
1225
+ res.should.not.be.empty();
1226
+ res.transactions.length.should.equal(2);
1227
+ });
1228
+ });
1229
+ describe('Build Consolidation Recoveries (MPCv2):', () => {
1230
+ const sandBox = sinon.createSandbox();
1231
+ const walletPassphrase = resources_1.wrwUser.walletPassphrase;
1232
+ let mpcV2UserKey;
1233
+ let mpcV2BackupKey;
1234
+ let mpcV2CommonKeyChain;
1235
+ let baseAddr;
1236
+ let mpcV2Address1;
1237
+ let mpcV2Address2;
1238
+ let mpcV2Address3;
1239
+ before(async function () {
1240
+ const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
1241
+ mpcV2UserKey = await (0, sdk_api_1.encrypt)(walletPassphrase, userDkg.getReducedKeyShare().toString('base64'));
1242
+ mpcV2BackupKey = await (0, sdk_api_1.encrypt)(walletPassphrase, backupDkg.getReducedKeyShare().toString('base64'));
1243
+ mpcV2CommonKeyChain = userDkg.getCommonKeychain();
1244
+ baseAddr = (await basecoin.getAdaAddressAndAccountId({ bitgoKey: mpcV2CommonKeyChain, index: 0 })).address;
1245
+ mpcV2Address1 = (await basecoin.getAdaAddressAndAccountId({ bitgoKey: mpcV2CommonKeyChain, index: 1 })).address;
1246
+ mpcV2Address2 = (await basecoin.getAdaAddressAndAccountId({ bitgoKey: mpcV2CommonKeyChain, index: 2 })).address;
1247
+ mpcV2Address3 = (await basecoin.getAdaAddressAndAccountId({ bitgoKey: mpcV2CommonKeyChain, index: 3 })).address;
1248
+ });
1249
+ beforeEach(function () {
1250
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1251
+ callBack
1252
+ .withArgs('address_info', { _addresses: [mpcV2Address1] })
1253
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
1254
+ callBack
1255
+ .withArgs('address_info', { _addresses: [mpcV2Address2] })
1256
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
1257
+ callBack
1258
+ .withArgs('address_info', { _addresses: [mpcV2Address3] })
1259
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO2);
1260
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1261
+ });
1262
+ afterEach(function () {
1263
+ sandBox.restore();
1264
+ });
1265
+ it('should build MPCv2 signed consolidation recoveries across 2+ funded indexes, sweeping to the MPCv2 base address', async function () {
1266
+ const getEddsaMaterialSpy = sandBox.spy(basecoin, 'getEddsaSigningMaterial');
1267
+ const res = await basecoin.recoverConsolidations({
1268
+ userKey: mpcV2UserKey,
1269
+ backupKey: mpcV2BackupKey,
1270
+ bitgoKey: mpcV2CommonKeyChain,
1271
+ walletPassphrase,
1272
+ startingScanIndex: 1,
1273
+ endingScanIndex: 4,
1274
+ });
1275
+ res.should.not.be.empty();
1276
+ res.transactions.length.should.equal(2);
1277
+ res.lastScanIndex.should.equal(3);
1278
+ const tx1 = new lib_1.Transaction(basecoin);
1279
+ tx1.fromRawTransaction(res.transactions[0].serializedTx);
1280
+ should.deepEqual(tx1.toJson().outputs[0].address, baseAddr);
1281
+ // recoverConsolidations must detect signing material exactly once at the top of the scan
1282
+ // loop, not per-iteration inside recover() — precomputedMaterial bypasses per-call detection.
1283
+ sandBox.assert.calledOnce(getEddsaMaterialSpy);
1284
+ });
1285
+ it('should leave MPCv1 base address derivation and signing unchanged (regression)', async function () {
1286
+ sandBox.restore();
1287
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1288
+ callBack
1289
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress1] })
1290
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
1291
+ callBack
1292
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress2] })
1293
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO);
1294
+ callBack
1295
+ .withArgs('address_info', { _addresses: [resources_1.consolidationWrwUser.walletAddress3] })
1296
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneUTXO2);
1297
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1298
+ const getTSSSignatureSpy = sandBox.spy(sdk_core_1.EDDSAMethods, 'getTSSSignature');
1299
+ const res = await basecoin.recoverConsolidations({
1300
+ userKey: resources_1.consolidationWrwUser.userKey,
1301
+ backupKey: resources_1.consolidationWrwUser.backupKey,
1302
+ bitgoKey: resources_1.consolidationWrwUser.bitgoKey,
1303
+ walletPassphrase: resources_1.consolidationWrwUser.walletPassphrase,
1304
+ startingScanIndex: 1,
1305
+ endingScanIndex: 4,
1306
+ });
1307
+ res.should.not.be.empty();
1308
+ sandBox.assert.called(getTSSSignatureSpy);
1309
+ const tx1 = new lib_1.Transaction(basecoin);
1310
+ tx1.fromRawTransaction(res.transactions[0].serializedTx);
1311
+ should.deepEqual(tx1.toJson().outputs[0].address, resources_1.consolidationWrwUser.walletAddress0);
1312
+ });
1313
+ it('should leave the unsigned (no passphrase) cold path unchanged when keycard is MPCv2', async function () {
1314
+ const res = await basecoin.recoverConsolidations({
1315
+ bitgoKey: mpcV2CommonKeyChain,
1316
+ startingScanIndex: 1,
1317
+ endingScanIndex: 4,
1318
+ });
1319
+ res.should.not.be.empty();
1320
+ res.txRequests.length.should.equal(2);
1321
+ });
1322
+ it('should throw missing userKey before scanning when walletPassphrase is set but userKey is omitted', async function () {
1323
+ const getEddsaMaterialSpy = sandBox.spy(basecoin, 'getEddsaSigningMaterial');
1324
+ await basecoin
1325
+ .recoverConsolidations({
1326
+ backupKey: mpcV2BackupKey,
1327
+ bitgoKey: mpcV2CommonKeyChain,
1328
+ walletPassphrase,
1329
+ startingScanIndex: 1,
1330
+ endingScanIndex: 4,
1331
+ })
1332
+ .should.be.rejectedWith('missing userKey');
1333
+ sandBox.assert.notCalled(getEddsaMaterialSpy);
1334
+ sandBox.assert.notCalled(basecoin.getDataFromNode);
1335
+ });
1336
+ });
1337
+ describe('Recover Transactions Failure:', () => {
1338
+ const destAddr = resources_1.address.address2;
1339
+ const sandBox = sinon.createSandbox();
1340
+ afterEach(function () {
1341
+ sandBox.restore();
1342
+ });
1343
+ it('should fail to recover due to not finding an address with funds', async function () {
1344
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1345
+ callBack
1346
+ .withArgs('address_info', sinon.match.has('_addresses'))
1347
+ .resolves(resources_1.endpointResponses.addressInfoResponse.ZeroUTXO);
1348
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1349
+ await basecoin
1350
+ .recover({
1351
+ userKey: resources_1.wrwUser.userKey,
1352
+ backupKey: resources_1.wrwUser.backupKey,
1353
+ bitgoKey: resources_1.wrwUser.bitgoKey,
1354
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
1355
+ recoveryDestination: destAddr,
1356
+ })
1357
+ .should.rejectedWith('Did not find address with funds to recover.');
1358
+ sandBox.assert.calledOnce(basecoin.getDataFromNode);
1359
+ });
1360
+ it('should fail to recover due to not having more than 1 ADA in funds', async function () {
1361
+ const callBack = sandBox.stub(src_1.Ada.prototype, 'getDataFromNode');
1362
+ callBack
1363
+ .withArgs('address_info', sinon.match.has('_addresses'))
1364
+ .resolves(resources_1.endpointResponses.addressInfoResponse.OneSmallUTXO);
1365
+ callBack.withArgs('tip').resolves(resources_1.endpointResponses.tipInfoResponse);
1366
+ await basecoin
1367
+ .recover({
1368
+ userKey: resources_1.wrwUser.userKey,
1369
+ backupKey: resources_1.wrwUser.backupKey,
1370
+ bitgoKey: resources_1.wrwUser.bitgoKey,
1371
+ walletPassphrase: resources_1.wrwUser.walletPassphrase,
1372
+ recoveryDestination: destAddr,
1373
+ })
1374
+ .should.rejectedWith('Insufficient funds to recover, minimum required is 1 ADA plus fees, got 834455 fees: 165545');
1375
+ sandBox.assert.calledTwice(basecoin.getDataFromNode);
1376
+ });
1377
+ });
1378
+ describe('Verify wallet address (isWalletAddress):', () => {
1379
+ const commonKeychain = 'ed312d0db4615688219c43231eb4b98d5883c0b44bcfef1956290555995ad68ef7c22917b4a8b69183864b83cc7028655cd7a70ef76d6948d809a15050054840';
1380
+ it('should verify a valid wallet address at index 0', async function () {
1381
+ const keychains = [
1382
+ {
1383
+ id: '1',
1384
+ commonKeychain: commonKeychain,
1385
+ type: 'tss',
1386
+ source: 'user',
1387
+ },
1388
+ {
1389
+ id: '2',
1390
+ commonKeychain: commonKeychain,
1391
+ type: 'tss',
1392
+ source: 'backup',
1393
+ },
1394
+ {
1395
+ id: '3',
1396
+ commonKeychain: commonKeychain,
1397
+ type: 'tss',
1398
+ source: 'bitgo',
1399
+ },
1400
+ ];
1401
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1402
+ const isValid = await basecoin.isWalletAddress({
1403
+ address,
1404
+ keychains,
1405
+ index: 0,
1406
+ });
1407
+ isValid.should.equal(true);
1408
+ });
1409
+ it('should fail to verify an address with wrong index', async function () {
1410
+ const keychains = [
1411
+ {
1412
+ id: '1',
1413
+ commonKeychain: commonKeychain,
1414
+ type: 'tss',
1415
+ source: 'user',
1416
+ },
1417
+ {
1418
+ id: '2',
1419
+ commonKeychain: commonKeychain,
1420
+ type: 'tss',
1421
+ source: 'backup',
1422
+ },
1423
+ {
1424
+ id: '3',
1425
+ commonKeychain: commonKeychain,
1426
+ type: 'tss',
1427
+ source: 'bitgo',
1428
+ },
1429
+ ];
1430
+ const isValid = await basecoin.isWalletAddress({
1431
+ address: 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq',
1432
+ keychains,
1433
+ index: 2,
1434
+ });
1435
+ isValid.should.equal(false);
1436
+ });
1437
+ it('should fail to verify a random address not from wallet', async function () {
1438
+ const keychains = [
1439
+ {
1440
+ id: '1',
1441
+ commonKeychain: commonKeychain,
1442
+ type: 'tss',
1443
+ source: 'user',
1444
+ },
1445
+ {
1446
+ id: '2',
1447
+ commonKeychain: commonKeychain,
1448
+ type: 'tss',
1449
+ source: 'backup',
1450
+ },
1451
+ {
1452
+ id: '3',
1453
+ commonKeychain: commonKeychain,
1454
+ type: 'tss',
1455
+ source: 'bitgo',
1456
+ },
1457
+ ];
1458
+ // Use a random valid ADA address not from this wallet
1459
+ const randomAddress = 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f';
1460
+ const isValid = await basecoin.isWalletAddress({
1461
+ address: randomAddress,
1462
+ keychains,
1463
+ index: 0,
1464
+ });
1465
+ isValid.should.equal(false);
1466
+ });
1467
+ it('should throw error for invalid address format', async function () {
1468
+ const keychains = [
1469
+ {
1470
+ id: '1',
1471
+ commonKeychain: commonKeychain,
1472
+ type: 'tss',
1473
+ source: 'user',
1474
+ },
1475
+ {
1476
+ id: '2',
1477
+ commonKeychain: commonKeychain,
1478
+ type: 'tss',
1479
+ source: 'backup',
1480
+ },
1481
+ {
1482
+ id: '3',
1483
+ commonKeychain: commonKeychain,
1484
+ type: 'tss',
1485
+ source: 'bitgo',
1486
+ },
1487
+ ];
1488
+ const invalidAddress = 'not_a_valid_address';
1489
+ await basecoin
1490
+ .isWalletAddress({
1491
+ address: invalidAddress,
1492
+ keychains,
1493
+ index: 0,
1494
+ })
1495
+ .should.be.rejectedWith('Invalid Cardano Address: not_a_valid_address');
1496
+ });
1497
+ it('should throw error when keychains are missing', async function () {
1498
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1499
+ await basecoin
1500
+ .isWalletAddress({
1501
+ address,
1502
+ keychains: [],
1503
+ index: 0,
1504
+ })
1505
+ .should.be.rejectedWith('missing required param keychains');
1506
+ });
1507
+ it('should throw error when commonKeychain is missing', async function () {
1508
+ const keychains = [
1509
+ {
1510
+ id: '1',
1511
+ type: 'tss',
1512
+ source: 'user',
1513
+ // commonKeychain is missing
1514
+ },
1515
+ ];
1516
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1517
+ await basecoin
1518
+ .isWalletAddress({
1519
+ address,
1520
+ keychains,
1521
+ index: 0,
1522
+ })
1523
+ .should.be.rejectedWith('missing required param commonKeychain');
1524
+ });
1525
+ it('should throw error when keychains have mismatched commonKeychains', async function () {
1526
+ const keychains = [
1527
+ {
1528
+ id: '1',
1529
+ commonKeychain: commonKeychain,
1530
+ type: 'tss',
1531
+ source: 'user',
1532
+ },
1533
+ {
1534
+ id: '2',
1535
+ commonKeychain: 'differentKeychain1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
1536
+ type: 'tss',
1537
+ source: 'backup',
1538
+ },
1539
+ ];
1540
+ const address = 'addr_test1qzvmazmpgfhjyppwlsw29zjjwazcsfk62z9zv5vsv24p0wyeh69kzsn0ygzzalqu5299ya693qnd55y2yegeqc42z7uq0ge2pq';
1541
+ await basecoin
1542
+ .isWalletAddress({
1543
+ address,
1544
+ keychains,
1545
+ index: 0,
1546
+ })
1547
+ .should.be.rejectedWith('all keychains must have the same commonKeychain for MPC coins');
1548
+ });
1549
+ it('should verify address when derivedFromParentWithSeed is present', async function () {
1550
+ const derivedFromParentWithSeed = 'testDerivationSeed123';
1551
+ const keychains = [
1552
+ {
1553
+ id: '1',
1554
+ commonKeychain: commonKeychain,
1555
+ derivedFromParentWithSeed: derivedFromParentWithSeed,
1556
+ type: 'tss',
1557
+ source: 'user',
1558
+ },
1559
+ {
1560
+ id: '2',
1561
+ commonKeychain: commonKeychain,
1562
+ derivedFromParentWithSeed: derivedFromParentWithSeed,
1563
+ type: 'tss',
1564
+ source: 'backup',
1565
+ },
1566
+ {
1567
+ id: '3',
1568
+ commonKeychain: commonKeychain,
1569
+ derivedFromParentWithSeed: derivedFromParentWithSeed,
1570
+ type: 'tss',
1571
+ source: 'bitgo',
1572
+ },
1573
+ ];
1574
+ const { address: expectedAddress } = await basecoin.getAdaAddressAndAccountId({
1575
+ bitgoKey: commonKeychain,
1576
+ index: 0,
1577
+ seed: derivedFromParentWithSeed,
1578
+ });
1579
+ const isValid = await basecoin.isWalletAddress({
1580
+ address: expectedAddress,
1581
+ keychains,
1582
+ index: 0,
1583
+ });
1584
+ isValid.should.equal(true);
1585
+ });
1586
+ it('should fail verification when derivedFromParentWithSeed is missing but address was created with seed', async function () {
1587
+ const derivedFromParentWithSeed = 'testDerivationSeed123';
1588
+ const { address: addressWithSeed } = await basecoin.getAdaAddressAndAccountId({
1589
+ bitgoKey: commonKeychain,
1590
+ index: 0,
1591
+ seed: derivedFromParentWithSeed,
1592
+ });
1593
+ const keychainsWithoutSeed = [
1594
+ {
1595
+ id: '1',
1596
+ commonKeychain: commonKeychain,
1597
+ type: 'tss',
1598
+ source: 'user',
1599
+ },
1600
+ {
1601
+ id: '2',
1602
+ commonKeychain: commonKeychain,
1603
+ type: 'tss',
1604
+ source: 'backup',
1605
+ },
1606
+ {
1607
+ id: '3',
1608
+ commonKeychain: commonKeychain,
1609
+ type: 'tss',
1610
+ source: 'bitgo',
1611
+ },
1612
+ ];
1613
+ const isValid = await basecoin.isWalletAddress({
1614
+ address: addressWithSeed,
1615
+ keychains: keychainsWithoutSeed,
1616
+ index: 0,
1617
+ });
1618
+ isValid.should.equal(false);
1619
+ });
1620
+ });
1621
+ describe('Verify token consolidation transaction:', () => {
1622
+ it('should fail to verify a spoofed token consolidation transaction with incorrect address', async () => {
1623
+ const consolidationTx = {
1624
+ txRequestId: '4fdd0cae-2563-43b1-b5cf-94865158ca10',
1625
+ walletId: '63068ed4efa63a000877f02fd4b0fa6d',
1626
+ txHex: '84a400818258204bd0f991c1532cffe31d4a10db492b43175ec326765b6b29ceee598df2b61f470001818258390087379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c87379ebc5533ebe621963c915c3cbc5f08537fcdca4af8f8ae08ed4c1a05f359ff021a00028701031a024972e1a10081825820bbacb13431b99208e6e8cdbf710147feaf06a39d71565e60b411ce9e4fa3f137584001a4ab8236563f69ff309e5786e8f39c629ed57676c692159cb2e0494c9e663355384c13c749d04c17a80ba2a45cc127df480fc64a43199a772f11acd5b14a0ff5f6',
1627
+ feeInfo: {
1628
+ fee: 10000,
1629
+ feeString: '10000',
1630
+ },
1631
+ txInfo: {
1632
+ inputs: [
1633
+ {
1634
+ address: '8iLa26KSbdpBUzNK7uYq8FvyuyA5h4k4erDHsDcPbHus',
1635
+ value: 2.0173228e10,
1636
+ valueString: '20173228000',
1637
+ },
1638
+ {
1639
+ address: '8P2kX7Tyh9eS3RKdaBhqbEtQGAX58DXzL7mhDQABGX2d',
1640
+ value: 10000,
1641
+ valueString: '10000',
1642
+ },
1643
+ ],
1644
+ minerFee: '10000',
1645
+ outputs: [
1646
+ {
1647
+ address: 'addr_test1vr8rakm66rcfv4fcxqykg5lf0yv7lsyk9mvapx369jpvtcgfcuk7f',
1648
+ coinName: 'tada:usdt',
1649
+ enterprise: {
1650
+ $oid: '5553ba8ae7a5c77006719661',
1651
+ },
1652
+ enterprises: [
1653
+ {
1654
+ $oid: '5553ba8ae7a5c77006719661',
1655
+ },
1656
+ ],
1657
+ value: 2.0173228e10,
1658
+ valueString: '20173228000',
1659
+ wallet: {
1660
+ $oid: '62f4c3720d92c50008257eb5',
1661
+ },
1662
+ walletType: 'hot',
1663
+ wallets: [
1664
+ {
1665
+ $oid: '62f4c3720d92c50008257eb5',
1666
+ },
1667
+ ],
1668
+ },
1669
+ ],
1670
+ payGoFee: '0',
1671
+ spendAmount: '20173228000',
1672
+ spendAmounts: [
1673
+ {
1674
+ amountString: '20173228000',
1675
+ coinName: 'tada:usdt',
1676
+ },
1677
+ ],
1678
+ type: 'Send',
1679
+ },
1680
+ consolidateId: '6712d7fda6de4906d658c04aebbf8f9b',
1681
+ coin: 'tada',
1682
+ };
1683
+ // Mock the wallet with a different address than the transaction's output
1684
+ const mockedWallet = {
1685
+ coinSpecific: () => {
1686
+ return {
1687
+ rootAddress: 'addr_test1qqnnvptrc3rec64q2n9jh572ncu5wvdtt8uvg4g3aj96s5dwu9nj70mlahzglm9939uevupsmj8dcdqv25d5n5r8vw8sn7prey',
1688
+ };
1689
+ },
1690
+ };
1691
+ await basecoin
1692
+ .verifyTransaction({
1693
+ txParams: {},
1694
+ txPrebuild: consolidationTx,
1695
+ wallet: mockedWallet,
1696
+ verification: {
1697
+ consolidationToBaseAddress: true,
1698
+ },
1699
+ })
1700
+ .should.be.rejectedWith('tx outputs does not match with expected address');
1701
+ });
1702
+ });
1703
+ });
1704
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2FkYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUgsaUNBQWtDO0FBQ2xDLDBEQUE2QjtBQUM3QixtQ0FBcUM7QUFDckMsNkNBQStCO0FBQy9CLG1EQUErRDtBQUMvRCxpREFBd0Q7QUFDeEQsNENBWXNCO0FBQ3RCLDBDQUE0QjtBQUM1QixzRkFBd0U7QUFDeEUsbUNBQStDO0FBQy9DLHVDQUE0QztBQUM1QywwRUFBa0Y7QUFDbEYsb0RBQTRCO0FBQzVCLG1EQUFvRTtBQUNwRSx5REFBa0Q7QUFDbEQsZ0RBQXdCO0FBRXhCLFFBQVEsQ0FBQyxLQUFLLEVBQUU7SUFDZCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDdkIsTUFBTSxTQUFTLEdBQUcsR0FBRyxHQUFHLFFBQVEsQ0FBQztJQUNqQyxJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxRQUFRLENBQUM7SUFDYixJQUFJLGFBQWEsQ0FBQztJQUNsQixJQUFJLFdBQVcsQ0FBQztJQUVoQixNQUFNLFVBQVUsR0FBRztRQUNqQixLQUFLLEVBQUUsaUJBQUssQ0FBQyxVQUFVO1FBQ3ZCLE1BQU0sRUFBRSxFQUFFO0tBQ1gsQ0FBQztJQUVGLE1BQU0sUUFBUSxHQUFHO1FBQ2YsVUFBVSxFQUFFO1lBQ1Y7Z0JBQ0UsT0FBTyxFQUFFLGlCQUFLLENBQUMsY0FBYyxDQUFDLE9BQU87Z0JBQ3JDLE1BQU0sRUFBRSxTQUFTO2FBQ2xCO1lBQ0Q7Z0JBQ0UsT0FBTyxFQUFFLGlCQUFLLENBQUMsY0FBYyxDQUFDLE9BQU87Z0JBQ3JDLE1BQU0sRUFBRSxXQUFXO2FBQ3BCO1NBQ0Y7S0FDRixDQUFDO0lBRUYsTUFBTSxzQkFBc0IsR0FBRztRQUM3QixZQUFZLEVBQUUsQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFLGNBQWMsRUFB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RSxXQUFXO3lCQUN0QjtxQkFDRjtvQkFDRCxJQUFJLEVBQUUsTUFBTTtpQkFDYjtnQkFDRCxhQUFhLEVBQUUsa0NBQWtDO2dCQUNqRCxJQUFJLEVBQUUsTUFBTTthQUNiLENBQUM7WUFFRix5RUFBeUU7WUFDekUsTUFBTSxZQUFZLEdBQUc7Z0JBQ25CLFlBQVksRUFBRSxHQUFHLEVBQUU7b0JBQ2pCLE9BQU87d0JBQ0wsV0FBVyxFQUNULDhHQUE4RztxQkFDakgsQ0FBQztnQkFDSixDQUFDO2FBQ0YsQ0FBQztZQUVGLE1BQU0sUUFBUTtpQkFDWCxpQkFBaUIsQ0FBQztnQkFDakIsUUFBUSxFQUFFLEVBQUU7Z0JBQ1osVUFBVSxFQUFFLGVBQWU7Z0JBQzNCLE1BQU0sRUFBRSxZQUFZO2dCQUNwQixZQUFZLEVBQUU7b0JBQ1osMEJBQTBCLEVBQUUsSUFBSTtpQkFDakM7YUFDRixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGlEQUFpRCxDQUFDLENBQUM7UUFDL0UsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuXG5pbXBvcnQgc2hvdWxkID0gcmVxdWlyZSgnc2hvdWxkJyk7XG5pbXBvcnQgbmFjbCBmcm9tICd0d2VldG5hY2wnO1xuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHb0FQSSwgZW5jcnlwdCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuaW1wb3J0IHtcbiAgYWRkcmVzcyxcbiAgY29uc29saWRhdGlvbldyd1VzZXIsXG4gIGVuZHBvaW50UmVzcG9uc2VzLFxuICBlbnRlcnByaXNlQWNjb3VudHMgYXMgYWNjb3VudHMsXG4gIG92Y1Jlc3BvbnNlLFxuICBvdmNSZXNwb25zZTIsXG4gIHByaXZhdGVLZXlzLFxuICBwdWJsaWNLZXlzLFxuICByYXdUeCxcbiAgdGVzdG5ldFVUWE8sXG4gIHdyd1VzZXIsXG59IGZyb20gJy4uL3Jlc291cmNlcyc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgKiBhcyBDYXJkYW5vV2FzbSBmcm9tICdAZW11cmdvL2NhcmRhbm8tc2VyaWFsaXphdGlvbi1saWItbm9kZWpzJztcbmltcG9ydCB7IEFkYSwgS2V5UGFpciwgVGFkYSB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uL3NyYy9saWInO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25UeXBlIH0gZnJvbSAnLi4vLi4vLi4vc2RrLWNvcmUvc3JjL2FjY291bnQtbGliL2Jhc2VDb2luL2VudW0nO1xuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgY29tbW9uLCBFRERTQU1ldGhvZHMsIFdhbGxldCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IE1QU1V0aWwgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstbGliLW1wYyc7XG5pbXBvcnQgbm9jayBmcm9tICdub2NrJztcblxuZGVzY3JpYmUoJ0FEQScsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgY29pbk5hbWUgPSAnYWRhJztcbiAgY29uc3QgdGNvaW5OYW1lID0gJ3QnICsgY29pbk5hbWU7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgYmFzZWNvaW47XG4gIGxldCBuZXdUeFByZWJ1aWxkO1xuICBsZXQgbmV3VHhQYXJhbXM7XG5cbiAgY29uc3QgdHhQcmVidWlsZCA9IHtcbiAgICB0eEhleDogcmF3VHgudW5zaWduZWRUeCxcbiAgICB0eEluZm86IHt9LFxuICB9O1xuXG4gIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgIHJlY2lwaWVudHM6IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogcmF3VHgub3V0cHV0QWRkcmVzczEuYWRkcmVzcyxcbiAgICAgICAgYW1vdW50OiAnNTAwMDAwMCcsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBhZGRyZXNzOiByYXdUeC5vdXRwdXRBZGRyZXNzMi5hZGRyZXNzLFxuICAgICAgICBhbW91bnQ6ICcyNDgzMjkxNTAnLFxuICAgICAgfSxcbiAgICBdLFxuICB9O1xuXG4gIGNvbnN0IHRyYW5zYWN0aW9uRXhwbGFuYXRpb24gPSB7XG4gICAgZGlzcGxheU9yZGVyOiBbJ2lkJywgJ291dHB1dEFtb3VudCcsICdjaGFuZ2VBbW91bnQnLCAnb3V0cHV0cycsICdjaGFuZ2VPdXRwdXRzJywgJ2ZlZScsICd0eXBlJ10sXG4gICAgaWQ6ICdmNDhmNmVhMGY3NWYzZjk0Mjg1NWNjMGVkZjI5ZTgxZTFlMDcyNGU3NWY1ZGI4YTE1NzViMTY2ZmIyMDIxNzZjJyxcbiAgICBvdXRwdXRzOiBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6XG4gICAgICAgICAgJ2FkZHJfdGVzdDFxcW5udnB0cmMzcmVjNjRxMm45amg1NzJuY3U1d3ZkdHQ4dXZnNGczYWo5NnM1ZHd1OW5qNzBtbGFoemdsbTk5Mzl1ZXZ1cHNtajhkY2RxdjI1ZDVuNXI4dnc4c243cHJleScsXG4gICAgICAgIGFtb3VudDogJzc4MjMxMjEnLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogJ2FkZHJfdGVzdDF2cjhyYWttNjZyY2Z2NGZjeHF5a2c1bGYweXY3bHN5azltdmFweDM2OWpwdnRjZ2ZjdWs3ZicsXG4gICAgICAgIGFtb3VudDogJzEzMDQxNzI5JyxcbiAgICAgIH0sXG4gICAgXSxcbiAgICBvdXRwdXRBbW91bnQ6ICcyMDg2NDg1MCcsXG4gICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgY2hhbmdlQW1vdW50OiAnMCcsXG4gICAgZmVlOiB7IGZlZTogJzE2NzE3MycgfSxcbiAgICB0eXBlOiAnVHJhbnNmZXInLFxuICAgIGNlcnRpZmljYXRlczogW10sXG4gICAgd2l0aGRyYXdhbHM6IFtdLFxuICAgIHBsZWRnZURldGFpbHM6IHVuZGVmaW5lZCxcbiAgfTtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJpdGdvLnNhZmVSZWdpc3Rlcihjb2luTmFtZSwgQWRhLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIodGNvaW5OYW1lLCBUYWRhLmNyZWF0ZUluc3RhbmNlKTtcbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4odGNvaW5OYW1lKTtcbiAgICBuZXdUeFByZWJ1aWxkID0gKCkgPT4ge1xuICAgICAgcmV0dXJuIF8uY2xvbmVEZWVwKHR4UHJlYnVpbGQpO1xuICAgIH07XG4gICAgbmV3VHhQYXJhbXMgPSAoKSA9PiB7XG4gICAgICByZXR1cm4gXy5jbG9uZURlZXAodHhQYXJhbXMpO1xuICAgIH07XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgaW5zdGFudGlhdGUgdGhlIGNvaW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGxvY2FsQmFzZWNvaW4gPSBiaXRnby5jb2luKHRjb2luTmFtZSk7XG4gICAgbG9jYWxCYXNlY29pbi5zaG91bGQuYmUuYW4uaW5zdGFuY2VvZihUYWRhKTtcbiAgICBsb2NhbEJhc2Vjb2luLmdldENoYWluKCkuc2hvdWxkLmVxdWFsKHRjb2luTmFtZSk7XG4gICAgbG9jYWxCYXNlY29pbi5nZXRGdWxsTmFtZSgpLnNob3VsZC5lcXVhbCgnVGVzdG5ldCBBZGEnKTtcblxuICAgIGxvY2FsQmFzZWNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lKTtcbiAgICBsb2NhbEJhc2Vjb2luLnNob3VsZC5iZS5hbi5pbnN0YW5jZW9mKEFkYSk7XG4gICAgbG9jYWxCYXNlY29pbi5nZXRDaGFpbigpLnNob3VsZC5lcXVhbChjb2luTmFtZSk7XG4gICAgbG9jYWxCYXNlY29pbi5nZXRGdWxsTmFtZSgpLnNob3VsZC5lcXVhbCgnQ2FyZGFubyBBREEnKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1NpZ24gTWVzc2FnZScsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJlIHBlcmZvcm1lZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgS2V5UGFpcigpO1xuICAgICAgY29uc3QgbWVzc2FnZVRvU2lnbiA9IEJ1ZmZlci5mcm9tKHJhbmRvbUJ5dGVzKDMyKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2Uoa2V5UGFpci5nZXRLZXlzKCksIG1lc3NhZ2VUb1NpZ24pO1xuICAgICAga2V5UGFpci52ZXJpZnlTaWduYXR1cmUobWVzc2FnZVRvU2lnbiwgVWludDhBcnJheS5mcm9tKHNpZ25hdHVyZSkpLnNob3VsZC5lcXVhbHMoZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHdpdGggbWlzc2luZyBwcml2YXRlIGtleScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgS2V5UGFpcih7XG4gICAgICAgIHB1YjogJzc3ODgzMjdjNjk1ZGNhNGIzZTY0OWEwZGI0NWJjM2U3MDNhMmM2NzQyOGZjZTM2MGU2MTgwMGNjNDI0OGY0ZjcnLFxuICAgICAgfSkuZ2V0S2V5cygpO1xuICAgICAgY29uc3QgbWVzc2FnZVRvU2lnbiA9IEJ1ZmZlci5mcm9tKHJhbmRvbUJ5dGVzKDMyKSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgYXdhaXQgYmFzZWNvaW4uc2lnbk1lc3NhZ2Uoa2V5UGFpciwgbWVzc2FnZVRvU2lnbikuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCBrZXkgcGFpciBvcHRpb25zJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTaWduIHRyYW5zYWN0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc2lnbiB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogcmF3VHgudW5zaWduZWRUeDIsXG4gICAgICAgIH0sXG4gICAgICAgIHB1YnM6IFtwdWJsaWNLZXlzLnB1YktleTFdLFxuICAgICAgICBwcnY6IHByaXZhdGVLZXlzLnBydktleTQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZC50eEhleC5zaG91bGQuZXF1YWwocmF3VHguc2lnbmVkVHgyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBzaWduIHRyYW5zYWN0aW9uIHdpdGggYW4gaW52YWxpZCBrZXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiByYXdUeC51bnNpZ25lZFR4MixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHB1YnM6IFtwdWJsaWNLZXlzLnB1YktleTFdLFxuICAgICAgICAgIHBydjogcHJpdmF0ZUtleXMucHJ2S2V5MixcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHNob3VsZC5lcXVhbChlLm1lc3NhZ2UsICdQcml2YXRlIGtleSBjYW5ub3Qgc2lnbiB0aGUgdHJhbnNhY3Rpb24nKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBidWlsZCB0cmFuc2FjdGlvbiB3aXRoIG1pc3NpbmcgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogcmF3VHgudW5zaWduZWRUeCxcbiAgICAgICAgICAgIGtleTogYWNjb3VudHMuYWNjb3VudDEucHVibGljS2V5LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcHJ2OiBhY2NvdW50cy5hY2NvdW50MS5zZWNyZXRLZXksXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBzaG91bGQubm90RXF1YWwoZSwgbnVsbCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZW5lcmF0ZSB3YWxsZXQga2V5IHBhaXI6ICcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleSBwYWlyJywgKCkgPT4ge1xuICAgICAgY29uc3Qga3AgPSBiYXNlY29pbi5nZW5lcmF0ZUtleVBhaXIoKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQdWIoa3AucHViKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHJ2KGtwLnBydikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBrZXkgcGFpciBmcm9tIHNlZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oJzlkNjFiMTlkZWZmZDVhNjBiYTg0NGFmNDkyZWMyY2M0NDQ0OWM1Njk3YjMyNjkxOTcwM2JhYzAzMWNhZTdmNjAnLCAnaGV4Jyk7XG4gICAgICBjb25zdCBrcCA9IGJhc2Vjb2luLmdlbmVyYXRlS2V5UGFpcihzZWVkKTtcbiAgICAgIGJhc2Vjb2luLmlzVmFsaWRQdWIoa3AucHViKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBiYXNlY29pbi5pc1ZhbGlkUHJ2KGtwLnBydikuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IHRyYW5zYWN0aW9uOiAnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBzdWNjZWVkIHRvIHZlcmlmeSB1bnNpZ25lZCB0cmFuc2FjdGlvbiBpbiBoZXggZW5jb2RpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNhY3Rpb25WZXJpZmllZCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQsIHZlcmlmaWNhdGlvbiB9KTtcbiAgICAgIGlzVHJhbnNhY3Rpb25WZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHNpZ25lZCB0cmFuc2FjdGlvbiBpbiBoZXggZW5jb2RpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0ge1xuICAgICAgICB0eEhleDogcmF3VHguc2lnbmVkVHgsXG4gICAgICAgIHR4SW5mbzoge30sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IG5ld1R4UGFyYW1zKCk7XG4gICAgICBjb25zdCB2ZXJpZmljYXRpb24gPSB7fTtcblxuICAgICAgY29uc3QgaXNUcmFuc2FjdGlvblZlcmlmaWVkID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgdmVyaWZpY2F0aW9uIH0pO1xuICAgICAgaXNUcmFuc2FjdGlvblZlcmlmaWVkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB2ZXJpZnkgdHJhbnNhY3Rpb25zIHdoZW4gaGF2ZSBkaWZmZXJlbnQgcmVjaXBpZW50cycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBuZXdUeFByZWJ1aWxkKCk7XG5cbiAgICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJzlmN2IwNjc1ZGI1OWQxOWI0YmQ5YzhjNzJlYWFiYmE3NWE5ODYzZDAyYjMwMTE1YjhiM2MzY2E1YzIwZjAyNTQnLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnOWY3YjA2NzVkYjU5ZDE5YjRiZDljOGM3MmVhYWJiYTc1YTk4NjNkMDJiMzAxMTViOGIzYzNjYTVjMjBmMDI1NCcsXG4gICAgICAgICAgICBhbW91bnQ6ICcyMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdmVyaWZpY2F0aW9uID0ge307XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB2ZXJpZmljYXRpb24gfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2Nhbm5vdCBmaW5kIHJlY2lwaWVudCBpbiBleHBlY3RlZCBvdXRwdXQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IHdoZW4gaW5wdXQgYHJlY2lwaWVudHNgIGlzIGFic2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UGFyYW1zID0gbmV3VHhQYXJhbXMoKTtcbiAgICAgIHR4UGFyYW1zLnJlY2lwaWVudHMgPSB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgY29uc3QgdmFsaWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB2ZXJpZnkgd2hlbiB0eEhleCBpcyBpbnZhbGlkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgdHhQYXJhbXMucmVjaXBpZW50cyA9IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7fTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7IHR4UGFyYW1zLCB0eFByZWJ1aWxkIH0pXG4gICAgICAgIC5zaG91bGQucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHJlcXVpcmVkIHR4IHByZWJ1aWxkIHByb3BlcnR5IHR4SGV4Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gdmVyaWZ5IHRyYW5zYWN0aW9ucyB3aGVuIHJlY2lwaWVudHMgaGFzIGV4dHJhIGRhdGEnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eFByZWJ1aWxkID0gbmV3VHhQcmVidWlsZCgpO1xuICAgICAgY29uc3QgdHhQYXJhbXMgPSBuZXdUeFBhcmFtcygpO1xuICAgICAgdHhQYXJhbXMuZGF0YSA9ICdkYXRhJztcblxuICAgICAgY29uc3QgdmFsaWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQYXJhbXMsIHR4UHJlYnVpbGQgfSk7XG4gICAgICB2YWxpZFRyYW5zYWN0aW9uLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgY29uc29saWRhdGlvbiB0cmFuc2FjdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNvbnNvbGlkYXRpb25UeCA9IHtcbiAgICAgICAgdHhSZXF1ZXN0SWQ6ICcxYjVjNzljNS1hYjdjLTRmNDctOTEyYi1kZTZhOTVmYjA3NzknLFxuICAgICAgICB3YWxsZXRJZDogJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYicsXG4gICAgICAgIHR4SGV4OlxuICAgICAgICAgICc4NGE0MDA4MTgyNTgyMGRiNDZjN2M3NmVhNTRmZWMyY2EwYTJmOTRiNzdhMjM4OTMxYThkY2UyMzg3Yzk5YTEyYjA4ZGQ4YWFjMjFjNGYwMDAxODE4MjU4MzkwMDQ2MDFmYzAxNmFjMzg1ODA5MTZkMzUyMGJjNzZiNjU5Mjk4MTU2MDA4NzM4ZDM0N2FhOTMxNDJmNDYwMWZjMDE2YWMzODU4MDkxNmQzNTIwYmM3NmI2NTkyOTgxNTYwMDg3MzhkMzQ3YWE5MzE0MmYxYTNiOTg0MzU3MDIxYTAwMDI4NmE5MDMxYTA2MGUzN2VlYTBmNWY2JyxcbiAgICAgICAgZmVlSW5mbzoge1xuICAgICAgICAgIGZlZTogMTY1NTQ1LFxuICAgICAgICAgIGZlZVN0cmluZzogJzE2NTU0NScsXG4gICAgICAgIH0sXG4gICAgICAgIHR4SW5mbzoge1xuICAgICAgICAgIG1pbmVyRmVlOiAnMTY1NTQ1JyxcbiAgICAgICAgICBzcGVuZEFtb3VudDogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgc3BlbmRBbW91bnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYScsXG4gICAgICAgICAgICAgIGFtb3VudFN0cmluZzogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgcGF5R29GZWU6ICcwJyxcbiAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6XG4gICAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcHJxcmxxcGR0cGN0cXkzZDU2anAwcmtrZXZqbnEya3F6cm4zNTY4NDJmM2d0NnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc2pkbWcycycsXG4gICAgICAgICAgICAgIHZhbHVlOiA5OTk4MzQ0NTUsXG4gICAgICAgICAgICAgIHdhbGxldDogJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYicsXG4gICAgICAgICAgICAgIHdhbGxldHM6IFsnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJ10sXG4gICAgICAgICAgICAgIGVudGVycHJpc2U6ICc2MmNjNTliNzI3NDQzYTAwMDcwODkwMzMnLFxuICAgICAgICAgICAgICBlbnRlcnByaXNlczogWyc2MmNjNTliNzI3NDQzYTAwMDcwODkwMzMnXSxcbiAgICAgICAgICAgICAgdmFsdWVTdHJpbmc6ICc5OTk4MzQ0NTUnLFxuICAgICAgICAgICAgICBjb2luTmFtZTogJ3RhZGEnLFxuICAgICAgICAgICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgICAgICAgICAgd2FsbGV0VHlwZXM6IFsnaG90J10sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgaW5wdXRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHZhbHVlOiAxMDAwMDAwMDAwLFxuICAgICAgICAgICAgICBhZGRyZXNzOlxuICAgICAgICAgICAgICAgICdhZGRyX3Rlc3QxcXFsenhmbDd0bGdwOTk5eDRhNzMzNHBjaHljcGtrNzJweWtyc3IzbXJ5bDN5ajZ4cTg3cXo2a3Jza3Fmem1mNHl6NzhkZGplOXhxNHZxeTg4cmY1MDI1bnpzaHN2cGdsOHcnLFxuICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzEwMDAwMDAwMDAnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHR5cGU6ICcwJyxcbiAgICAgICAgfSxcbiAgICAgICAgY29uc29saWRhdGVJZDogJzY4YjlmYzE4NTU4MDA2YWFiNTM3ODU2MTVmZWE3YzI4JyxcbiAgICAgICAgY29pbjogJ3RhZGEnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgbW9ja2VkV2FsbGV0ID0ge1xuICAgICAgICBjb2luU3BlY2lmaWM6ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm9vdEFkZHJlc3M6XG4gICAgICAgICAgICAgICdhZGRyX3Rlc3QxcXBycXJscXBkdHBjdHF5M2Q1NmpwMHJra2V2am5xMmtxenJuMzU2ODQyZjNndDZ4cTg3cXo2a3Jza3Fmem1mNHl6NzhkZGplOXhxNHZxeTg4cmY1MDI1bnpzaHNqZG1nMnMnLFxuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBpc1ZlcmlmaWVkID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7fSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBjb25zb2xpZGF0aW9uVHgsXG4gICAgICAgICAgd2FsbGV0OiBtb2NrZWRXYWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7XG4gICAgICAgICAgICBjb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzczogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgaXNWZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGFzc2VydC5mYWlsKCdUcmFuc2FjdGlvbiBzaG91bGQgcGFzcyB2ZXJpZmljYXRpb24nKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgc3BvbnNvcmVkIGNvbnNvbGlkYXRpb24gdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjb25zb2xpZGF0aW9uVHggPSB7XG4gICAgICAgIHR4UmVxdWVzdElkOiAnMWI1Yzc5YzUtYWI3Yy00ZjQ3LTkxMmItZGU2YTk1ZmIwNzc5JyxcbiAgICAgICAgd2FsbGV0SWQ6ICc2NGZhMzFhOTRkYjY1YTAwMDdjOTY5MWInLFxuICAgICAgICB0eEhleDpcbiAgICAgICAgICAnODRhNDAwODI4MjU4MjAyMjdmNjVkMjBhYzZlNDk2MDJkNzljNjIzYzUxOTExZWFkODI0MjM1ZTAxZWIyYTFlN2UzM2E3MmYwNzQ3Y2JiMDA4MjU4MjAyMjdmNjVkMjBhYzZlNDk2MDJkNzljNjIzYzUxOTExZWFkODI0MjM1ZTAxZWIyYTFlN2UzM2E3MmYwNzQ3Y2JiMDIwMTgyODI1ODM5MDAyMjA5ODI3MGE1YzE5YzlmYjcwNmRjZTBlN2U0NTY2YjIzNGVjNWYwMDEwNjIzY2Q2M2YxOThhZDIyMDk4MjcwYTVjMTljOWZiNzA2ZGNlMGU3ZTQ1NjZiMjM0ZWM1ZjAwMTA2MjNjZDYzZjE5OGFkMWEwMDk4OTY4MDgyNTgxZDYwY2Y5MGY5ZmIwMmM4OGJhZDNjNTI5NGQ5MDU4NzQ1OGM0ZjE2MGEyZGIyNmJhOGFmM2RhMjU1YjExYTA1ZDQyZmI4MDIxYTAwMDJhNDkxMDMxYTA2ZDhjMDQ4YTBmNWY2JyxcbiAgICAgICAgZmVlSW5mbzoge1xuICAgICAgICAgIGZlZTogMTY1NTQ1LFxuICAgICAgICAgIGZlZVN0cmluZzogJzE2NTU0NScsXG4gICAgICAgIH0sXG4gICAgICAgIHR4SW5mbzoge1xuICAgICAgICAgIG1pbmVyRmVlOiAnMTY1NTQ1JyxcbiAgICAgICAgICBzcGVuZEFtb3VudDogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgc3BlbmRBbW91bnRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYScsXG4gICAgICAgICAgICAgIGFtb3VudFN0cmluZzogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgcGF5R29GZWU6ICcwJyxcbiAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6XG4gICAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcHJxcmxxcGR0cGN0cXkzZDU2anAwcmtrZXZqbnEya3F6cm4zNTY4NDJmM2d0NnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc2pkbWcycycsXG4gICAgICAgICAgICAgIHZhbHVlOiA5OTk4MzQ0NTUsXG4gICAgICAgICAgICAgIHdhbGxldDogJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYicsXG4gICAgICAgICAgICAgIHdhbGxldHM6IFsnNjRmYTMxYTk0ZGI2NWEwMDA3Yzk2OTFiJ10sXG4gICAgICAgICAgICAgIGVudGVycHJpc2U6ICc2MmNjNTliNzI3NDQzYTAwMDcwODkwMzMnLFxuICAgICAgICAgICAgICBlbnRlcnByaXNlczogWyc2MmNjNTliNzI3NDQzYTAwMDcwODkwMzMnXSxcbiAgICAgICAgICAgICAgdmFsdWVTdHJpbmc6ICc5OTk4MzQ0NTUnLFxuICAgICAgICAgICAgICBjb2luTmFtZTogJ3RhZGEnLFxuICAgICAgICAgICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgICAgICAgICAgd2FsbGV0VHlwZXM6IFsnaG90J10sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgaW5wdXRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHZhbHVlOiAxMDAwMDAwMDAwLFxuICAgICAgICAgICAgICBhZGRyZXNzOlxuICAgICAgICAgICAgICAgICdhZGRyX3Rlc3QxcXFsenhmbDd0bGdwOTk5eDRhNzMzNHBjaHljcGtrNzJweWtyc3IzbXJ5bDN5ajZ4cTg3cXo2a3Jza3Fmem1mNHl6NzhkZGplOXhxNHZxeTg4cmY1MDI1bnpzaHN2cGdsOHcnLFxuICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzEwMDAwMDAwMDAnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIHR5cGU6ICcwJyxcbiAgICAgICAgICBmZWVBZGRyZXNzOiAnYWRkcl90ZXN0MXZyOGVwNzBtcXR5Z2h0ZnUyMjJkanB2OGdreHk3OXMyOWtleGgyOTA4azM5dHZnZTAyZDVqJyxcbiAgICAgICAgfSxcbiAgICAgICAgY29uc29saWRhdGVJZDogJzY4YjlmYzE4NTU4MDA2YWFiNTM3ODU2MTVmZWE3YzI4JyxcbiAgICAgICAgY29pbjogJ3RhZGEnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgbW9ja2VkV2FsbGV0ID0ge1xuICAgICAgICBjb2luU3BlY2lmaWM6ICgpID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm9vdEFkZHJlc3M6XG4gICAgICAgICAgICAgICdhZGRyX3Rlc3QxcXEzcW5xbnM1aHFlZThhaHFtd3dwZWx5MmU0anhuazk3cXFzdmc3ZHYwY2UzdGZ6cHhwOHBmd3BuajBtd3BrdXVybjdnNG50eWQ4dnR1cXBxYzN1NmNsM256a3N2Z2d1ODInLFxuICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBpc1ZlcmlmaWVkID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7fSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiBjb25zb2xpZGF0aW9uVHgsXG4gICAgICAgICAgd2FsbGV0OiBtb2NrZWRXYWxsZXQsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uOiB7XG4gICAgICAgICAgICBjb25zb2xpZGF0aW9uVG9CYXNlQWRkcmVzczogdHJ1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgaXNWZXJpZmllZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGFzc2VydC5mYWlsKCdUcmFuc2FjdGlvbiBzaG91bGQgcGFzcyB2ZXJpZmljYXRpb24nKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBzaWduIGEgc3Bvb2ZlZCBjb25zb2xpZGF0aW9uIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gU2V0IHVwIHdhbGxldCBkYXRhXG4gICAgICBjb25zdCB3YWxsZXREYXRhID0ge1xuICAgICAgICBpZDogJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJyxcbiAgICAgICAgY29pbjogJ3RhZGEnLFxuICAgICAgICBrZXlzOiBbXG4gICAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NTAwMDAwMDAwJyxcbiAgICAgICAgICAnNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc2MDAwMDAwMDAnLFxuICAgICAgICAgICc1YjM0MjRmOTFiZjM0OTkzMGUzNDAxNzcwMDAwMDAwMCcsXG4gICAgICAgIF0sXG4gICAgICAgIGNvaW5TcGVjaWZpYzoge1xuICAgICAgICAgIHJvb3RBZGRyZXNzOlxuICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcHJxcmxxcGR0cGN0cXkzZDU2anAwcmtrZXZqbnEya3F6cm4zNTY4NDJmM2d0NnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc2pkbWcycycsXG4gICAgICAgIH0sXG4gICAgICAgIG11bHRpc2lnVHlwZTogJ3RzcycsXG4gICAgICB9O1xuICAgICAgY29uc3QgZmFrZVBydiA9IGF3YWl0IGVuY3J5cHQoJ3Bhc3N3b3JkJywgJ3BydicpO1xuXG4gICAgICBjb25zdCB3YWxsZXRPYmogPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlY29pbiwgd2FsbGV0RGF0YSk7XG4gICAgICBjb25zdCBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbJ21vY2snXS51cmk7XG5cbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoJy9hcGkvdjIvdGFkYS9rZXkvNWIzNDI0ZjkxYmYzNDk5MzBlMzQwMTc1MDAwMDAwMDAnKVxuICAgICAgICAucmVwbHkoMjAwLCBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZW5jcnlwdGVkUHJ2OiBmYWtlUHJ2LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuXG4gICAgICAvLyBNb2NrIHRoZSBBUEkgcmVzcG9uc2UgZm9yIGJ1aWxkQWNjb3VudENvbnNvbGlkYXRpb25zXG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAucG9zdCgnL2FwaS92Mi90YWRhL3dhbGxldC81YjM0MjUyZjFiZjM0OTkzMGUzNDAyMGEwMDAwMDAwMC9jb25zb2xpZGF0ZUFjY291bnQvYnVpbGQnKVxuICAgICAgICAucmVwbHkoMjAwLCBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHhSZXF1ZXN0SWQ6ICcxYjVjNzljNS1hYjdjLTRmNDctOTEyYi1kZTZhOTVmYjA3NzknLFxuICAgICAgICAgICAgd2FsbGV0SWQ6ICc2NGZhMzFhOTRkYjY1YTAwMDdjOTY5MWInLFxuICAgICAgICAgICAgdHhIZXg6XG4gICAgICAgICAgICAgICc4NGE0MDA4MTgyNTgyMGRiNDZjN2M3NmVhNTRmZWMyY2EwYTJmOTRiNzdhMjM4OTMxYThkY2UyMzg3Yzk5YTEyYjA4ZGQ4YWFjMjFjNGYwMTAxODI4MjU4MWQ2MDMzYzM3OGNlZTQxYjJlMTVhYzg0OGY3ZjZmMWQyZjc4MTU1YWIxMmQ5M2I3MTNkZTg5OGQ4NTVmMWEwMDk4OTY4MDgyNTgzOTAwNDYwMWZjMDE2YWMzODU4MDkxNmQzNTIwYmM3NmI2NTkyOTgxNTYwMDg3MzhkMzQ3YWE5MzE0MmY0NjAxZmMwMTZhYzM4NTgwOTE2ZDM1MjBiYzc2YjY1OTI5ODE1NjAwODczOGQzNDdhYTkzMTQyZjFiMDAwMDAwMDIxN2FjZWJlOTAyMWEwMDAyOGRiNTAzMWEwNjBlM2I0MWEwZjVmNicsXG4gICAgICAgICAgICBmZWVJbmZvOiB7XG4gICAgICAgICAgICAgIGZlZTogMTY1NTQ1LFxuICAgICAgICAgICAgICBmZWVTdHJpbmc6ICcxNjU1NDUnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHR4SW5mbzoge1xuICAgICAgICAgICAgICBtaW5lckZlZTogJzE2NTU0NScsXG4gICAgICAgICAgICAgIHNwZW5kQW1vdW50OiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICAgICAgc3BlbmRBbW91bnRzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgY29pbk5hbWU6ICd0YWRhJyxcbiAgICAgICAgICAgICAgICAgIGFtb3VudFN0cmluZzogJzk5OTgzNDQ1NScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgcGF5R29GZWU6ICcwJyxcbiAgICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGFkZHJlc3M6XG4gICAgICAgICAgICAgICAgICAgICdhZGRyX3Rlc3QxcXBycXJscXBkdHBjdHF5M2Q1NmpwMHJra2V2am5xMmtxenJuMzU2ODQyZjNndDZ4cTg3cXo2a3Jza3Fmem1mNHl6NzhkZGplOXhxNHZxeTg4cmY1MDI1bnpzaHNqZG1nMnMnLFxuICAgICAgICAgICAgICAgICAgdmFsdWU6IDk5OTgzNDQ1NSxcbiAgICAgICAgICAgICAgICAgIHdhbGxldDogJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYicsXG4gICAgICAgICAgICAgICAgICB3YWxsZXRzOiBbJzY0ZmEzMWE5NGRiNjVhMDAwN2M5NjkxYiddLFxuICAgICAgICAgICAgICAgICAgZW50ZXJwcmlzZTogJzYyY2M1OWI3Mjc0NDNhMDAwNzA4OTAzMycsXG4gICAgICAgICAgICAgICAgICBlbnRlcnByaXNlczogWyc2MmNjNTliNzI3NDQzYTAwMDcwODkwMzMnXSxcbiAgICAgICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnOTk5ODM0NDU1JyxcbiAgICAgICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYScsXG4gICAgICAgICAgICAgICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgICAgICAgICAgICAgIHdhbGxldFR5cGVzOiBbJ2hvdCddLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIGlucHV0czogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiAxMDAwMDAwMDAwLFxuICAgICAgICAgICAgICAgICAgYWRkcmVzczpcbiAgICAgICAgICAgICAgICAgICAgJ2FkZHJfdGVzdDFxcWx6eGZsN3RsZ3A5OTl4NGE3MzM0cGNoeWNwa2s3MnB5a3JzcjNtcnlsM3lqNnhxODdxejZrcnNrcWZ6bWY0eXo3OGRkamU5eHE0dnF5ODhyZjUwMjVuenNoc3ZwZ2w4dycsXG4gICAgICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzEwMDAwMDAwMDAnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHR5cGU6ICcwJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb25zb2xpZGF0ZUlkOiAnNjhiOWZjMTg1NTgwMDZhYWI1Mzc4NTYxNWZlYTdjMjgnLFxuICAgICAgICAgICAgY29pbjogJ3RhZGEnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuXG4gICAgICAvLyBDYWxsIHRoZSBmdW5jdGlvbiB0byB0ZXN0XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHdhbGxldE9iai5zZW5kQWNjb3VudENvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6ICdwYXNzd29yZCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOiAndHggb3V0cHV0cyBkb2VzIG5vdCBtYXRjaCB3aXRoIGV4cGVjdGVkIGFkZHJlc3MnLFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRXhwbGFpbiBUcmFuc2FjdGlvbnM6JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZXhwbGFpbiBhbiB1bnNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4uZXhwbGFpblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiByYXdUeC51bnNpZ25lZFR4MixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgY29uc29sZS5sb2coZXhwbGFpbmVkVHJhbnNhY3Rpb24pO1xuICAgICAgZXhwbGFpbmVkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh0cmFuc2FjdGlvbkV4cGxhbmF0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBleHBsYWluIHRyYW5zYWN0aW9uIHdpdGggbWlzc2luZyBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHt9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHNob3VsZC5lcXVhbChlcnJvci5tZXNzYWdlLCAnSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGV4cGxhaW4gdHJhbnNhY3Rpb24gd2l0aCB3cm9uZyBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBiYXNlY29pbi5leHBsYWluVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiAnaW52YWxpZFR4SGV4JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHNob3VsZC5lcXVhbChlcnJvci5tZXNzYWdlLCAnSW52YWxpZCB0cmFuc2FjdGlvbicpO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUGFyc2UgUmF3IFRyYW5zYWN0aW9ucycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHBhcnNlIHN0YWtpbmcgcGxlZGdlIHRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24oYmFzZWNvaW4pO1xuICAgICAgdHguZnJvbVJhd1RyYW5zYWN0aW9uKHJhd1R4LnVuc2lnbmVkTmV3UGxlZGdlVHgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nUGxlZGdlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2Ugc3Rha2luZyBhY3RpdmF0aW9uIHR4JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24oYmFzZWNvaW4pO1xuICAgICAgdHguZnJvbVJhd1RyYW5zYWN0aW9uKHJhd1R4LnVuc2lnbmVkU3Rha2luZ0FjdGl2ZVR4KTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2Ugc3Rha2luZyBkZWFjdGl2YXRpb24gdHgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmF3VHgudW5zaWduZWRTdGFraW5nRGVhY3RpdmVUeCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1BhcnNlIFRyYW5zYWN0aW9uczonLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhbiB1bnNpZ25lZCB0cmFuc2ZlciB0cmFuc2FjdGlvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcnNlZFRyYW5zYWN0aW9uID0gYXdhaXQgYmFzZWNvaW4ucGFyc2VUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICB0eEhleDogcmF3VHgudW5zaWduZWRUeDIsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgcGFyc2VkVHJhbnNhY3Rpb24uc2hvdWxkLmRlZXBFcXVhbCh0cmFuc2FjdGlvbkV4cGxhbmF0aW9uKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2UgYSBzaWduZWQgdHJhbnNmZXIgdHJhbnNhY3Rpb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJzZWRUcmFuc2FjdGlvbiA9IGF3YWl0IGJhc2Vjb2luLnBhcnNlVHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHJhd1R4LnNpZ25lZFR4MixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBwYXJzZWRUcmFuc2FjdGlvbi5zaG91bGQuZGVlcEVxdWFsKHRyYW5zYWN0aW9uRXhwbGFuYXRpb24pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHBhcnNlIGEgc2lnbmVkIHRyYW5zZmVyIHRyYW5zYWN0aW9uIHdoZW4gZXhwbGFpblRyYW5zYWN0aW9uIHJlc3BvbnNlIGlzIHVuZGVmaW5lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHN0dWIgPSBzaW5vbi5zdHViKEFkYS5wcm90b3R5cGUsICdleHBsYWluVHJhbnNhY3Rpb24nKTtcbiAgICAgIHN0dWIucmVzb2x2ZXModW5kZWZpbmVkKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5wYXJzZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogcmF3VHguc2lnbmVkVHgsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ludmFsaWQgdHJhbnNhY3Rpb24nKTtcbiAgICAgIHN0dWIucmVzdG9yZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVjb3ZlciBUcmFuc2FjdGlvbnM6JywgKCkgPT4ge1xuICAgIGNvbnN0IGRlc3RBZGRyID0gYWRkcmVzcy5hZGRyZXNzMjtcbiAgICBjb25zdCBzYW5kQm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuICAgIGxldCBjYWxsQmFjazogc2lub24uU2lub25TdHViO1xuXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7XG4gICAgICAgICAgX2FkZHJlc3NlczogW3dyd1VzZXIud2FsbGV0QWRkcmVzczBdLFxuICAgICAgICB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5PbmVVVFhPKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0YWtlIE9WQyBvdXRwdXQgYW5kIGdlbmVyYXRlIGEgc2lnbmVkIHN3ZWVwIHRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyYW1zID0gb3ZjUmVzcG9uc2U7XG4gICAgICBjb25zdCByZWNvdmVyeVR4biA9IGF3YWl0IGJhc2Vjb2luLmNyZWF0ZUJyb2FkY2FzdGFibGVTd2VlcFRyYW5zYWN0aW9uKHBhcmFtcyk7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMF0uc2VyaWFsaXplZFR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzg0YTQwMDgxODI1ODIwNGJkMGY5OTFjMTUzMmNmZmUzMWQ0YTEwZGI0OTJiNDMxNzVlYzMyNjc2NWI2YjI5Y2VlZTU5OGRmMmI2MWY0NzAwMDE4MTgyNTgzOTAwODczNzllYmM1NTMzZWJlNjIxOTYzYzkxNWMzY2JjNWYwODUzN2ZjZGNhNGFmOGY4YWUwOGVkNGM4NzM3OWViYzU1MzNlYmU2MjE5NjNjOTE1YzNjYmM1ZjA4NTM3ZmNkY2E0YWY4ZjhhZTA4ZWQ0YzFhMDVmMzU5ZmYwMjFhMDAwMjg3MDEwMzFhMDI0OTcyZTFhMTAwODE4MjU4MjBiYmFjYjEzNDMxYjk5MjA4ZTZlOGNkYmY3MTAxNDdmZWFmMDZhMzlkNzE1NjVlNjBiNDExY2U5ZTRmYTNmMTM3NTg0MDAxYTRhYjgyMzY1NjNmNjlmZjMwOWU1Nzg2ZThmMzljNjI5ZWQ1NzY3NmM2OTIxNTljYjJlMDQ5NGM5ZTY2MzM1NTM4NGMxM2M3NDlkMDRjMTdhODBiYTJhNDVjYzEyN2RmNDgwZmM2NGE0MzE5OWE3NzJmMTFhY2Q1YjE0YTBmZjVmNidcbiAgICAgICk7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMF0uc2NhbkluZGV4LnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIHJlY292ZXJ5VHhuLmxhc3RTY2FuSW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0YWtlIGNvbnNvbGlkYXRpb24gT1ZDIG91dHB1dCBhbmQgZ2VuZXJhdGUgbXVsdGlwbGUgc2lnbmVkIHN3ZWVwIHRyYW5zYWN0aW9ucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IG92Y1Jlc3BvbnNlMjtcbiAgICAgIGNvbnN0IHJlY292ZXJ5VHhuID0gYXdhaXQgYmFzZWNvaW4uY3JlYXRlQnJvYWRjYXN0YWJsZVN3ZWVwVHJhbnNhY3Rpb24ocGFyYW1zKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1swXS5zZXJpYWxpemVkVHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnODRhNDAwODE4MjU4MjAzZTYyZTVlZThiMTIwMTJjNGI5NDlmOTc3N2I3MjE2NTIzOWJiMjE0NmFlOGIwNzhiNGQxYzVjYThkMzE2OGUzMDAwMTgxODI1ODM5MDBiYWY1NWViY2Y5YWRhMWI4ZWNiMTY0MDg4MGZiYTU0ZDI4MTc2OTBmMTJiM2ExMDZhZmQwODAwNGJhZjU1ZWJjZjlhZGExYjhlY2IxNjQwODgwZmJhNTRkMjgxNzY5MGYxMmIzYTEwNmFmZDA4MDA0MWEwMDk2MGY3ZjAyMWEwMDAyODcwMTAzMWEwMjUwZjdlYWExMDA4MTgyNTgyMDUwMGUwZDcyNWE1YmEzYTMwNmRhMzUwM2RmZTU3YjhhMTQwNjhhMDliNjFiMzZlYzA2OGZjZjhjZjVjMzkxZGU1ODQwYzgzNmNlNmQzMjYyZDU2NTQ3MDZlYTA2NzIxNTIyZDNiNzVmNmQ1NDUyNDUwNDdhN2JlNzQ2MzYyOWQ4OGIzZjQyNjRiOTk1ZjU5MWRmNTJiZGZmY2YwOWRhMWU2YWI5ZTg4ZGUzNzE0YzZlMmVjMTk2MTc4NmNmMWM1ODZhMDdmNWY2J1xuICAgICAgKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1swXS5zY2FuSW5kZXguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgcmVjb3ZlcnlUeG4udHJhbnNhY3Rpb25zWzFdLnNlcmlhbGl6ZWRUeC5zaG91bGQuZXF1YWwoXG4gICAgICAgICc4NGE0MDA4MTgyNTgyMDI5YzEwYWNmMGUwOGY5NTIzMzI1Yzg4MjQzNTY1YWY2YjMyMjc0OTkyMTg5YzExNTM5MDNjNDEwYmVkN2MyYzcwMDAxODE4MjU4MzkwMGJhZjU1ZWJjZjlhZGExYjhlY2IxNjQwODgwZmJhNTRkMjgxNzY5MGYxMmIzYTEwNmFmZDA4MDA0YmFmNTVlYmNmOWFkYTFiOGVjYjE2NDA4ODBmYmE1NGQyODE3NjkwZjEyYjNhMTA2YWZkMDgwMDQxYTAwOTYwZjdmMDIxYTAwMDI4NzAxMDMxYTAyNTBmN2VhYTEwMDgxODI1ODIwNjI3NzBiMjI0YmQzMTRiYzUyNmZiZDZhOTRlOTA4MmZiNjQ1OGM0MjVlNmUwOWJhZDc0MDA0ZGQ4OTdlOTYyMzU4NDAzODQyNTQ0ZjJmZjI4YmUwNTRlYjdjNzk5N2JjMzAzYjFlMjUxZWIxM2E0MTgwMmM4MjMxOGU1OTJiYjI0ZWFhMzE5N2M0NTBlNzk3Y2M4NTU5ZjAzNTZjZDVjZGQxYWI1ZWI4MGM1MTczZTM0ZTllMWQxNzM3NTMzYTg5NTIwY2Y1ZjYnXG4gICAgICApO1xuICAgICAgcmVjb3ZlcnlUeG4udHJhbnNhY3Rpb25zWzFdLnNjYW5JbmRleC5zaG91bGQuZXF1YWwoMik7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMl0uc2VyaWFsaXplZFR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzg0YTQwMDgxODI1ODIwZGQxNDBmMTMzZDg2NWUxYmI1NjQyZTcwOGZlNjg1YmY3NjAxZDcxZDBjOTk1MTFlNWQ1NTJkYTdmOGJkMTBmZjAwMDE4MTgyNTgzOTAwYmFmNTVlYmNmOWFkYTFiOGVjYjE2NDA4ODBmYmE1NGQyODE3NjkwZjEyYjNhMTA2YWZkMDgwMDRiYWY1NWViY2Y5YWRhMWI4ZWNiMTY0MDg4MGZiYTU0ZDI4MTc2OTBmMTJiM2ExMDZhZmQwODAwNDFhMDA5NjBmN2YwMjFhMDAwMjg3MDEwMzFhMDI1MGY3ZWFhMTAwODE4MjU4MjA1M2I0YmI3NGFhMzhhZGQ0NThkYWZjODE1M2YwYWE4MjY2YWNhZDU5MzIyYjg3N2NhOWMyM2M1ZDM4NzM3NzlkNTg0MGU5NGNlNzg5Njk1N2QwOTRjNmJhZmJmMmVjMTBkZjVlYmIwZjFkMmEyN2E3ZTMxZjJkNDVjNTMxZmI2ODdlZGQ2YzRkMzNmOGU5Yjk5Yzc2OTJiNmZhYzZkODM5OWJkOGZkNDc2NDFiYWFlOWJiYjY5ZjUxOGQ0MmFkMTE3MTBhZjVmNidcbiAgICAgICk7XG4gICAgICByZWNvdmVyeVR4bi50cmFuc2FjdGlvbnNbMl0uc2NhbkluZGV4LnNob3VsZC5lcXVhbCgzKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1szXS5zZXJpYWxpemVkVHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnODRhNDAwODE4MjU4MjAxNWExZDZkYjVkM2Y1OTJhYTFjZGExODViNjM1OWNhMGUyOTIxYzNjNTE5NTlmNjQyMjJhNmI3ZDk1ZDMzOTIzMDAwMTgxODI1ODM5MDBiYWY1NWViY2Y5YWRhMWI4ZWNiMTY0MDg4MGZiYTU0ZDI4MTc2OTBmMTJiM2ExMDZhZmQwODAwNGJhZjU1ZWJjZjlhZGExYjhlY2IxNjQwODgwZmJhNTRkMjgxNzY5MGYxMmIzYTEwNmFmZDA4MDA0MWEwMDk2MGY3ZjAyMWEwMDAyODcwMTAzMWEwMjUwZjdlYWExMDA4MTgyNTgyMDYwMGY4NmNhMjJkNjcwZjBhOTkwYWRlNGU4ODJjMDVlNjU0MzQzMjYzNDk0NzM1YTMxNTE3ZGUwODE5Njc2NzM1ODQwZmUxOTlmOGUyNDdhNGNmYWJmZWI0ZjljYjU3NGFhMzU3MzlhMGFhOTg4NjBlZTBhODVkNzIwYzRhYjRmZWNmYWM3YjQ1MDRkZjMxMGIzZTRiZWEwNDcxMWY2MDY1MmQ0YThjZjVlYjQxODE3MjkzYjhkMjk5NzdmZTY5NWY3MDRmNWY2J1xuICAgICAgKTtcbiAgICAgIHJlY292ZXJ5VHhuLnRyYW5zYWN0aW9uc1szXS5zY2FuSW5kZXguc2hvdWxkLmVxdWFsKDQpO1xuICAgICAgcmVjb3ZlcnlUeG4ubGFzdFNjYW5JbmRleC5zaG91bGQuZXF1YWwoMjApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciBub24tYml0Z28gcmVjb3ZlcmllcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiB3cndVc2VyLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogd3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiB3cndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRUd2ljZShiYXNlY29pbi5nZXREYXRhRnJvbU5vZGUpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgIGNvbnN0IGZlZSA9IE51bWJlcih0eC5leHBsYWluVHJhbnNhY3Rpb24oKS5mZWUuZmVlKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1swXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2luZGV4LCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaW5kZXgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24ub3V0cHV0c1swXS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0eEpzb24ub3V0cHV0c1swXS5hbW91bnQpICsgZmVlLCB0ZXN0bmV0VVRYTy5VVFhPXzEudmFsdWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciB1bnNpZ25lZCBzd2VlcCByZWNvdmVyaWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50eFJlcXVlc3RzWzBdLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4LnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRUd2ljZShiYXNlY29pbi5nZXREYXRhRnJvbU5vZGUpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbiA9IHR4LnRvSnNvbigpO1xuICAgICAgY29uc3QgZmVlID0gTnVtYmVyKHR4LmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5vdXRwdXRzWzBdLmFkZHJlc3MsIGRlc3RBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHR4SnNvbi5vdXRwdXRzWzBdLmFtb3VudCkgKyBmZWUsIHRlc3RuZXRVVFhPLlVUWE9fMS52YWx1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgQURBIHBsdXMgdG9rZW4gVVRYT3MgLSB0b2tlbiBhbmQgQURBIGJvdGggYXBwZWFyIGluIG91dHB1dHMgKHVuc2lnbmVkIHN3ZWVwKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgeyBfYWRkcmVzc2VzOiBbd3J3VXNlci53YWxsZXRBZGRyZXNzMF0gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuQURBQW5kVG9rZW5VVFhPcyk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICBiaXRnb0tleTogd3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdEFkZHIsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICB1bnNpZ25lZFR4LnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbih1bnNpZ25lZFR4LnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgdHhKc29uLmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMV0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fVE9LRU4udHhfaGFzaCk7XG5cbiAgICAgIHR4SnNvbi5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG5cbiAgICAgIGNvbnN0IHRva2VuUG9saWN5SWQgPSAnMjUzM2NjYTZlYjQyMDc2ZTE0NGU5ZjI3NzJjMzkwZGVjZTlmY2UxNzNiYzM4YzcyMjk0YjM5MjQnO1xuICAgICAgY29uc3QgdG9rZW5FbmNvZGVkQXNzZXROYW1lID0gJzU3NDE1NDQ1NTInO1xuICAgICAgY29uc3QgdG9rZW5RdWFudGl0eSA9ICcxMTEnO1xuICAgICAgY29uc3QgbWluQURBRm9yVG9rZW4gPSAxNTAwMDAwO1xuXG4gICAgICBjb25zdCB0b2tlbk91dHB1dCA9IHR4SnNvbi5vdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgIT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QodG9rZW5PdXRwdXQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0b2tlbk91dHB1dCEuYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIodG9rZW5PdXRwdXQhLmFtb3VudCksIG1pbkFEQUZvclRva2VuKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkUG9saWN5SWQgPSBDYXJkYW5vV2FzbS5TY3JpcHRIYXNoLmZyb21fYnl0ZXMoQnVmZmVyLmZyb20odG9rZW5Qb2xpY3lJZCwgJ2hleCcpKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkQXNzZXROYW1lID0gQ2FyZGFub1dhc20uQXNzZXROYW1lLm5ldyhCdWZmZXIuZnJvbSh0b2tlbkVuY29kZWRBc3NldE5hbWUsICdoZXgnKSk7XG4gICAgICAodG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIGFzIENhcmRhbm9XYXNtLk11bHRpQXNzZXQpXG4gICAgICAgIC5nZXRfYXNzZXQoZXhwZWN0ZWRQb2xpY3lJZCwgZXhwZWN0ZWRBc3NldE5hbWUpXG4gICAgICAgIC50b19zdHIoKVxuICAgICAgICAuc2hvdWxkLmVxdWFsKHRva2VuUXVhbnRpdHkpO1xuXG4gICAgICBjb25zdCBhZGFPdXRwdXQgPSB0eEpzb24ub3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzID09PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KGFkYU91dHB1dCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKGFkYU91dHB1dCEuYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgICAgY29uc3QgZmVlID0gTnVtYmVyKHR4LmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgY29uc3QgdG90YWxCYWxhbmNlID0gdGVzdG5ldFVUWE8uVVRYT18xLnZhbHVlICsgdGVzdG5ldFVUWE8uVVRYT19UT0tFTi52YWx1ZTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKGFkYU91dHB1dCEuYW1vdW50KSwgdG90YWxCYWxhbmNlIC0gbWluQURBRm9yVG9rZW4gLSBmZWUpO1xuXG4gICAgICBjb25zdCBleHBsYWluZWQgPSB0eC5leHBsYWluVHJhbnNhY3Rpb24oKTtcbiAgICAgIGNvbnN0IGV4cGxhaW5lZFRva2VuT3V0cHV0ID0gZXhwbGFpbmVkLm91dHB1dHMuZmluZCgobykgPT4gby5hbW91bnQgPT09IG1pbkFEQUZvclRva2VuLnRvU3RyaW5nKCkpO1xuICAgICAgc2hvdWxkLmV4aXN0KGV4cGxhaW5lZFRva2VuT3V0cHV0KTtcblxuICAgICAgLy8gaW5wdXRzIGFuZCBvdXRwdXRzIGluIHBhcnNlZFR4IHNob3VsZCBjYXJyeSBtdWx0aUFzc2V0c1xuICAgICAgY29uc3QgcGFyc2VkVHhJbnB1dHMgPSByZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5wYXJzZWRUeC5pbnB1dHMgYXMge1xuICAgICAgICBhZGRyZXNzOiBzdHJpbmc7XG4gICAgICAgIHZhbHVlU3RyaW5nOiBzdHJpbmc7XG4gICAgICAgIG11bHRpQXNzZXRzPzogeyBwb2xpY3lfaWQ6IHN0cmluZzsgYXNzZXRfbmFtZTogc3RyaW5nOyBxdWFudGl0eTogc3RyaW5nIH1bXTtcbiAgICAgIH1bXTtcbiAgICAgIHBhcnNlZFR4SW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMpO1xuICAgICAgcGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMhLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFR4SW5wdXRzWzBdLm11bHRpQXNzZXRzIVswXS5wb2xpY3lfaWQsIHRva2VuUG9saWN5SWQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeElucHV0c1swXS5tdWx0aUFzc2V0cyFbMF0uYXNzZXRfbmFtZSwgdG9rZW5FbmNvZGVkQXNzZXROYW1lKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMhWzBdLnF1YW50aXR5LCB0b2tlblF1YW50aXR5KTtcblxuICAgICAgY29uc3QgcGFyc2VkVHhPdXRwdXRzID0gcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHgucGFyc2VkVHgub3V0cHV0cyBhcyB7XG4gICAgICAgIGFkZHJlc3M6IHN0cmluZztcbiAgICAgICAgdmFsdWVTdHJpbmc6IHN0cmluZztcbiAgICAgICAgbXVsdGlBc3NldHM/OiB7IHBvbGljeV9pZDogc3RyaW5nOyBhc3NldF9uYW1lOiBzdHJpbmc7IHF1YW50aXR5OiBzdHJpbmcgfVtdO1xuICAgICAgfVtdO1xuICAgICAgY29uc3QgcGFyc2VkVG9rZW5PdXRwdXQgPSBwYXJzZWRUeE91dHB1dHMuZmluZCgobykgPT4gby5tdWx0aUFzc2V0cyAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIHNob3VsZC5leGlzdChwYXJzZWRUb2tlbk91dHB1dCk7XG4gICAgICBwYXJzZWRUb2tlbk91dHB1dCEubXVsdGlBc3NldHMhLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyFbMF0ucG9saWN5X2lkLCB0b2tlblBvbGljeUlkKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIVswXS5hc3NldF9uYW1lLCB0b2tlbkVuY29kZWRBc3NldE5hbWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUb2tlbk91dHB1dCEubXVsdGlBc3NldHMhWzBdLnF1YW50aXR5LCB0b2tlblF1YW50aXR5KTtcbiAgICAgIC8vIHB1cmUgQURBIG91dHB1dCBzaG91bGQgbm90IGhhdmUgbXVsdGlBc3NldHNcbiAgICAgIGNvbnN0IHBhcnNlZEFkYU91dHB1dCA9IHBhcnNlZFR4T3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzID09PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHBhcnNlZEFkYU91dHB1dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgQURBIHBsdXMgdG9rZW4gVVRYT3MgLSB0b2tlbiBhbmQgQURBIGJvdGggYXBwZWFyIGluIG91dHB1dHMgKHNpZ25lZCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW3dyd1VzZXIud2FsbGV0QWRkcmVzczBdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLkFEQUFuZFRva2VuVVRYT3MpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgdXNlcktleTogd3J3VXNlci51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IHdyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICBiaXRnb0tleTogd3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogd3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgdHhKc29uLmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMV0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fVE9LRU4udHhfaGFzaCk7XG5cbiAgICAgIC8vIGV4cGVjdCAyIG91dHB1dHM6IG9uZSB0b2tlbiBvdXRwdXQgKyBvbmUgQURBIGNoYW5nZSBvdXRwdXQsIGJvdGggYXQgZGVzdEFkZHJcbiAgICAgIHR4SnNvbi5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG5cbiAgICAgIGNvbnN0IHRva2VuUG9saWN5SWQgPSAnMjUzM2NjYTZlYjQyMDc2ZTE0NGU5ZjI3NzJjMzkwZGVjZTlmY2UxNzNiYzM4YzcyMjk0YjM5MjQnO1xuICAgICAgY29uc3QgdG9rZW5FbmNvZGVkQXNzZXROYW1lID0gJzU3NDE1NDQ1NTInO1xuICAgICAgY29uc3QgdG9rZW5RdWFudGl0eSA9ICcxMTEnO1xuICAgICAgY29uc3QgbWluQURBRm9yVG9rZW4gPSAxNTAwMDAwO1xuXG4gICAgICBjb25zdCB0b2tlbk91dHB1dCA9IHR4SnNvbi5vdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgIT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QodG9rZW5PdXRwdXQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0b2tlbk91dHB1dCEuYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIodG9rZW5PdXRwdXQhLmFtb3VudCksIG1pbkFEQUZvclRva2VuKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkUG9saWN5SWQgPSBDYXJkYW5vV2FzbS5TY3JpcHRIYXNoLmZyb21fYnl0ZXMoQnVmZmVyLmZyb20odG9rZW5Qb2xpY3lJZCwgJ2hleCcpKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkQXNzZXROYW1lID0gQ2FyZGFub1dhc20uQXNzZXROYW1lLm5ldyhCdWZmZXIuZnJvbSh0b2tlbkVuY29kZWRBc3NldE5hbWUsICdoZXgnKSk7XG4gICAgICAodG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIGFzIENhcmRhbm9XYXNtLk11bHRpQXNzZXQpXG4gICAgICAgIC5nZXRfYXNzZXQoZXhwZWN0ZWRQb2xpY3lJZCwgZXhwZWN0ZWRBc3NldE5hbWUpXG4gICAgICAgIC50b19zdHIoKVxuICAgICAgICAuc2hvdWxkLmVxdWFsKHRva2VuUXVhbnRpdHkpO1xuXG4gICAgICBjb25zdCBhZGFPdXRwdXQgPSB0eEpzb24ub3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzID09PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KGFkYU91dHB1dCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKGFkYU91dHB1dCEuYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgICAgY29uc3QgZmVlID0gTnVtYmVyKHR4LmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgY29uc3QgdG90YWxCYWxhbmNlID0gdGVzdG5ldFVUWE8uVVRYT18xLnZhbHVlICsgdGVzdG5ldFVUWE8uVVRYT19UT0tFTi52YWx1ZTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKGFkYU91dHB1dCEuYW1vdW50KSwgdG90YWxCYWxhbmNlIC0gbWluQURBRm9yVG9rZW4gLSBmZWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVjb3ZlciBUcmFuc2FjdGlvbnMgKE1QQ3YyKTonLCAoKSA9PiB7XG4gICAgY29uc3QgZGVzdEFkZHIgPSBhZGRyZXNzLmFkZHJlc3MyO1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9IHdyd1VzZXIud2FsbGV0UGFzc3BocmFzZTtcbiAgICBsZXQgbXBjVjJVc2VyS2V5OiBzdHJpbmc7XG4gICAgbGV0IG1wY1YyQmFja3VwS2V5OiBzdHJpbmc7XG4gICAgbGV0IG1wY1YyQ29tbW9uS2V5Q2hhaW46IHN0cmluZztcbiAgICBsZXQgbXBjVjJXYWxsZXRBZGRyZXNzOiBzdHJpbmc7XG4gICAgbGV0IG1pc21hdGNoZWRCaXRnb0tleTogc3RyaW5nO1xuICAgIGxldCBtaXNtYXRjaGVkV2FsbGV0QWRkcmVzczogc3RyaW5nO1xuXG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgICBjb25zdCBbb3RoZXJVc2VyRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuXG4gICAgICBtcGNWMlVzZXJLZXkgPSBhd2FpdCBlbmNyeXB0KHdhbGxldFBhc3NwaHJhc2UsIHVzZXJEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcbiAgICAgIG1wY1YyQmFja3VwS2V5ID0gYXdhaXQgZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCBiYWNrdXBEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcbiAgICAgIG1wY1YyQ29tbW9uS2V5Q2hhaW4gPSB1c2VyRGtnLmdldENvbW1vbktleWNoYWluKCk7XG4gICAgICBtaXNtYXRjaGVkQml0Z29LZXkgPSBvdGhlclVzZXJEa2cuZ2V0Q29tbW9uS2V5Y2hhaW4oKTtcblxuICAgICAgbXBjVjJXYWxsZXRBZGRyZXNzID0gKGF3YWl0IGJhc2Vjb2luLmdldEFkYUFkZHJlc3NBbmRBY2NvdW50SWQoeyBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbiwgaW5kZXg6IDAgfSkpXG4gICAgICAgIC5hZGRyZXNzO1xuICAgICAgbWlzbWF0Y2hlZFdhbGxldEFkZHJlc3MgPSAoYXdhaXQgYmFzZWNvaW4uZ2V0QWRhQWRkcmVzc0FuZEFjY291bnRJZCh7IGJpdGdvS2V5OiBtaXNtYXRjaGVkQml0Z29LZXksIGluZGV4OiAwIH0pKVxuICAgICAgICAuYWRkcmVzcztcbiAgICB9KTtcblxuICAgIGxldCBjYWxsQmFjazogc2lub24uU2lub25TdHViO1xuXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7IF9hZGRyZXNzZXM6IFttcGNWMldhbGxldEFkZHJlc3NdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8pO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7IF9hZGRyZXNzZXM6IFttaXNtYXRjaGVkV2FsbGV0QWRkcmVzc10gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuT25lVVRYTyk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygndGlwJykucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMudGlwSW5mb1Jlc3BvbnNlKTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91dGUgdG8gTVBDdjIgcGF0aCBmb3IgbmF0aXZlIEFEQSByZWNvdmVyeSB3aGVuIGtleWNhcmQgaXMgTVBDdjInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBnZXRUU1NTaWduYXR1cmVTcHkgPSBzYW5kQm94LnNweShFRERTQU1ldGhvZHMsICdnZXRUU1NTaWduYXR1cmUnKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IG1wY1YyVXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBtcGNWMkJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IG1wY1YyQ29tbW9uS2V5Q2hhaW4sXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG5cbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHNhbmRCb3guYXNzZXJ0Lm5vdENhbGxlZChnZXRUU1NTaWduYXR1cmVTcHkpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLm91dHB1dHNbMF0uYWRkcmVzcywgZGVzdEFkZHIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIE1QQ3YyIGNvbW1vbktleUNoYWluIGRvZXMgbm90IG1hdGNoIGJpdGdvS2V5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IG1wY1YyVXNlcktleSxcbiAgICAgICAgICBiYWNrdXBLZXk6IG1wY1YyQmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBtaXNtYXRjaGVkQml0Z29LZXksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0VkRFNBIE1QQ3YyIHJlY292ZXJ5OiBjb21tb25LZXlDaGFpbiBmcm9tIGtleWNhcmQgZG9lcyBub3QgbWF0Y2ggYml0Z29LZXknKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBnZXRFZGRzYVNpZ25pbmdNYXRlcmlhbCBleGFjdGx5IG9uY2UgcGVyIHJlY292ZXIoKSBjYWxsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZ2V0RWRkc2FNYXRlcmlhbFNweSA9IHNhbmRCb3guc3B5KFxuICAgICAgICBiYXNlY29pbiBhcyB1bmtub3duIGFzIHsgZ2V0RWRkc2FTaWduaW5nTWF0ZXJpYWw6IHVua25vd24gfSxcbiAgICAgICAgJ2dldEVkZHNhU2lnbmluZ01hdGVyaWFsJ1xuICAgICAgKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IG1wY1YyVXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBtcGNWMkJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IG1wY1YyQ29tbW9uS2V5Q2hhaW4sXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG5cbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRPbmNlKGdldEVkZHNhTWF0ZXJpYWxTcHkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBpZ25vcmUgYSBtYWxmb3JtZWQgcHJlY29tcHV0ZWRNYXRlcmlhbCBhbmQgZGV0ZWN0IHNpZ25pbmcgbWF0ZXJpYWwgaXRzZWxmIChyZWdyZXNzaW9uOiBXUlcgb3BlblNTTEJ5dGVzIGNvbGxpc2lvbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBXUlcncyBnZW5lcmljIEVsZWN0cm9uICdyZWNvdmVyJyBJUEMgaGFuZGxlciBwYXNzZXMgb3BlblNTTEJ5dGVzIChhbiBBcnJheUJ1ZmZlcilcbiAgICAgIC8vIGFzIGEgc2Vjb25kIHBvc2l0aW9uYWwgYXJndW1lbnQgdG8gZXZlcnkgY29pbidzIHJlY292ZXIoKSwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyXG4gICAgICAvLyB0aGF0IGNvaW4gdXNlcyBpdC4gUHJldmlvdXNseSB0aGlzIHdhcyBibGluZGx5IHRydXN0ZWQgYXMgcHJlY29tcHV0ZWRNYXRlcmlhbCxcbiAgICAgIC8vIHByb2R1Y2luZyBgSlNPTi5wYXJzZSh1bmRlZmluZWQpYCAtPiBTeW50YXhFcnJvcjogXCJ1bmRlZmluZWRcIiBpcyBub3QgdmFsaWQgSlNPTi5cbiAgICAgIGNvbnN0IGdldEVkZHNhTWF0ZXJpYWxTcHkgPSBzYW5kQm94LnNweShcbiAgICAgICAgYmFzZWNvaW4gYXMgdW5rbm93biBhcyB7IGdldEVkZHNhU2lnbmluZ01hdGVyaWFsOiB1bmtub3duIH0sXG4gICAgICAgICdnZXRFZGRzYVNpZ25pbmdNYXRlcmlhbCdcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoXG4gICAgICAgIHtcbiAgICAgICAgICB1c2VyS2V5OiBtcGNWMlVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBtcGNWMkJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbixcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgICB9LFxuICAgICAgICBuZXcgQXJyYXlCdWZmZXIoOCkgYXMgYW55XG4gICAgICApO1xuXG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRPbmNlKGdldEVkZHNhTWF0ZXJpYWxTcHkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByb3V0ZSB0byBNUEN2MSBwYXRoIHdoZW4ga2V5Y2FyZCBpcyBNUEN2MSAocmVncmVzc2lvbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW3dyd1VzZXIud2FsbGV0QWRkcmVzczBdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8pO1xuXG4gICAgICBjb25zdCBnZXRUU1NTaWduYXR1cmVTcHkgPSBzYW5kQm94LnNweShFRERTQU1ldGhvZHMsICdnZXRUU1NTaWduYXR1cmUnKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3Zlcih7XG4gICAgICAgIHVzZXJLZXk6IHdyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiB3cndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IHdyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdEFkZHIsXG4gICAgICB9KTtcblxuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3NlcmlhbGl6ZWRUeCcpO1xuICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbGVkT25jZShnZXRUU1NTaWduYXR1cmVTcHkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGEgY3J5cHRvZ3JhcGhpY2FsbHkgdmFsaWQgRWQyNTUxOSBzaWduYXR1cmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzaWduUmVjb3ZlcnlTcHkgPSBzYW5kQm94LnNweShcbiAgICAgICAgYmFzZWNvaW4gYXMgdW5rbm93biBhcyB7IHNpZ25BZGFNcGNWMlJlY292ZXJ5OiB1bmtub3duIH0sXG4gICAgICAgICdzaWduQWRhTXBjVjJSZWNvdmVyeSdcbiAgICAgICk7XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiBtcGNWMlVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogbXBjVjJCYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBtcGNWMkNvbW1vbktleUNoYWluLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByYXdTaWc6IEJ1ZmZlciA9IGF3YWl0IChzaWduUmVjb3ZlcnlTcHkuZmlyc3RDYWxsLnJldHVyblZhbHVlIGFzIFByb21pc2U8QnVmZmVyPik7XG4gICAgICBjb25zdCBzaWduYWJsZVBheWxvYWQ6IEJ1ZmZlciA9IChzaWduUmVjb3ZlcnlTcHkuZmlyc3RDYWxsLmFyZ3NbMF0gYXMgeyBtZXNzYWdlOiBCdWZmZXIgfSkubWVzc2FnZTtcblxuICAgICAgY29uc3QgTVBDID0gYXdhaXQgRUREU0FNZXRob2RzLmdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICAgIGNvbnN0IGFjY291bnRJZCA9IE1QQy5kZXJpdmVVbmhhcmRlbmVkKG1wY1YyQ29tbW9uS2V5Q2hhaW4sICdtLzAnKS5zbGljZSgwLCA2NCk7XG5cbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBuYWNsLnNpZ24uZGV0YWNoZWQudmVyaWZ5KFxuICAgICAgICBuZXcgVWludDhBcnJheShzaWduYWJsZVBheWxvYWQpLFxuICAgICAgICBuZXcgVWludDhBcnJheShyYXdTaWcpLFxuICAgICAgICBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbShhY2NvdW50SWQsICdoZXgnKSlcbiAgICAgICk7XG4gICAgICBpc1ZhbGlkLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IG1pc3NpbmcgdXNlcktleSB3aGVuIGJhY2t1cEtleSBhbmQgd2FsbGV0UGFzc3BocmFzZSBhcmUgcHJlc2VudCBidXQgdXNlcktleSBpcyBub3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsQmFjay5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8pO1xuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnJlY292ZXIoe1xuICAgICAgICAgIHVzZXJLZXk6IHVuZGVmaW5lZCxcbiAgICAgICAgICBiYWNrdXBLZXk6IG1wY1YyQmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBtcGNWMkNvbW1vbktleUNoYWluLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdEFkZHIsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtaXNzaW5nIHVzZXJLZXknKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgbWlzc2luZyBiYWNrdXBLZXkgd2hlbiB1c2VyS2V5IGFuZCB3YWxsZXRQYXNzcGhyYXNlIGFyZSBwcmVzZW50IGJ1dCBiYWNrdXBLZXkgaXMgbm90JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY2FsbEJhY2sucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5PbmVVVFhPKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiBtcGNWMlVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiB1bmRlZmluZWQsXG4gICAgICAgICAgYml0Z29LZXk6IG1wY1YyQ29tbW9uS2V5Q2hhaW4sXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgYmFja3VwS2V5Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGEgY2xlYXIgZXJyb3Igd2hlbiB0aGUgTVBDdjEgYmFja3VwIGtleWNhcmQgZmFpbHMgdG8gZGVjcnlwdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgeyBfYWRkcmVzc2VzOiBbd3J3VXNlci53YWxsZXRBZGRyZXNzMF0gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuT25lVVRYTyk7XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB3cndVc2VyLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiAnbm90LWEtdmFsaWQtZW5jcnlwdGVkLWtleWNhcmQnLFxuICAgICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHdyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICByZWNvdmVyeURlc3RpbmF0aW9uOiBkZXN0QWRkcixcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0Vycm9yIGRlY3J5cHRpbmcgYmFja3VwIGtleWNoYWluOiBpbnZhbGlkIHBhc3N3b3JkIG9yIGNvcnJ1cHRlZCBrZXknKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JlY292ZXIgVHJhbnNhY3Rpb25zIE11bHRpcGxlIFVUWE86JywgKCkgPT4ge1xuICAgIGNvbnN0IGRlc3RBZGRyID0gYWRkcmVzcy5hZGRyZXNzMjtcbiAgICBjb25zdCBzYW5kQm94ID0gc2lub24uY3JlYXRlU2FuZGJveCgpO1xuXG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCB7XG4gICAgICAgICAgX2FkZHJlc3NlczogW3dyd1VzZXIud2FsbGV0QWRkcmVzczBdLFxuICAgICAgICB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5Ud29VVFhPKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNvdmVyIGEgdHhuIGZvciBub24tYml0Z28gcmVjb3ZlcmllcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXIoe1xuICAgICAgICB1c2VyS2V5OiB3cndVc2VyLnVzZXJLZXksXG4gICAgICAgIGJhY2t1cEtleTogd3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiB3cndVc2VyLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiB3cndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICBzYW5kQm94LmFzc2VydC5jYWxsZWRUd2ljZShiYXNlY29pbi5nZXREYXRhRnJvbU5vZGUpO1xuXG4gICAgICBjb25zdCB0eCA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eC5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcbiAgICAgIGNvbnN0IGZlZSA9IE51bWJlcih0eC5leHBsYWluVHJhbnNhY3Rpb24oKS5mZWUuZmVlKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1swXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2luZGV4LCB0ZXN0bmV0VVRYTy5VVFhPXzEudHhfaW5kZXgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzFdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMV0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMi50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5vdXRwdXRzWzBdLmFkZHJlc3MsIGRlc3RBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHR4SnNvbi5vdXRwdXRzWzBdLmFtb3VudCkgKyBmZWUsIHRlc3RuZXRVVFhPLlVUWE9fMS52YWx1ZSArIHRlc3RuZXRVVFhPLlVUWE9fMi52YWx1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlY292ZXIgYSB0eG4gZm9yIHVuc2lnbmVkIHN3ZWVwIHJlY292ZXJpZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyKHtcbiAgICAgICAgYml0Z29LZXk6IHdyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHguc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcbiAgICAgIHNhbmRCb3guYXNzZXJ0LmNhbGxlZFR3aWNlKGJhc2Vjb2luLmdldERhdGFGcm9tTm9kZSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbihyZXMudHhSZXF1ZXN0c1swXS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeC5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uID0gdHgudG9Kc29uKCk7XG4gICAgICBjb25zdCBmZWUgPSBOdW1iZXIodHguZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1swXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1sxXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18yLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24uaW5wdXRzWzFdLnRyYW5zYWN0aW9uX2luZGV4LCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaW5kZXgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24ub3V0cHV0c1swXS5hZGRyZXNzLCBkZXN0QWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0eEpzb24ub3V0cHV0c1swXS5hbW91bnQpICsgZmVlLCB0ZXN0bmV0VVRYTy5VVFhPXzEudmFsdWUgKyB0ZXN0bmV0VVRYTy5VVFhPXzIudmFsdWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQnVpbGQgQ29uc29saWRhdGlvbiBSZWNvdmVyaWVzOicsICgpID0+IHtcbiAgICBjb25zdCBiYXNlQWRkciA9IGNvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MwO1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKEFkYS5wcm90b3R5cGUsICdnZXREYXRhRnJvbU5vZGUnIGFzIGtleW9mIEFkYSk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHtcbiAgICAgICAgICBfYWRkcmVzc2VzOiBbY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczFdLFxuICAgICAgICB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5aZXJvVVRYTyk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHtcbiAgICAgICAgICBfYWRkcmVzc2VzOiBbY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczJdLFxuICAgICAgICB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5PbmVVVFhPKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywge1xuICAgICAgICAgIF9hZGRyZXNzZXM6IFtjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRBZGRyZXNzM10sXG4gICAgICAgIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8yKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBzaWduZWQgY29uc29saWRhdGlvbiByZWNvdmVyaWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHJlcy5sYXN0U2NhbkluZGV4LnNob3VsZC5lcXVhbCgzKTtcbiAgICAgIGNvbnN0IHR4bjEgPSByZXMudHJhbnNhY3Rpb25zWzBdO1xuICAgICAgY29uc3QgdHgxID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4MS5mcm9tUmF3VHJhbnNhY3Rpb24odHhuMS5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uMSA9IHR4MS50b0pzb24oKTtcbiAgICAgIGNvbnN0IGZlZTEgPSBOdW1iZXIodHgxLmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24xLmlucHV0c1swXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24xLmlucHV0c1swXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMS5vdXRwdXRzWzBdLmFkZHJlc3MsIGJhc2VBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHR4SnNvbjEub3V0cHV0c1swXS5hbW91bnQpICsgZmVlMSwgdGVzdG5ldFVUWE8uVVRYT18xLnZhbHVlKTtcblxuICAgICAgY29uc3QgdHhuMiA9IHJlcy50cmFuc2FjdGlvbnNbMV07XG4gICAgICBjb25zdCB0eDIgPSBuZXcgVHJhbnNhY3Rpb24oYmFzZWNvaW4pO1xuICAgICAgdHgyLmZyb21SYXdUcmFuc2FjdGlvbih0eG4yLnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24yID0gdHgyLnRvSnNvbigpO1xuICAgICAgY29uc3QgZmVlMiA9IE51bWJlcih0eDIuZXhwbGFpblRyYW5zYWN0aW9uKCkuZmVlLmZlZSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjIuaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2lkLCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaGFzaCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjIuaW5wdXRzWzBdLnRyYW5zYWN0aW9uX2luZGV4LCB0ZXN0bmV0VVRYTy5VVFhPXzIudHhfaW5kZXgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24yLm91dHB1dHNbMF0uYWRkcmVzcywgYmFzZUFkZHIpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChOdW1iZXIodHhKc29uMi5vdXRwdXRzWzBdLmFtb3VudCkgKyBmZWUyLCB0ZXN0bmV0VVRYTy5VVFhPXzIudmFsdWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBza2lwIGJ1aWxkaW5nIGNvbnNvbGlkYXRlIHRyYW5zYWN0aW9uIGlmIGJhbGFuY2UgaXMgZXF1YWwgdG8gemVybycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyQ29uc29saWRhdGlvbnMoe1xuICAgICAgICAgIHVzZXJLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJpdGdvS2V5LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IGNvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgICAgZW5kaW5nU2NhbkluZGV4OiAyLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLnJlamVjdGVkV2l0aCgnRGlkIG5vdCBmaW5kIGFuIGFkZHJlc3Mgd2l0aCBmdW5kcyB0byByZWNvdmVyLicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiBzdGFydGluZ1NjYW5JbmRleCBpcyBub3QgZ2UgdG8gMScsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyQ29uc29saWRhdGlvbnMoe1xuICAgICAgICAgIHVzZXJLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJpdGdvS2V5LFxuICAgICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAtMSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ0ludmFsaWQgc3RhcnRpbmcgb3IgZW5kaW5nIGluZGV4IHRvIHNjYW4gZm9yIGFkZHJlc3Nlcy4gc3RhcnRpbmdTY2FuSW5kZXg6IC0xLCBlbmRpbmdTY2FuSW5kZXg6IDE5LidcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgc2NhbiBmYWN0b3IgaXMgdG9vIGhpZ2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgICB1c2VyS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogY29uc29saWRhdGlvbldyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDMwMCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgJ0ludmFsaWQgc3RhcnRpbmcgb3IgZW5kaW5nIGluZGV4IHRvIHNjYW4gZm9yIGFkZHJlc3Nlcy4gc3RhcnRpbmdTY2FuSW5kZXg6IDEsIGVuZGluZ1NjYW5JbmRleDogMzAwLidcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgdW5zaWduZWQgY29uc29saWRhdGlvbiByZWNvdmVyaWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgIH0pO1xuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgdW5zaWduZWQgY29uc29saWRhdGlvbiByZWNvdmVyaWVzIGZvciBXUlcgKEFEQSBvbmx5KSBhbmQgYXNzZXJ0IGJ1aWxkIHJlc3BvbnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgYml0Z29LZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJpdGdvS2V5LFxuICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgZW5kaW5nU2NhbkluZGV4OiA0LFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnR4UmVxdWVzdHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcblxuICAgICAgLy8gQXNzZXJ0IGZpcnN0IGNvbnNvbGlkYXRpb24gdHhSZXF1ZXN0IHN0cnVjdHVyZVxuICAgICAgY29uc3QgdHhSZXF1ZXN0MSA9IHJlcy50eFJlcXVlc3RzWzBdO1xuICAgICAgdHhSZXF1ZXN0MS50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHgxID0gdHhSZXF1ZXN0MS50cmFuc2FjdGlvbnNbMF0udW5zaWduZWRUeDtcbiAgICAgIHVuc2lnbmVkVHgxLnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG4gICAgICB1bnNpZ25lZFR4MS5zaG91bGQuaGFzT3duUHJvcGVydHkoJ3BhcnNlZFR4Jyk7XG4gICAgICB1bnNpZ25lZFR4MS5zaG91bGQuaGFzT3duUHJvcGVydHkoJ2NvaW5TcGVjaWZpYycpO1xuXG4gICAgICAvLyBEZXNlcmlhbGl6ZSBhbmQgdmVyaWZ5IGlucHV0cy9vdXRwdXRzXG4gICAgICBjb25zdCB0eDEgPSBuZXcgVHJhbnNhY3Rpb24oYmFzZWNvaW4pO1xuICAgICAgdHgxLmZyb21SYXdUcmFuc2FjdGlvbih1bnNpZ25lZFR4MS5zZXJpYWxpemVkVHgpO1xuICAgICAgY29uc3QgdHhKc29uMSA9IHR4MS50b0pzb24oKTtcbiAgICAgIGNvbnN0IGZlZTEgPSBOdW1iZXIodHgxLmV4cGxhaW5UcmFuc2FjdGlvbigpLmZlZS5mZWUpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24xLmlucHV0c1swXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2hhc2gpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eEpzb24xLmlucHV0c1swXS50cmFuc2FjdGlvbl9pbmRleCwgdGVzdG5ldFVUWE8uVVRYT18xLnR4X2luZGV4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMS5vdXRwdXRzWzBdLmFkZHJlc3MsIGJhc2VBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHR4SnNvbjEub3V0cHV0c1swXS5hbW91bnQpICsgZmVlMSwgdGVzdG5ldFVUWE8uVVRYT18xLnZhbHVlKTtcblxuICAgICAgLy8gcGFyc2VkVHggaW5wdXRzL291dHB1dHMgbXVzdCBiZSBwcmVzZW50IGFuZCBjYXJyeSBjb3JyZWN0IGFkZHJlc3NcbiAgICAgIGNvbnN0IHBhcnNlZFR4MUlucHV0cyA9IHVuc2lnbmVkVHgxLnBhcnNlZFR4LmlucHV0cztcbiAgICAgIHBhcnNlZFR4MUlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeDFJbnB1dHNbMF0uYWRkcmVzcywgY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczIpO1xuICAgICAgY29uc3QgcGFyc2VkVHgxT3V0cHV0cyA9IHVuc2lnbmVkVHgxLnBhcnNlZFR4Lm91dHB1dHM7XG4gICAgICBwYXJzZWRUeDFPdXRwdXRzLmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oMCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFR4MU91dHB1dHNbMF0uYWRkcmVzcywgYmFzZUFkZHIpO1xuXG4gICAgICAvLyBBc3NlcnQgc2Vjb25kIGNvbnNvbGlkYXRpb24gdHhSZXF1ZXN0IHN0cnVjdHVyZVxuICAgICAgY29uc3QgdHhSZXF1ZXN0MiA9IHJlcy50eFJlcXVlc3RzWzFdO1xuICAgICAgY29uc3QgdW5zaWduZWRUeDIgPSB0eFJlcXVlc3QyLnRyYW5zYWN0aW9uc1swXS51bnNpZ25lZFR4O1xuICAgICAgdW5zaWduZWRUeDIuc2hvdWxkLmhhc093blByb3BlcnR5KCdzZXJpYWxpemVkVHgnKTtcblxuICAgICAgY29uc3QgdHgyID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4Mi5mcm9tUmF3VHJhbnNhY3Rpb24odW5zaWduZWRUeDIuc2VyaWFsaXplZFR4KTtcbiAgICAgIGNvbnN0IHR4SnNvbjIgPSB0eDIudG9Kc29uKCk7XG4gICAgICBjb25zdCBmZWUyID0gTnVtYmVyKHR4Mi5leHBsYWluVHJhbnNhY3Rpb24oKS5mZWUuZmVlKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMi50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uMi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faW5kZXgsIHRlc3RuZXRVVFhPLlVUWE9fMi50eF9pbmRleCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbjIub3V0cHV0c1swXS5hZGRyZXNzLCBiYXNlQWRkcik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcih0eEpzb24yLm91dHB1dHNbMF0uYW1vdW50KSArIGZlZTIsIHRlc3RuZXRVVFhPLlVUWE9fMi52YWx1ZSk7XG5cbiAgICAgIC8vIGxhc3RTY2FuSW5kZXggbXVzdCBiZSBzZXQgaW4gY29pblNwZWNpZmljIG9mIHRoZSBsYXN0IHR4UmVxdWVzdFxuICAgICAgY29uc3QgbGFzdENvaW5TcGVjaWZpYyA9IHVuc2lnbmVkVHgyLmNvaW5TcGVjaWZpYztcbiAgICAgIGxhc3RDb2luU3BlY2lmaWMuc2hvdWxkLmhhc093blByb3BlcnR5KCdsYXN0U2NhbkluZGV4Jyk7XG4gICAgICBsYXN0Q29pblNwZWNpZmljLmxhc3RTY2FuSW5kZXguc2hvdWxkLmVxdWFsKDMpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCB1bnNpZ25lZCBjb25zb2xpZGF0aW9uIHJlY292ZXJpZXMgZm9yIFdSVyAoQURBICsgVG9rZW4pIGFuZCBhc3NlcnQgYnVpbGQgcmVzcG9uc2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBPdmVycmlkZSB3YWxsZXRBZGRyZXNzMiB0byByZXR1cm4gQURBK1Rva2VuIFVUWE9zXG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IGNhbGxCYWNrMiA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2syXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgeyBfYWRkcmVzc2VzOiBbY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczFdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLlplcm9VVFhPKTtcbiAgICAgIGNhbGxCYWNrMlxuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MyXSB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5BREFBbmRUb2tlblVUWE9zKTtcbiAgICAgIGNhbGxCYWNrMlxuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MzXSB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5aZXJvVVRYTyk7XG4gICAgICBjYWxsQmFjazIud2l0aEFyZ3MoJ3RpcCcpLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLnRpcEluZm9SZXNwb25zZSk7XG5cbiAgICAgIGNvbnN0IHRva2VuUG9saWN5SWQgPSAnMjUzM2NjYTZlYjQyMDc2ZTE0NGU5ZjI3NzJjMzkwZGVjZTlmY2UxNzNiYzM4YzcyMjk0YjM5MjQnO1xuICAgICAgY29uc3QgdG9rZW5FbmNvZGVkQXNzZXROYW1lID0gJzU3NDE1NDQ1NTInO1xuICAgICAgY29uc3QgdG9rZW5RdWFudGl0eSA9ICcxMTEnO1xuICAgICAgY29uc3QgbWluQURBRm9yVG9rZW4gPSAxNTAwMDAwO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyQ29uc29saWRhdGlvbnMoe1xuICAgICAgICBiaXRnb0tleTogY29uc29saWRhdGlvbldyd1VzZXIuYml0Z29LZXksXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDQsXG4gICAgICB9KTtcbiAgICAgIHJlcy5zaG91bGQubm90LmJlLmVtcHR5KCk7XG4gICAgICByZXMudHhSZXF1ZXN0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICBjb25zdCB1bnNpZ25lZFR4ID0gcmVzLnR4UmVxdWVzdHNbMF0udHJhbnNhY3Rpb25zWzBdLnVuc2lnbmVkVHg7XG4gICAgICB1bnNpZ25lZFR4LnNob3VsZC5oYXNPd25Qcm9wZXJ0eSgnc2VyaWFsaXplZFR4Jyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4LmZyb21SYXdUcmFuc2FjdGlvbih1bnNpZ25lZFR4LnNlcmlhbGl6ZWRUeCk7XG4gICAgICBjb25zdCB0eEpzb24gPSB0eC50b0pzb24oKTtcblxuICAgICAgLy8gVHdvIGlucHV0czogQURBIFVUWE8gKyBUb2tlbiBVVFhPXG4gICAgICB0eEpzb24uaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHR4SnNvbi5pbnB1dHNbMF0udHJhbnNhY3Rpb25faWQsIHRlc3RuZXRVVFhPLlVUWE9fMS50eF9oYXNoKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHhKc29uLmlucHV0c1sxXS50cmFuc2FjdGlvbl9pZCwgdGVzdG5ldFVUWE8uVVRYT19UT0tFTi50eF9oYXNoKTtcblxuICAgICAgLy8gVHdvIG91dHB1dHM6IHRva2VuIG91dHB1dCAod2l0aCBtdWx0aUFzc2V0cykgKyBwdXJlIEFEQSBjaGFuZ2UgdG8gYmFzZSBhZGRyZXNzXG4gICAgICB0eEpzb24ub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgY29uc3QgdG9rZW5PdXRwdXQgPSB0eEpzb24ub3V0cHV0cy5maW5kKChvKSA9PiBvLm11bHRpQXNzZXRzICE9PSB1bmRlZmluZWQpO1xuICAgICAgc2hvdWxkLmV4aXN0KHRva2VuT3V0cHV0KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodG9rZW5PdXRwdXQhLmFkZHJlc3MsIGJhc2VBZGRyKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwoTnVtYmVyKHRva2VuT3V0cHV0IS5hbW91bnQpLCBtaW5BREFGb3JUb2tlbik7XG4gICAgICBjb25zdCBleHBlY3RlZFBvbGljeUlkID0gQ2FyZGFub1dhc20uU2NyaXB0SGFzaC5mcm9tX2J5dGVzKEJ1ZmZlci5mcm9tKHRva2VuUG9saWN5SWQsICdoZXgnKSk7XG4gICAgICBjb25zdCBleHBlY3RlZEFzc2V0TmFtZSA9IENhcmRhbm9XYXNtLkFzc2V0TmFtZS5uZXcoQnVmZmVyLmZyb20odG9rZW5FbmNvZGVkQXNzZXROYW1lLCAnaGV4JykpO1xuICAgICAgKHRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyBhcyBDYXJkYW5vV2FzbS5NdWx0aUFzc2V0KVxuICAgICAgICAuZ2V0X2Fzc2V0KGV4cGVjdGVkUG9saWN5SWQsIGV4cGVjdGVkQXNzZXROYW1lKVxuICAgICAgICAudG9fc3RyKClcbiAgICAgICAgLnNob3VsZC5lcXVhbCh0b2tlblF1YW50aXR5KTtcblxuICAgICAgY29uc3QgYWRhT3V0cHV0ID0gdHhKc29uLm91dHB1dHMuZmluZCgobykgPT4gby5tdWx0aUFzc2V0cyA9PT0gdW5kZWZpbmVkKTtcbiAgICAgIHNob3VsZC5leGlzdChhZGFPdXRwdXQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChhZGFPdXRwdXQhLmFkZHJlc3MsIGJhc2VBZGRyKTtcbiAgICAgIGNvbnN0IGZlZSA9IE51bWJlcih0eC5leHBsYWluVHJhbnNhY3Rpb24oKS5mZWUuZmVlKTtcbiAgICAgIGNvbnN0IHRvdGFsQmFsYW5jZSA9IHRlc3RuZXRVVFhPLlVUWE9fMS52YWx1ZSArIHRlc3RuZXRVVFhPLlVUWE9fVE9LRU4udmFsdWU7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKE51bWJlcihhZGFPdXRwdXQhLmFtb3VudCksIHRvdGFsQmFsYW5jZSAtIG1pbkFEQUZvclRva2VuIC0gZmVlKTtcblxuICAgICAgLy8gcGFyc2VkVHggaW5wdXRzIG11c3QgY2FycnkgbXVsdGlBc3NldHMgZm9yIHRoZSB0b2tlbiBVVFhPXG4gICAgICBjb25zdCBwYXJzZWRUeElucHV0cyA9IHVuc2lnbmVkVHgucGFyc2VkVHguaW5wdXRzIGFzIHtcbiAgICAgICAgYWRkcmVzczogc3RyaW5nO1xuICAgICAgICB2YWx1ZVN0cmluZzogc3RyaW5nO1xuICAgICAgICBtdWx0aUFzc2V0cz86IHsgcG9saWN5X2lkOiBzdHJpbmc7IGFzc2V0X25hbWU6IHN0cmluZzsgcXVhbnRpdHk6IHN0cmluZyB9W107XG4gICAgICB9W107XG4gICAgICBwYXJzZWRUeElucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeElucHV0c1swXS5hZGRyZXNzLCBjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRBZGRyZXNzMik7XG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMpO1xuICAgICAgcGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMhLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFR4SW5wdXRzWzBdLm11bHRpQXNzZXRzIVswXS5wb2xpY3lfaWQsIHRva2VuUG9saWN5SWQpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUeElucHV0c1swXS5tdWx0aUFzc2V0cyFbMF0uYXNzZXRfbmFtZSwgdG9rZW5FbmNvZGVkQXNzZXROYW1lKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVHhJbnB1dHNbMF0ubXVsdGlBc3NldHMhWzBdLnF1YW50aXR5LCB0b2tlblF1YW50aXR5KTtcblxuICAgICAgLy8gcGFyc2VkVHggb3V0cHV0cyBtdXN0IGNhcnJ5IG11bHRpQXNzZXRzIGZvciB0aGUgdG9rZW4gb3V0cHV0XG4gICAgICBjb25zdCBwYXJzZWRUeE91dHB1dHMgPSB1bnNpZ25lZFR4LnBhcnNlZFR4Lm91dHB1dHMgYXMge1xuICAgICAgICBhZGRyZXNzOiBzdHJpbmc7XG4gICAgICAgIHZhbHVlU3RyaW5nOiBzdHJpbmc7XG4gICAgICAgIG11bHRpQXNzZXRzPzogeyBwb2xpY3lfaWQ6IHN0cmluZzsgYXNzZXRfbmFtZTogc3RyaW5nOyBxdWFudGl0eTogc3RyaW5nIH1bXTtcbiAgICAgIH1bXTtcbiAgICAgIGNvbnN0IHBhcnNlZFRva2VuT3V0cHV0ID0gcGFyc2VkVHhPdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgIT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkVG9rZW5PdXRwdXQpO1xuICAgICAgcGFyc2VkVG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbChwYXJzZWRUb2tlbk91dHB1dCEubXVsdGlBc3NldHMhWzBdLnBvbGljeV9pZCwgdG9rZW5Qb2xpY3lJZCk7XG4gICAgICBzaG91bGQuZGVlcEVxdWFsKHBhcnNlZFRva2VuT3V0cHV0IS5tdWx0aUFzc2V0cyFbMF0uYXNzZXRfbmFtZSwgdG9rZW5FbmNvZGVkQXNzZXROYW1lKTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwocGFyc2VkVG9rZW5PdXRwdXQhLm11bHRpQXNzZXRzIVswXS5xdWFudGl0eSwgdG9rZW5RdWFudGl0eSk7XG4gICAgICAvLyBwdXJlIEFEQSBvdXRwdXQgbXVzdCBub3QgaGF2ZSBtdWx0aUFzc2V0c1xuICAgICAgY29uc3QgcGFyc2VkQWRhT3V0cHV0ID0gcGFyc2VkVHhPdXRwdXRzLmZpbmQoKG8pID0+IG8ubXVsdGlBc3NldHMgPT09IHVuZGVmaW5lZCk7XG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkQWRhT3V0cHV0KTtcblxuICAgICAgLy8gbGFzdFNjYW5JbmRleCBpbiBjb2luU3BlY2lmaWMgb2YgdGhlIGxhc3QgdHhSZXF1ZXN0XG4gICAgICB1bnNpZ25lZFR4LmNvaW5TcGVjaWZpYy5zaG91bGQuaGFzT3duUHJvcGVydHkoJ2xhc3RTY2FuSW5kZXgnKTtcbiAgICAgIHVuc2lnbmVkVHguY29pblNwZWNpZmljLmxhc3RTY2FuSW5kZXguc2hvdWxkLmVxdWFsKDMpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBpZiBhbGwgYWRkcmVzc2VzIGhhdmUgYmFsYW5jZSBsZXNzIHRoYW4gMSBBREEnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKEFkYS5wcm90b3R5cGUsICdnZXREYXRhRnJvbU5vZGUnIGFzIGtleW9mIEFkYSk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygnYWRkcmVzc19pbmZvJywgc2lub24ubWF0Y2guaGFzKCdfYWRkcmVzc2VzJykpLnJlc29sdmVzKHtcbiAgICAgICAgc3RhdHVzOiAyMDAsXG4gICAgICAgIGJvZHk6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBiYWxhbmNlOiA1MDAwMDAsXG4gICAgICAgICAgICB1dHhvX3NldDogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogJzhkZjhkNDEyMDc5ODBmOWUyMWRlNjk4YmQ1ZDZjMzk1YzM5ZTQyMGY3ZGUyN2Y4NTM5MDUyZGQzNGUzYTI4ZDYnLFxuICAgICAgICAgICAgICAgIHR4X2luZGV4OiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiA1MDAwMDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgICB1c2VyS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogY29uc29saWRhdGlvbldyd1VzZXIuYmFja3VwS2V5LFxuICAgICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0RpZCBub3QgZmluZCBhbiBhZGRyZXNzIHdpdGggZnVuZHMgdG8gcmVjb3Zlci4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgZXZlbiBpZiBzaW5nbGUgYWRkcmVzcyBoYXMgbm8gZnVuZHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyQ29uc29saWRhdGlvbnMoe1xuICAgICAgICB1c2VyS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgZW5kaW5nU2NhbkluZGV4OiA0LFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnRyYW5zYWN0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBldmVuIGlmIHNpbmdsZSBhZGRyZXNzIGhhcyBpbnN1ZmZpY2llbnQgZnVuZHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBiYXNlY29pbi5yZWNvdmVyQ29uc29saWRhdGlvbnMoe1xuICAgICAgICB1c2VyS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci51c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IGNvbnNvbGlkYXRpb25XcndVc2VyLmJpdGdvS2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBjb25zb2xpZGF0aW9uV3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBzdGFydGluZ1NjYW5JbmRleDogMSxcbiAgICAgICAgZW5kaW5nU2NhbkluZGV4OiA0LFxuICAgICAgfSk7XG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgcmVzLnRyYW5zYWN0aW9ucy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQnVpbGQgQ29uc29saWRhdGlvbiBSZWNvdmVyaWVzIChNUEN2Mik6JywgKCkgPT4ge1xuICAgIGNvbnN0IHNhbmRCb3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9IHdyd1VzZXIud2FsbGV0UGFzc3BocmFzZTtcbiAgICBsZXQgbXBjVjJVc2VyS2V5OiBzdHJpbmc7XG4gICAgbGV0IG1wY1YyQmFja3VwS2V5OiBzdHJpbmc7XG4gICAgbGV0IG1wY1YyQ29tbW9uS2V5Q2hhaW46IHN0cmluZztcbiAgICBsZXQgYmFzZUFkZHI6IHN0cmluZztcbiAgICBsZXQgbXBjVjJBZGRyZXNzMTogc3RyaW5nO1xuICAgIGxldCBtcGNWMkFkZHJlc3MyOiBzdHJpbmc7XG4gICAgbGV0IG1wY1YyQWRkcmVzczM6IHN0cmluZztcblxuICAgIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBbdXNlckRrZywgYmFja3VwRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuXG4gICAgICBtcGNWMlVzZXJLZXkgPSBhd2FpdCBlbmNyeXB0KHdhbGxldFBhc3NwaHJhc2UsIHVzZXJEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcbiAgICAgIG1wY1YyQmFja3VwS2V5ID0gYXdhaXQgZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCBiYWNrdXBEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcbiAgICAgIG1wY1YyQ29tbW9uS2V5Q2hhaW4gPSB1c2VyRGtnLmdldENvbW1vbktleWNoYWluKCk7XG5cbiAgICAgIGJhc2VBZGRyID0gKGF3YWl0IGJhc2Vjb2luLmdldEFkYUFkZHJlc3NBbmRBY2NvdW50SWQoeyBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbiwgaW5kZXg6IDAgfSkpLmFkZHJlc3M7XG4gICAgICBtcGNWMkFkZHJlc3MxID0gKGF3YWl0IGJhc2Vjb2luLmdldEFkYUFkZHJlc3NBbmRBY2NvdW50SWQoeyBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbiwgaW5kZXg6IDEgfSkpLmFkZHJlc3M7XG4gICAgICBtcGNWMkFkZHJlc3MyID0gKGF3YWl0IGJhc2Vjb2luLmdldEFkYUFkZHJlc3NBbmRBY2NvdW50SWQoeyBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbiwgaW5kZXg6IDIgfSkpLmFkZHJlc3M7XG4gICAgICBtcGNWMkFkZHJlc3MzID0gKGF3YWl0IGJhc2Vjb2luLmdldEFkYUFkZHJlc3NBbmRBY2NvdW50SWQoeyBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbiwgaW5kZXg6IDMgfSkpLmFkZHJlc3M7XG4gICAgfSk7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKEFkYS5wcm90b3R5cGUsICdnZXREYXRhRnJvbU5vZGUnIGFzIGtleW9mIEFkYSk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW21wY1YyQWRkcmVzczFdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLlplcm9VVFhPKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgeyBfYWRkcmVzc2VzOiBbbXBjVjJBZGRyZXNzMl0gfSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuT25lVVRYTyk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW21wY1YyQWRkcmVzczNdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8yKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNhbmRCb3gucmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBNUEN2MiBzaWduZWQgY29uc29saWRhdGlvbiByZWNvdmVyaWVzIGFjcm9zcyAyKyBmdW5kZWQgaW5kZXhlcywgc3dlZXBpbmcgdG8gdGhlIE1QQ3YyIGJhc2UgYWRkcmVzcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGdldEVkZHNhTWF0ZXJpYWxTcHkgPSBzYW5kQm94LnNweShcbiAgICAgICAgYmFzZWNvaW4gYXMgdW5rbm93biBhcyB7IGdldEVkZHNhU2lnbmluZ01hdGVyaWFsOiB1bmtub3duIH0sXG4gICAgICAgICdnZXRFZGRzYVNpZ25pbmdNYXRlcmlhbCdcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGJhc2Vjb2luLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgIHVzZXJLZXk6IG1wY1YyVXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBtcGNWMkJhY2t1cEtleSxcbiAgICAgICAgYml0Z29LZXk6IG1wY1YyQ29tbW9uS2V5Q2hhaW4sXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDQsXG4gICAgICB9KTtcblxuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHJlcy5sYXN0U2NhbkluZGV4LnNob3VsZC5lcXVhbCgzKTtcblxuICAgICAgY29uc3QgdHgxID0gbmV3IFRyYW5zYWN0aW9uKGJhc2Vjb2luKTtcbiAgICAgIHR4MS5mcm9tUmF3VHJhbnNhY3Rpb24ocmVzLnRyYW5zYWN0aW9uc1swXS5zZXJpYWxpemVkVHgpO1xuICAgICAgc2hvdWxkLmRlZXBFcXVhbCh0eDEudG9Kc29uKCkub3V0cHV0c1swXS5hZGRyZXNzLCBiYXNlQWRkcik7XG5cbiAgICAgIC8vIHJlY292ZXJDb25zb2xpZGF0aW9ucyBtdXN0IGRldGVjdCBzaWduaW5nIG1hdGVyaWFsIGV4YWN0bHkgb25jZSBhdCB0aGUgdG9wIG9mIHRoZSBzY2FuXG4gICAgICAvLyBsb29wLCBub3QgcGVyLWl0ZXJhdGlvbiBpbnNpZGUgcmVjb3ZlcigpIOKAlCBwcmVjb21wdXRlZE1hdGVyaWFsIGJ5cGFzc2VzIHBlci1jYWxsIGRldGVjdGlvbi5cbiAgICAgIHNhbmRCb3guYXNzZXJ0LmNhbGxlZE9uY2UoZ2V0RWRkc2FNYXRlcmlhbFNweSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGxlYXZlIE1QQ3YxIGJhc2UgYWRkcmVzcyBkZXJpdmF0aW9uIGFuZCBzaWduaW5nIHVuY2hhbmdlZCAocmVncmVzc2lvbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICAgIGNvbnN0IGNhbGxCYWNrID0gc2FuZEJveC5zdHViKEFkYS5wcm90b3R5cGUsICdnZXREYXRhRnJvbU5vZGUnIGFzIGtleW9mIEFkYSk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MxXSB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5aZXJvVVRYTyk7XG4gICAgICBjYWxsQmFja1xuICAgICAgICAud2l0aEFyZ3MoJ2FkZHJlc3NfaW5mbycsIHsgX2FkZHJlc3NlczogW2NvbnNvbGlkYXRpb25XcndVc2VyLndhbGxldEFkZHJlc3MyXSB9KVxuICAgICAgICAucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMuYWRkcmVzc0luZm9SZXNwb25zZS5PbmVVVFhPKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgeyBfYWRkcmVzc2VzOiBbY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczNdIH0pXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVVUWE8yKTtcbiAgICAgIGNhbGxCYWNrLndpdGhBcmdzKCd0aXAnKS5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy50aXBJbmZvUmVzcG9uc2UpO1xuXG4gICAgICBjb25zdCBnZXRUU1NTaWduYXR1cmVTcHkgPSBzYW5kQm94LnNweShFRERTQU1ldGhvZHMsICdnZXRUU1NTaWduYXR1cmUnKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgdXNlcktleTogY29uc29saWRhdGlvbldyd1VzZXIudXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgIGJpdGdvS2V5OiBjb25zb2xpZGF0aW9uV3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgc3RhcnRpbmdTY2FuSW5kZXg6IDEsXG4gICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgIH0pO1xuXG4gICAgICByZXMuc2hvdWxkLm5vdC5iZS5lbXB0eSgpO1xuICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbGVkKGdldFRTU1NpZ25hdHVyZVNweSk7XG5cbiAgICAgIGNvbnN0IHR4MSA9IG5ldyBUcmFuc2FjdGlvbihiYXNlY29pbik7XG4gICAgICB0eDEuZnJvbVJhd1RyYW5zYWN0aW9uKHJlcy50cmFuc2FjdGlvbnNbMF0uc2VyaWFsaXplZFR4KTtcbiAgICAgIHNob3VsZC5kZWVwRXF1YWwodHgxLnRvSnNvbigpLm91dHB1dHNbMF0uYWRkcmVzcywgY29uc29saWRhdGlvbldyd1VzZXIud2FsbGV0QWRkcmVzczApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBsZWF2ZSB0aGUgdW5zaWduZWQgKG5vIHBhc3NwaHJhc2UpIGNvbGQgcGF0aCB1bmNoYW5nZWQgd2hlbiBrZXljYXJkIGlzIE1QQ3YyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgYmFzZWNvaW4ucmVjb3ZlckNvbnNvbGlkYXRpb25zKHtcbiAgICAgICAgYml0Z29LZXk6IG1wY1YyQ29tbW9uS2V5Q2hhaW4sXG4gICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICBlbmRpbmdTY2FuSW5kZXg6IDQsXG4gICAgICB9KTtcblxuICAgICAgcmVzLnNob3VsZC5ub3QuYmUuZW1wdHkoKTtcbiAgICAgIHJlcy50eFJlcXVlc3RzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IG1pc3NpbmcgdXNlcktleSBiZWZvcmUgc2Nhbm5pbmcgd2hlbiB3YWxsZXRQYXNzcGhyYXNlIGlzIHNldCBidXQgdXNlcktleSBpcyBvbWl0dGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZ2V0RWRkc2FNYXRlcmlhbFNweSA9IHNhbmRCb3guc3B5KFxuICAgICAgICBiYXNlY29pbiBhcyB1bmtub3duIGFzIHsgZ2V0RWRkc2FTaWduaW5nTWF0ZXJpYWw6IHVua25vd24gfSxcbiAgICAgICAgJ2dldEVkZHNhU2lnbmluZ01hdGVyaWFsJ1xuICAgICAgKTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnJlY292ZXJDb25zb2xpZGF0aW9ucyh7XG4gICAgICAgICAgYmFja3VwS2V5OiBtcGNWMkJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogbXBjVjJDb21tb25LZXlDaGFpbixcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHN0YXJ0aW5nU2NhbkluZGV4OiAxLFxuICAgICAgICAgIGVuZGluZ1NjYW5JbmRleDogNCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgdXNlcktleScpO1xuXG4gICAgICBzYW5kQm94LmFzc2VydC5ub3RDYWxsZWQoZ2V0RWRkc2FNYXRlcmlhbFNweSk7XG4gICAgICBzYW5kQm94LmFzc2VydC5ub3RDYWxsZWQoYmFzZWNvaW4uZ2V0RGF0YUZyb21Ob2RlIGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWNvdmVyIFRyYW5zYWN0aW9ucyBGYWlsdXJlOicsICgpID0+IHtcbiAgICBjb25zdCBkZXN0QWRkciA9IGFkZHJlc3MuYWRkcmVzczI7XG4gICAgY29uc3Qgc2FuZEJveCA9IHNpbm9uLmNyZWF0ZVNhbmRib3goKTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBzYW5kQm94LnJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byByZWNvdmVyIGR1ZSB0byBub3QgZmluZGluZyBhbiBhZGRyZXNzIHdpdGggZnVuZHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjYWxsQmFjayA9IHNhbmRCb3guc3R1YihBZGEucHJvdG90eXBlLCAnZ2V0RGF0YUZyb21Ob2RlJyBhcyBrZXlvZiBBZGEpO1xuICAgICAgY2FsbEJhY2tcbiAgICAgICAgLndpdGhBcmdzKCdhZGRyZXNzX2luZm8nLCBzaW5vbi5tYXRjaC5oYXMoJ19hZGRyZXNzZXMnKSlcbiAgICAgICAgLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLmFkZHJlc3NJbmZvUmVzcG9uc2UuWmVyb1VUWE8pO1xuICAgICAgY2FsbEJhY2sud2l0aEFyZ3MoJ3RpcCcpLnJlc29sdmVzKGVuZHBvaW50UmVzcG9uc2VzLnRpcEluZm9SZXNwb25zZSk7XG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAucmVjb3Zlcih7XG4gICAgICAgICAgdXNlcktleTogd3J3VXNlci51c2VyS2V5LFxuICAgICAgICAgIGJhY2t1cEtleTogd3J3VXNlci5iYWNrdXBLZXksXG4gICAgICAgICAgYml0Z29LZXk6IHdyd1VzZXIuYml0Z29LZXksXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogd3J3VXNlci53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIHJlY292ZXJ5RGVzdGluYXRpb246IGRlc3RBZGRyLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLnJlamVjdGVkV2l0aCgnRGlkIG5vdCBmaW5kIGFkZHJlc3Mgd2l0aCBmdW5kcyB0byByZWNvdmVyLicpO1xuICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbGVkT25jZShiYXNlY29pbi5nZXREYXRhRnJvbU5vZGUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHJlY292ZXIgZHVlIHRvIG5vdCBoYXZpbmcgbW9yZSB0aGFuIDEgQURBIGluIGZ1bmRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY2FsbEJhY2sgPSBzYW5kQm94LnN0dWIoQWRhLnByb3RvdHlwZSwgJ2dldERhdGFGcm9tTm9kZScgYXMga2V5b2YgQWRhKTtcbiAgICAgIGNhbGxCYWNrXG4gICAgICAgIC53aXRoQXJncygnYWRkcmVzc19pbmZvJywgc2lub24ubWF0Y2guaGFzKCdfYWRkcmVzc2VzJykpXG4gICAgICAgIC5yZXNvbHZlcyhlbmRwb2ludFJlc3BvbnNlcy5hZGRyZXNzSW5mb1Jlc3BvbnNlLk9uZVNtYWxsVVRYTyk7XG4gICAgICBjYWxsQmFjay53aXRoQXJncygndGlwJykucmVzb2x2ZXMoZW5kcG9pbnRSZXNwb25zZXMudGlwSW5mb1Jlc3BvbnNlKTtcbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5yZWNvdmVyKHtcbiAgICAgICAgICB1c2VyS2V5OiB3cndVc2VyLnVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5OiB3cndVc2VyLmJhY2t1cEtleSxcbiAgICAgICAgICBiaXRnb0tleTogd3J3VXNlci5iaXRnb0tleSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiB3cndVc2VyLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogZGVzdEFkZHIsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICdJbnN1ZmZpY2llbnQgZnVuZHMgdG8gcmVjb3ZlciwgbWluaW11bSByZXF1aXJlZCBpcyAxIEFEQSBwbHVzIGZlZXMsIGdvdCA4MzQ0NTUgZmVlczogMTY1NTQ1J1xuICAgICAgICApO1xuICAgICAgc2FuZEJveC5hc3NlcnQuY2FsbGVkVHdpY2UoYmFzZWNvaW4uZ2V0RGF0YUZyb21Ob2RlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1ZlcmlmeSB3YWxsZXQgYWRkcmVzcyAoaXNXYWxsZXRBZGRyZXNzKTonLCAoKSA9PiB7XG4gICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPVxuICAgICAgJ2VkMzEyZDBkYjQ2MTU2ODgyMTljNDMyMzFlYjRiOThkNTg4M2MwYjQ0YmNmZWYxOTU2MjkwNTU1OTk1YWQ2OGVmN2MyMjkxN2I0YThiNjkxODM4NjRiODNjYzcwMjg2NTVjZDdhNzBlZjc2ZDY5NDhkODA5YTE1MDUwMDU0ODQwJztcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgdmFsaWQgd2FsbGV0IGFkZHJlc3MgYXQgaW5kZXggMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcyJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycsXG4gICAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMycsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGFkZHJlc3MgPVxuICAgICAgICAnYWRkcl90ZXN0MXF6dm1hem1wZ2ZoanlwcHdsc3cyOXpqandhemNzZms2Mno5enY1dnN2MjRwMHd5ZWg2OWt6c24weWd6emFscXU1Mjk5eWE2OTNxbmQ1NXkyeWVnZXFjNDJ6N3VxMGdlMnBxJztcbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICBhZGRyZXNzLFxuICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgfSk7XG5cbiAgICAgIGlzVmFsaWQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIHZlcmlmeSBhbiBhZGRyZXNzIHdpdGggd3JvbmcgaW5kZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXljaGFpbnMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICd1c2VyJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMicsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzMnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiaXRnbycgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBpc1ZhbGlkID0gYXdhaXQgYmFzZWNvaW4uaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgYWRkcmVzczpcbiAgICAgICAgICAnYWRkcl90ZXN0MXF6dm1hem1wZ2ZoanlwcHdsc3cyOXpqandhemNzZms2Mno5enY1dnN2MjRwMHd5ZWg2OWt6c24weWd6emFscXU1Mjk5eWE2OTNxbmQ1NXkyeWVnZXFjNDJ6N3VxMGdlMnBxJyxcbiAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICBpbmRleDogMixcbiAgICAgIH0pO1xuXG4gICAgICBpc1ZhbGlkLnNob3VsZC5lcXVhbChmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gdmVyaWZ5IGEgcmFuZG9tIGFkZHJlc3Mgbm90IGZyb20gd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAndXNlcicgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzInLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICczJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAnYml0Z28nIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgLy8gVXNlIGEgcmFuZG9tIHZhbGlkIEFEQSBhZGRyZXNzIG5vdCBmcm9tIHRoaXMgd2FsbGV0XG4gICAgICBjb25zdCByYW5kb21BZGRyZXNzID0gJ2FkZHJfdGVzdDF2cjhyYWttNjZyY2Z2NGZjeHF5a2c1bGYweXY3bHN5azltdmFweDM2OWpwdnRjZ2ZjdWs3Zic7XG5cbiAgICAgIGNvbnN0IGlzVmFsaWQgPSBhd2FpdCBiYXNlY29pbi5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICBhZGRyZXNzOiByYW5kb21BZGRyZXNzLFxuICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgfSk7XG5cbiAgICAgIGlzVmFsaWQuc2hvdWxkLmVxdWFsKGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgYWRkcmVzcyBmb3JtYXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXljaGFpbnMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICd1c2VyJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMicsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ2JhY2t1cCcgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzMnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiaXRnbycgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCBpbnZhbGlkQWRkcmVzcyA9ICdub3RfYV92YWxpZF9hZGRyZXNzJztcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzczogaW52YWxpZEFkZHJlc3MsXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCBDYXJkYW5vIEFkZHJlc3M6IG5vdF9hX3ZhbGlkX2FkZHJlc3MnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBrZXljaGFpbnMgYXJlIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGRyZXNzID1cbiAgICAgICAgJ2FkZHJfdGVzdDFxenZtYXptcGdmaGp5cHB3bHN3Mjl6amp3YXpjc2ZrNjJ6OXp2NXZzdjI0cDB3eWVoNjlrenNuMHlnenphbHF1NTI5OXlhNjkzcW5kNTV5MnllZ2VxYzQyejd1cTBnZTJwcSc7XG5cbiAgICAgIGF3YWl0IGJhc2Vjb2luXG4gICAgICAgIC5pc1dhbGxldEFkZHJlc3Moe1xuICAgICAgICAgIGFkZHJlc3MsXG4gICAgICAgICAga2V5Y2hhaW5zOiBbXSxcbiAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcmVxdWlyZWQgcGFyYW0ga2V5Y2hhaW5zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gY29tbW9uS2V5Y2hhaW4gaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAndXNlcicgYXMgY29uc3QsXG4gICAgICAgICAgLy8gY29tbW9uS2V5Y2hhaW4gaXMgbWlzc2luZ1xuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgY29uc3QgYWRkcmVzcyA9XG4gICAgICAgICdhZGRyX3Rlc3QxcXp2bWF6bXBnZmhqeXBwd2xzdzI5empqd2F6Y3NmazYyejl6djV2c3YyNHAwd3llaDY5a3pzbjB5Z3p6YWxxdTUyOTl5YTY5M3FuZDU1eTJ5ZWdlcWM0Mno3dXEwZ2UycHEnO1xuXG4gICAgICBhd2FpdCBiYXNlY29pblxuICAgICAgICAuaXNXYWxsZXRBZGRyZXNzKHtcbiAgICAgICAgICBhZGRyZXNzLFxuICAgICAgICAgIGtleWNoYWlucyxcbiAgICAgICAgICBpbmRleDogMCxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ21pc3NpbmcgcmVxdWlyZWQgcGFyYW0gY29tbW9uS2V5Y2hhaW4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBrZXljaGFpbnMgaGF2ZSBtaXNtYXRjaGVkIGNvbW1vbktleWNoYWlucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIGlkOiAnMScsXG4gICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcyJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogJ2RpZmZlcmVudEtleWNoYWluMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZicsXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAnYmFja3VwJyBhcyBjb25zdCxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGFkZHJlc3MgPVxuICAgICAgICAnYWRkcl90ZXN0MXF6dm1hem1wZ2ZoanlwcHdsc3cyOXpqandhemNzZms2Mno5enY1dnN2MjRwMHd5ZWg2OWt6c24weWd6emFscXU1Mjk5eWE2OTNxbmQ1NXkyeWVnZXFjNDJ6N3VxMGdlMnBxJztcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgICAgYWRkcmVzcyxcbiAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdhbGwga2V5Y2hhaW5zIG11c3QgaGF2ZSB0aGUgc2FtZSBjb21tb25LZXljaGFpbiBmb3IgTVBDIGNvaW5zJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhZGRyZXNzIHdoZW4gZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCBpcyBwcmVzZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCA9ICd0ZXN0RGVyaXZhdGlvblNlZWQxMjMnO1xuXG4gICAgICBjb25zdCBrZXljaGFpbnMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzEnLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkOiBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkLFxuICAgICAgICAgIHR5cGU6ICd0c3MnIGFzIGNvbnN0LFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcyJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZDogZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCxcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICczJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZDogZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCxcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiaXRnbycgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICBdO1xuXG4gICAgICBjb25zdCB7IGFkZHJlc3M6IGV4cGVjdGVkQWRkcmVzcyB9ID0gYXdhaXQgKGJhc2Vjb2luIGFzIGFueSkuZ2V0QWRhQWRkcmVzc0FuZEFjY291bnRJZCh7XG4gICAgICAgIGJpdGdvS2V5OiBjb21tb25LZXljaGFpbixcbiAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgIHNlZWQ6IGRlcml2ZWRGcm9tUGFyZW50V2l0aFNlZWQsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgaXNWYWxpZCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3M6IGV4cGVjdGVkQWRkcmVzcyxcbiAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICBpbmRleDogMCxcbiAgICAgIH0pO1xuXG4gICAgICBpc1ZhbGlkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB2ZXJpZmljYXRpb24gd2hlbiBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkIGlzIG1pc3NpbmcgYnV0IGFkZHJlc3Mgd2FzIGNyZWF0ZWQgd2l0aCBzZWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCA9ICd0ZXN0RGVyaXZhdGlvblNlZWQxMjMnO1xuICAgICAgY29uc3QgeyBhZGRyZXNzOiBhZGRyZXNzV2l0aFNlZWQgfSA9IGF3YWl0IChiYXNlY29pbiBhcyBhbnkpLmdldEFkYUFkZHJlc3NBbmRBY2NvdW50SWQoe1xuICAgICAgICBiaXRnb0tleTogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgICBzZWVkOiBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGtleWNoYWluc1dpdGhvdXRTZWVkID0gW1xuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICcxJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAndXNlcicgYXMgY29uc3QsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogJzInLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbixcbiAgICAgICAgICB0eXBlOiAndHNzJyBhcyBjb25zdCxcbiAgICAgICAgICBzb3VyY2U6ICdiYWNrdXAnIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgaWQ6ICczJyxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgdHlwZTogJ3RzcycgYXMgY29uc3QsXG4gICAgICAgICAgc291cmNlOiAnYml0Z28nIGFzIGNvbnN0LFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgY29uc3QgaXNWYWxpZCA9IGF3YWl0IGJhc2Vjb2luLmlzV2FsbGV0QWRkcmVzcyh7XG4gICAgICAgIGFkZHJlc3M6IGFkZHJlc3NXaXRoU2VlZCxcbiAgICAgICAga2V5Y2hhaW5zOiBrZXljaGFpbnNXaXRob3V0U2VlZCxcbiAgICAgICAgaW5kZXg6IDAsXG4gICAgICB9KTtcblxuICAgICAgaXNWYWxpZC5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVmVyaWZ5IHRva2VuIGNvbnNvbGlkYXRpb24gdHJhbnNhY3Rpb246JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZmFpbCB0byB2ZXJpZnkgYSBzcG9vZmVkIHRva2VuIGNvbnNvbGlkYXRpb24gdHJhbnNhY3Rpb24gd2l0aCBpbmNvcnJlY3QgYWRkcmVzcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNvbnNvbGlkYXRpb25UeCA9IHtcbiAgICAgICAgdHhSZXF1ZXN0SWQ6ICc0ZmRkMGNhZS0yNTYzLTQzYjEtYjVjZi05NDg2NTE1OGNhMTAnLFxuICAgICAgICB3YWxsZXRJZDogJzYzMDY4ZWQ0ZWZhNjNhMDAwODc3ZjAyZmQ0YjBmYTZkJyxcbiAgICAgICAgdHhIZXg6XG4gICAgICAgICAgJzg0YTQwMDgxODI1ODIwNGJkMGY5OTFjMTUzMmNmZmUzMWQ0YTEwZGI0OTJiNDMxNzVlYzMyNjc2NWI2YjI5Y2VlZTU5OGRmMmI2MWY0NzAwMDE4MTgyNTgzOTAwODczNzllYmM1NTMzZWJlNjIxOTYzYzkxNWMzY2JjNWYwODUzN2ZjZGNhNGFmOGY4YWUwOGVkNGM4NzM3OWViYzU1MzNlYmU2MjE5NjNjOTE1YzNjYmM1ZjA4NTM3ZmNkY2E0YWY4ZjhhZTA4ZWQ0YzFhMDVmMzU5ZmYwMjFhMDAwMjg3MDEwMzFhMDI0OTcyZTFhMTAwODE4MjU4MjBiYmFjYjEzNDMxYjk5MjA4ZTZlOGNkYmY3MTAxNDdmZWFmMDZhMzlkNzE1NjVlNjBiNDExY2U5ZTRmYTNmMTM3NTg0MDAxYTRhYjgyMzY1NjNmNjlmZjMwOWU1Nzg2ZThmMzljNjI5ZWQ1NzY3NmM2OTIxNTljYjJlMDQ5NGM5ZTY2MzM1NTM4NGMxM2M3NDlkMDRjMTdhODBiYTJhNDVjYzEyN2RmNDgwZmM2NGE0MzE5OWE3NzJmMTFhY2Q1YjE0YTBmZjVmNicsXG4gICAgICAgIGZlZUluZm86IHtcbiAgICAgICAgICBmZWU6IDEwMDAwLFxuICAgICAgICAgIGZlZVN0cmluZzogJzEwMDAwJyxcbiAgICAgICAgfSxcbiAgICAgICAgdHhJbmZvOiB7XG4gICAgICAgICAgaW5wdXRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6ICc4aUxhMjZLU2JkcEJVek5LN3VZcThGdnl1eUE1aDRrNGVyREhzRGNQYkh1cycsXG4gICAgICAgICAgICAgIHZhbHVlOiAyLjAxNzMyMjhlMTAsXG4gICAgICAgICAgICAgIHZhbHVlU3RyaW5nOiAnMjAxNzMyMjgwMDAnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWRkcmVzczogJzhQMmtYN1R5aDllUzNSS2RhQmhxYkV0UUdBWDU4RFh6TDdtaERRQUJHWDJkJyxcbiAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzEwMDAwJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBtaW5lckZlZTogJzEwMDAwJyxcbiAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFkZHJlc3M6ICdhZGRyX3Rlc3QxdnI4cmFrbTY2cmNmdjRmY3hxeWtnNWxmMHl2N2xzeWs5bXZhcHgzNjlqcHZ0Y2dmY3VrN2YnLFxuICAgICAgICAgICAgICBjb2luTmFtZTogJ3RhZGE6dXNkdCcsXG4gICAgICAgICAgICAgIGVudGVycHJpc2U6IHtcbiAgICAgICAgICAgICAgICAkb2lkOiAnNTU1M2JhOGFlN2E1Yzc3MDA2NzE5NjYxJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZW50ZXJwcmlzZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAkb2lkOiAnNTU1M2JhOGFlN2E1Yzc3MDA2NzE5NjYxJyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB2YWx1ZTogMi4wMTczMjI4ZTEwLFxuICAgICAgICAgICAgICB2YWx1ZVN0cmluZzogJzIwMTczMjI4MDAwJyxcbiAgICAgICAgICAgICAgd2FsbGV0OiB7XG4gICAgICAgICAgICAgICAgJG9pZDogJzYyZjRjMzcyMGQ5MmM1MDAwODI1N2ViNScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgICAgICAgICB3YWxsZXRzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgJG9pZDogJzYyZjRjMzcyMGQ5MmM1MDAwODI1N2ViNScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBwYXlHb0ZlZTogJzAnLFxuICAgICAgICAgIHNwZW5kQW1vdW50OiAnMjAxNzMyMjgwMDAnLFxuICAgICAgICAgIHNwZW5kQW1vdW50czogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhbW91bnRTdHJpbmc6ICcyMDE3MzIyODAwMCcsXG4gICAgICAgICAgICAgIGNvaW5OYW1lOiAndGFkYTp1c2R0JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0eXBlOiAnU2VuZCcsXG4gICAgICAgIH0sXG4gICAgICAgIGNvbnNvbGlkYXRlSWQ6ICc2NzEyZDdmZGE2ZGU0OTA2ZDY1OGMwNGFlYmJmOGY5YicsXG4gICAgICAgIGNvaW46ICd0YWRhJyxcbiAgICAgIH07XG5cbiAgICAgIC8vIE1vY2sgdGhlIHdhbGxldCB3aXRoIGEgZGlmZmVyZW50IGFkZHJlc3MgdGhhbiB0aGUgdHJhbnNhY3Rpb24ncyBvdXRwdXRcbiAgICAgIGNvbnN0IG1vY2tlZFdhbGxldCA9IHtcbiAgICAgICAgY29pblNwZWNpZmljOiAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJvb3RBZGRyZXNzOlxuICAgICAgICAgICAgICAnYWRkcl90ZXN0MXFxbm52cHRyYzNyZWM2NHEybjlqaDU3Mm5jdTV3dmR0dDh1dmc0ZzNhajk2czVkd3U5bmo3MG1sYWh6Z2xtOTkzOXVldnVwc21qOGRjZHF2MjVkNW41cjh2dzhzbjdwcmV5JyxcbiAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgYmFzZWNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICAgICAgdHhQcmVidWlsZDogY29uc29saWRhdGlvblR4LFxuICAgICAgICAgIHdhbGxldDogbW9ja2VkV2FsbGV0LFxuICAgICAgICAgIHZlcmlmaWNhdGlvbjoge1xuICAgICAgICAgICAgY29uc29saWRhdGlvblRvQmFzZUFkZHJlc3M6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCBhZGRyZXNzJyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=