@bitgo-beta/sdk-coin-trx 1.0.2-beta.222 → 1.0.2-beta.2221

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 (142) hide show
  1. package/dist/resources/protobuf/Contract.proto +32 -0
  2. package/dist/resources/protobuf/tron.d.ts +1478 -214
  3. package/dist/resources/protobuf/tron.js +6312 -2600
  4. package/dist/resources/protobuf/tron.proto +6 -0
  5. package/dist/src/index.js +6 -2
  6. package/dist/src/lib/accountCreateTxBuilder.d.ts +60 -0
  7. package/dist/src/lib/accountCreateTxBuilder.d.ts.map +1 -0
  8. package/dist/src/lib/accountCreateTxBuilder.js +191 -0
  9. package/dist/src/lib/constants.d.ts +4 -0
  10. package/dist/src/lib/constants.d.ts.map +1 -0
  11. package/dist/src/lib/constants.js +7 -0
  12. package/dist/src/lib/contractCallBuilder.d.ts +1 -35
  13. package/dist/src/lib/contractCallBuilder.d.ts.map +1 -1
  14. package/dist/src/lib/contractCallBuilder.js +13 -76
  15. package/dist/src/lib/delegateResourceTxBuilder.d.ts +27 -0
  16. package/dist/src/lib/delegateResourceTxBuilder.d.ts.map +1 -0
  17. package/dist/src/lib/delegateResourceTxBuilder.js +104 -0
  18. package/dist/src/lib/enum.d.ts +40 -1
  19. package/dist/src/lib/enum.d.ts.map +1 -1
  20. package/dist/src/lib/enum.js +44 -4
  21. package/dist/src/lib/freezeBalanceTxBuilder.d.ts +71 -0
  22. package/dist/src/lib/freezeBalanceTxBuilder.d.ts.map +1 -0
  23. package/dist/src/lib/freezeBalanceTxBuilder.js +217 -0
  24. package/dist/src/lib/iface.d.ts +248 -2
  25. package/dist/src/lib/iface.d.ts.map +1 -1
  26. package/dist/src/lib/iface.js +1 -1
  27. package/dist/src/lib/index.js +23 -9
  28. package/dist/src/lib/keyPair.d.ts +0 -1
  29. package/dist/src/lib/keyPair.d.ts.map +1 -1
  30. package/dist/src/lib/keyPair.js +31 -18
  31. package/dist/src/lib/resourceManagementTxBuilder.d.ts +72 -0
  32. package/dist/src/lib/resourceManagementTxBuilder.d.ts.map +1 -0
  33. package/dist/src/lib/resourceManagementTxBuilder.js +150 -0
  34. package/dist/src/lib/tokenTransferBuilder.d.ts +1 -1
  35. package/dist/src/lib/tokenTransferBuilder.js +3 -3
  36. package/dist/src/lib/transaction.d.ts +3 -0
  37. package/dist/src/lib/transaction.d.ts.map +1 -1
  38. package/dist/src/lib/transaction.js +115 -6
  39. package/dist/src/lib/transactionBuilder.d.ts +53 -6
  40. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  41. package/dist/src/lib/transactionBuilder.js +114 -21
  42. package/dist/src/lib/undelegateResourceTxBuilder.d.ts +27 -0
  43. package/dist/src/lib/undelegateResourceTxBuilder.d.ts.map +1 -0
  44. package/dist/src/lib/undelegateResourceTxBuilder.js +104 -0
  45. package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts +65 -0
  46. package/dist/src/lib/unfreezeBalanceTxBuilder.d.ts.map +1 -0
  47. package/dist/src/lib/unfreezeBalanceTxBuilder.js +210 -0
  48. package/dist/src/lib/utils.d.ts +92 -4
  49. package/dist/src/lib/utils.d.ts.map +1 -1
  50. package/dist/src/lib/utils.js +482 -47
  51. package/dist/src/lib/voteWitnessTxBuilder.d.ts +62 -0
  52. package/dist/src/lib/voteWitnessTxBuilder.d.ts.map +1 -0
  53. package/dist/src/lib/voteWitnessTxBuilder.js +219 -0
  54. package/dist/src/lib/withdrawBuilder.d.ts +49 -0
  55. package/dist/src/lib/withdrawBuilder.d.ts.map +1 -0
  56. package/dist/src/lib/withdrawBuilder.js +167 -0
  57. package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts +49 -0
  58. package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.d.ts.map +1 -0
  59. package/dist/src/lib/withdrawExpireUnfreezeTxBuilder.js +167 -0
  60. package/dist/src/lib/wrappedBuilder.d.ts +67 -1
  61. package/dist/src/lib/wrappedBuilder.d.ts.map +1 -1
  62. package/dist/src/lib/wrappedBuilder.js +114 -4
  63. package/dist/src/trx.d.ts +119 -4
  64. package/dist/src/trx.d.ts.map +1 -1
  65. package/dist/src/trx.js +600 -147
  66. package/dist/src/trxToken.d.ts +2 -2
  67. package/dist/src/trxToken.d.ts.map +1 -1
  68. package/dist/src/trxToken.js +53 -6
  69. package/dist/test/fixtures.d.ts +40 -0
  70. package/dist/test/fixtures.d.ts.map +1 -0
  71. package/dist/test/fixtures.js +46 -0
  72. package/dist/test/resources.d.ts +614 -0
  73. package/dist/test/resources.d.ts.map +1 -0
  74. package/dist/test/resources.js +782 -0
  75. package/dist/test/unit/index.d.ts +2 -0
  76. package/dist/test/unit/index.d.ts.map +1 -0
  77. package/dist/test/unit/index.js +19 -0
  78. package/dist/test/unit/keyPair.d.ts +2 -0
  79. package/dist/test/unit/keyPair.d.ts.map +1 -0
  80. package/dist/test/unit/keyPair.js +163 -0
  81. package/dist/test/unit/transaction.d.ts +2 -0
  82. package/dist/test/unit/transaction.d.ts.map +1 -0
  83. package/dist/test/unit/transaction.js +38 -0
  84. package/dist/test/unit/transactionBuilder/accountCreateTxBuilder.d.ts +2 -0
  85. package/dist/test/unit/transactionBuilder/accountCreateTxBuilder.d.ts.map +1 -0
  86. package/dist/test/unit/transactionBuilder/accountCreateTxBuilder.js +247 -0
  87. package/dist/test/unit/transactionBuilder/contractCallBuilder.d.ts +2 -0
  88. package/dist/test/unit/transactionBuilder/contractCallBuilder.d.ts.map +1 -0
  89. package/dist/test/unit/transactionBuilder/contractCallBuilder.js +315 -0
  90. package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.d.ts +2 -0
  91. package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.d.ts.map +1 -0
  92. package/dist/test/unit/transactionBuilder/delegateResourceTxBuilder.js +339 -0
  93. package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.d.ts +2 -0
  94. package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.d.ts.map +1 -0
  95. package/dist/test/unit/transactionBuilder/freezeBalanceTxBuilder.js +365 -0
  96. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
  97. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
  98. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +55 -0
  99. package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.d.ts +2 -0
  100. package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.d.ts.map +1 -0
  101. package/dist/test/unit/transactionBuilder/undelegateResourceTxBuilder.js +339 -0
  102. package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.d.ts +2 -0
  103. package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.d.ts.map +1 -0
  104. package/dist/test/unit/transactionBuilder/unfreezeBalanceTxBuilder.js +336 -0
  105. package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.d.ts +2 -0
  106. package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.d.ts.map +1 -0
  107. package/dist/test/unit/transactionBuilder/voteWitnessTxBuilder.js +277 -0
  108. package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.d.ts +2 -0
  109. package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.d.ts.map +1 -0
  110. package/dist/test/unit/transactionBuilder/withdrawBalanceBuilder.js +213 -0
  111. package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.d.ts +2 -0
  112. package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.d.ts.map +1 -0
  113. package/dist/test/unit/transactionBuilder/withdrawExpireUnfreezeTxBuilder.js +213 -0
  114. package/dist/test/unit/transactionBuilder/wrappedBuilder.d.ts +2 -0
  115. package/dist/test/unit/transactionBuilder/wrappedBuilder.d.ts.map +1 -0
  116. package/dist/test/unit/transactionBuilder/wrappedBuilder.js +50 -0
  117. package/dist/test/unit/transactionBuilder.d.ts +2 -0
  118. package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
  119. package/dist/test/unit/transactionBuilder.js +178 -0
  120. package/dist/test/unit/trx.d.ts +2 -0
  121. package/dist/test/unit/trx.d.ts.map +1 -0
  122. package/dist/test/unit/trx.js +796 -0
  123. package/dist/test/unit/trxToken.d.ts +2 -0
  124. package/dist/test/unit/trxToken.d.ts.map +1 -0
  125. package/dist/test/unit/trxToken.js +120 -0
  126. package/dist/test/unit/util.d.ts +2 -0
  127. package/dist/test/unit/util.d.ts.map +1 -0
  128. package/dist/test/unit/util.js +141 -0
  129. package/dist/test/unit/verifyTransaction.d.ts +2 -0
  130. package/dist/test/unit/verifyTransaction.d.ts.map +1 -0
  131. package/dist/test/unit/verifyTransaction.js +593 -0
  132. package/dist/tsconfig.tsbuildinfo +1 -0
  133. package/package.json +22 -16
  134. package/.eslintignore +0 -5
  135. package/.mocharc.yml +0 -8
  136. package/CHANGELOG.md +0 -118
  137. package/resources/README.md +0 -31
  138. package/resources/protobuf/Contract.proto +0 -256
  139. package/resources/protobuf/Discover.proto +0 -44
  140. package/resources/protobuf/tron.d.ts +0 -11205
  141. package/resources/protobuf/tron.js +0 -33480
  142. package/resources/protobuf/tron.proto +0 -677
@@ -0,0 +1,593 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_assert_1 = __importDefault(require("node:assert"));
7
+ const crypto_1 = require("crypto");
8
+ const node_test_1 = require("node:test");
9
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
10
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
11
+ const src_1 = require("../../src");
12
+ const lib_1 = require("../../src/lib");
13
+ const resources_1 = require("../resources");
14
+ (0, node_test_1.describe)('TRON Verify Transaction:', function () {
15
+ const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
16
+ bitgo.initializeTestVars();
17
+ bitgo.safeRegister('trx', src_1.Trx.createInstance);
18
+ bitgo.safeRegister('ttrx', src_1.Ttrx.createInstance);
19
+ let basecoin;
20
+ (0, node_test_1.before)(function () {
21
+ basecoin = bitgo.coin('ttrx');
22
+ });
23
+ (0, node_test_1.describe)('Parameter Validation', () => {
24
+ (0, node_test_1.it)('should throw error when txParams is missing', async function () {
25
+ const params = {
26
+ txPrebuild: {
27
+ txHex: JSON.stringify({
28
+ ...resources_1.UnsignedBuildTransaction,
29
+ raw_data: {
30
+ ...resources_1.UnsignedBuildTransaction.raw_data,
31
+ expiration: Date.now() + 3600000,
32
+ timestamp: Date.now(),
33
+ },
34
+ }),
35
+ },
36
+ wallet: {},
37
+ };
38
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
39
+ message: 'missing txParams',
40
+ });
41
+ });
42
+ (0, node_test_1.it)('should throw error when wallet or txPrebuild is missing', async function () {
43
+ const params = {
44
+ txParams: {
45
+ recipients: [{ address: 'TQFxDSoXy2yXRE5HtKwAwrNRXGxYxkeSGk', amount: '1000000' }],
46
+ },
47
+ };
48
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
49
+ message: 'missing txPrebuild',
50
+ });
51
+ });
52
+ (0, node_test_1.it)('should throw error when txPrebuild.txHex is missing', async function () {
53
+ const params = {
54
+ txParams: {
55
+ recipients: [{ address: 'TQFxDSoXy2yXRE5HtKwAwrNRXGxYxkeSGk', amount: '1000000' }],
56
+ },
57
+ txPrebuild: {},
58
+ wallet: {},
59
+ };
60
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
61
+ message: 'missing txHex in txPrebuild',
62
+ });
63
+ });
64
+ });
65
+ (0, node_test_1.describe)('Contract Type Validation', () => {
66
+ (0, node_test_1.describe)('TransferContract', () => {
67
+ (0, node_test_1.it)('should validate valid TransferContract', async function () {
68
+ const timestamp = Date.now();
69
+ const transferContract = {
70
+ parameter: {
71
+ value: {
72
+ amount: 1000000,
73
+ owner_address: '4173a5993cd182ae152adad8203163f780c65a8aa5',
74
+ to_address: '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882',
75
+ },
76
+ type_url: 'type.googleapis.com/protocol.TransferContract',
77
+ },
78
+ type: 'TransferContract',
79
+ };
80
+ const rawData = {
81
+ contract: [transferContract],
82
+ ref_block_bytes: 'c8cf',
83
+ ref_block_hash: '89177fd84c5d9196',
84
+ expiration: timestamp + 3600000,
85
+ timestamp: timestamp,
86
+ fee_limit: 150000000,
87
+ };
88
+ // Transform rawData to match the expected parameter structure
89
+ const transformedRawData = {
90
+ contract: rawData.contract,
91
+ refBlockBytes: rawData.ref_block_bytes,
92
+ refBlockHash: rawData.ref_block_hash,
93
+ expiration: rawData.expiration,
94
+ timestamp: rawData.timestamp,
95
+ feeLimit: rawData.fee_limit,
96
+ };
97
+ // Generate raw_data_hex using the utility function
98
+ const rawDataHex = lib_1.Utils.generateRawDataHex(transformedRawData);
99
+ // Calculate txID as SHA256 hash of raw_data_hex
100
+ const txID = (0, crypto_1.createHash)('sha256').update(Buffer.from(rawDataHex, 'hex')).digest('hex');
101
+ const params = {
102
+ txParams: {
103
+ recipients: [
104
+ {
105
+ address: lib_1.Utils.getBase58AddressFromHex('41d6cd6a2c0ff35a319e6abb5b9503ba0278679882'),
106
+ amount: '1000000',
107
+ },
108
+ ],
109
+ },
110
+ txPrebuild: {
111
+ txHex: JSON.stringify({
112
+ txID,
113
+ raw_data: rawData,
114
+ raw_data_hex: rawDataHex,
115
+ }),
116
+ },
117
+ wallet: {},
118
+ };
119
+ const result = await basecoin.verifyTransaction(params);
120
+ node_assert_1.default.strictEqual(result, true);
121
+ });
122
+ (0, node_test_1.it)('should fail with missing owner address', async function () {
123
+ const timestamp = Date.now();
124
+ const txID = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
125
+ const transferContract = {
126
+ parameter: {
127
+ value: {
128
+ amount: 1000000,
129
+ to_address: '41c25420255c2c5a2dd54ef69f92ef261e6bd4216a',
130
+ },
131
+ type_url: 'type.googleapis.com/protocol.TransferContract',
132
+ },
133
+ type: 'TransferContract',
134
+ };
135
+ const rawData = {
136
+ txID,
137
+ contract: [transferContract],
138
+ ref_block_bytes: 'c8cf',
139
+ ref_block_hash: '89177fd84c5d9196',
140
+ expiration: timestamp + 3600000,
141
+ timestamp: timestamp,
142
+ fee_limit: 150000000,
143
+ };
144
+ const transformedRawData = {
145
+ contract: rawData.contract,
146
+ refBlockBytes: rawData.ref_block_bytes,
147
+ refBlockHash: rawData.ref_block_hash,
148
+ expiration: rawData.expiration,
149
+ timestamp: rawData.timestamp,
150
+ feeLimit: rawData.fee_limit,
151
+ };
152
+ const expectedRawDataHex = lib_1.Utils.generateRawDataHex(transformedRawData);
153
+ const params = {
154
+ txParams: {
155
+ recipients: [{ address: 'TLWh67P93KgtnZNCtGnEHM1H33Nhq2uvvN', amount: '1000000' }],
156
+ },
157
+ txPrebuild: {
158
+ txHex: JSON.stringify({
159
+ txID,
160
+ raw_data: rawData,
161
+ raw_data_hex: expectedRawDataHex,
162
+ }),
163
+ },
164
+ wallet: {},
165
+ };
166
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
167
+ message: 'Transaction has not have a valid id',
168
+ });
169
+ });
170
+ (0, node_test_1.it)('should fail with missing destination address', async function () {
171
+ const timestamp = Date.now();
172
+ const txID = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
173
+ const transferContract = {
174
+ parameter: {
175
+ value: {
176
+ amount: 1000000,
177
+ owner_address: '4173a5993cd182ae152adad8203163f780c65a8aa5',
178
+ },
179
+ type_url: 'type.googleapis.com/protocol.TransferContract',
180
+ },
181
+ type: 'TransferContract',
182
+ };
183
+ const rawData = {
184
+ txID,
185
+ contract: [transferContract],
186
+ ref_block_bytes: 'c8cf',
187
+ ref_block_hash: '89177fd84c5d9196',
188
+ expiration: timestamp + 3600000,
189
+ timestamp: timestamp,
190
+ fee_limit: 150000000,
191
+ };
192
+ const transformedRawData = {
193
+ contract: rawData.contract,
194
+ refBlockBytes: rawData.ref_block_bytes,
195
+ refBlockHash: rawData.ref_block_hash,
196
+ expiration: rawData.expiration,
197
+ timestamp: rawData.timestamp,
198
+ feeLimit: rawData.fee_limit,
199
+ };
200
+ const expectedRawDataHex = lib_1.Utils.generateRawDataHex(transformedRawData);
201
+ const params = {
202
+ txParams: {
203
+ recipients: [{ address: 'TLWh67P93KgtnZNCtGnEHM1H33Nhq2uvvN', amount: '1000000' }],
204
+ },
205
+ txPrebuild: {
206
+ txHex: JSON.stringify({
207
+ txID,
208
+ raw_data: rawData,
209
+ raw_data_hex: expectedRawDataHex,
210
+ }),
211
+ },
212
+ wallet: {},
213
+ };
214
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
215
+ message: 'Transaction has not have a valid id',
216
+ });
217
+ });
218
+ (0, node_test_1.it)('should fail with missing amount', async function () {
219
+ const timestamp = Date.now();
220
+ const transferContract = {
221
+ parameter: {
222
+ value: {
223
+ owner_address: '4173a5993cd182ae152adad8203163f780c65a8aa5',
224
+ to_address: '41c25420255c2c5a2dd54ef69f92ef261e6bd4216a',
225
+ },
226
+ type_url: 'type.googleapis.com/protocol.TransferContract',
227
+ },
228
+ type: 'TransferContract',
229
+ };
230
+ const rawData = {
231
+ contract: [transferContract],
232
+ ref_block_bytes: 'c8cf',
233
+ ref_block_hash: '89177fd84c5d9196',
234
+ expiration: timestamp + 3600000,
235
+ timestamp: timestamp,
236
+ fee_limit: 150000000,
237
+ };
238
+ const transformedRawData = {
239
+ contract: rawData.contract,
240
+ refBlockBytes: rawData.ref_block_bytes,
241
+ refBlockHash: rawData.ref_block_hash,
242
+ expiration: rawData.expiration,
243
+ timestamp: rawData.timestamp,
244
+ feeLimit: rawData.fee_limit,
245
+ };
246
+ const expectedRawDataHex = lib_1.Utils.generateRawDataHex(transformedRawData);
247
+ const params = {
248
+ txParams: {
249
+ recipients: [{ address: 'TLWh67P93KgtnZNCtGnEHM1H33Nhq2uvvN', amount: '1000000' }],
250
+ },
251
+ txPrebuild: {
252
+ txHex: JSON.stringify({
253
+ raw_data: rawData,
254
+ raw_data_hex: expectedRawDataHex,
255
+ }),
256
+ },
257
+ wallet: {},
258
+ };
259
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
260
+ message: 'Amount does not exist in this transfer contract.',
261
+ });
262
+ });
263
+ (0, node_test_1.it)('should fail due to amount missmatch', async function () {
264
+ const timestamp = Date.now();
265
+ const transferContract = {
266
+ parameter: {
267
+ value: {
268
+ amount: 2000000,
269
+ owner_address: '4173a5993cd182ae152adad8203163f780c65a8aa5',
270
+ to_address: '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882',
271
+ },
272
+ type_url: 'type.googleapis.com/protocol.TransferContract',
273
+ },
274
+ type: 'TransferContract',
275
+ };
276
+ const rawData = {
277
+ contract: [transferContract],
278
+ ref_block_bytes: 'c8cf',
279
+ ref_block_hash: '89177fd84c5d9196',
280
+ expiration: timestamp + 3600000,
281
+ timestamp: timestamp,
282
+ fee_limit: 150000000,
283
+ };
284
+ // Transform rawData to match the expected parameter structure
285
+ const transformedRawData = {
286
+ contract: rawData.contract,
287
+ refBlockBytes: rawData.ref_block_bytes,
288
+ refBlockHash: rawData.ref_block_hash,
289
+ expiration: rawData.expiration,
290
+ timestamp: rawData.timestamp,
291
+ feeLimit: rawData.fee_limit,
292
+ };
293
+ // Generate raw_data_hex using the utility function
294
+ const rawDataHex = lib_1.Utils.generateRawDataHex(transformedRawData);
295
+ // Calculate txID as SHA256 hash of raw_data_hex
296
+ const txID = (0, crypto_1.createHash)('sha256').update(Buffer.from(rawDataHex, 'hex')).digest('hex');
297
+ const params = {
298
+ txParams: {
299
+ recipients: [
300
+ {
301
+ address: '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882',
302
+ amount: '1000000',
303
+ },
304
+ ],
305
+ },
306
+ txPrebuild: {
307
+ txHex: JSON.stringify({
308
+ txID,
309
+ raw_data: rawData,
310
+ raw_data_hex: rawDataHex,
311
+ }),
312
+ },
313
+ wallet: {},
314
+ };
315
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
316
+ message: 'transaction amount in txPrebuild does not match the value given by client',
317
+ });
318
+ });
319
+ (0, node_test_1.it)('should fail due to destination address missmatch', async function () {
320
+ const timestamp = Date.now();
321
+ const transferContract = {
322
+ parameter: {
323
+ value: {
324
+ amount: 1000000,
325
+ owner_address: '4173a5993cd182ae152adad8203163f780c65a8aa5',
326
+ to_address: '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882',
327
+ },
328
+ type_url: 'type.googleapis.com/protocol.TransferContract',
329
+ },
330
+ type: 'TransferContract',
331
+ };
332
+ const rawData = {
333
+ contract: [transferContract],
334
+ ref_block_bytes: 'c8cf',
335
+ ref_block_hash: '89177fd84c5d9196',
336
+ expiration: timestamp + 3600000,
337
+ timestamp: timestamp,
338
+ fee_limit: 150000000,
339
+ };
340
+ // Transform rawData to match the expected parameter structure
341
+ const transformedRawData = {
342
+ contract: rawData.contract,
343
+ refBlockBytes: rawData.ref_block_bytes,
344
+ refBlockHash: rawData.ref_block_hash,
345
+ expiration: rawData.expiration,
346
+ timestamp: rawData.timestamp,
347
+ feeLimit: rawData.fee_limit,
348
+ };
349
+ // Generate raw_data_hex using the utility function
350
+ const rawDataHex = lib_1.Utils.generateRawDataHex(transformedRawData);
351
+ // Calculate txID as SHA256 hash of raw_data_hex
352
+ const txID = (0, crypto_1.createHash)('sha256').update(Buffer.from(rawDataHex, 'hex')).digest('hex');
353
+ const params = {
354
+ txParams: {
355
+ recipients: [
356
+ {
357
+ address: '41d6cd6a2c0ff35a319e6abb5b9503ba0278679883',
358
+ amount: '1000000',
359
+ },
360
+ ],
361
+ },
362
+ txPrebuild: {
363
+ txHex: JSON.stringify({
364
+ txID,
365
+ raw_data: rawData,
366
+ raw_data_hex: rawDataHex,
367
+ }),
368
+ },
369
+ wallet: {},
370
+ };
371
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
372
+ message: 'destination address does not match with the recipient address',
373
+ });
374
+ });
375
+ });
376
+ });
377
+ (0, node_test_1.describe)('TSS Wallet Verification', () => {
378
+ /**
379
+ * Helper to build a raw_data_hex (protobuf) for a TransferContract.
380
+ * For TSS, txPrebuild.txHex is the raw_data_hex directly (not a JSON string).
381
+ */
382
+ function buildTssTransferTxHex(params) {
383
+ const timestamp = params.timestamp || Date.now();
384
+ const transferContract = {
385
+ parameter: {
386
+ value: {
387
+ amount: params.amount,
388
+ owner_address: params.ownerAddress,
389
+ to_address: params.toAddress,
390
+ },
391
+ type_url: 'type.googleapis.com/protocol.TransferContract',
392
+ },
393
+ type: 'TransferContract',
394
+ };
395
+ const transformedRawData = {
396
+ contract: [transferContract],
397
+ refBlockBytes: 'c8cf',
398
+ refBlockHash: '89177fd84c5d9196',
399
+ expiration: params.expiration || timestamp + 3600000,
400
+ timestamp: timestamp,
401
+ };
402
+ return lib_1.Utils.generateRawDataHex(transformedRawData);
403
+ }
404
+ (0, node_test_1.describe)('TransferContract', () => {
405
+ (0, node_test_1.it)('should validate a valid TSS TransferContract', async function () {
406
+ const ownerHex = '4173a5993cd182ae152adad8203163f780c65a8aa5';
407
+ const toHex = '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882';
408
+ const amount = 1000000;
409
+ const rawDataHex = buildTssTransferTxHex({ ownerAddress: ownerHex, toAddress: toHex, amount });
410
+ const params = {
411
+ txParams: {
412
+ recipients: [
413
+ {
414
+ // TSS path: recipients use base58 addresses
415
+ address: lib_1.Utils.getBase58AddressFromHex(toHex),
416
+ amount: amount.toString(),
417
+ },
418
+ ],
419
+ },
420
+ txPrebuild: {
421
+ // TSS path: txHex is the raw protobuf hex, not a JSON string
422
+ txHex: rawDataHex,
423
+ },
424
+ wallet: {},
425
+ walletType: 'tss',
426
+ };
427
+ const result = await basecoin.verifyTransaction(params);
428
+ node_assert_1.default.strictEqual(result, true);
429
+ });
430
+ (0, node_test_1.it)('should fail TSS verification when amount does not match', async function () {
431
+ const ownerHex = '4173a5993cd182ae152adad8203163f780c65a8aa5';
432
+ const toHex = '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882';
433
+ const rawDataHex = buildTssTransferTxHex({ ownerAddress: ownerHex, toAddress: toHex, amount: 2000000 });
434
+ const params = {
435
+ txParams: {
436
+ recipients: [
437
+ {
438
+ address: lib_1.Utils.getBase58AddressFromHex(toHex),
439
+ amount: '1000000', // mismatch: txHex has 2000000
440
+ },
441
+ ],
442
+ },
443
+ txPrebuild: {
444
+ txHex: rawDataHex,
445
+ },
446
+ wallet: {},
447
+ walletType: 'tss',
448
+ };
449
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
450
+ message: 'transaction amount in txPrebuild does not match the value given by client',
451
+ });
452
+ });
453
+ (0, node_test_1.it)('should fail TSS verification when destination address does not match', async function () {
454
+ const ownerHex = '4173a5993cd182ae152adad8203163f780c65a8aa5';
455
+ const toHex = '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882';
456
+ const rawDataHex = buildTssTransferTxHex({ ownerAddress: ownerHex, toAddress: toHex, amount: 1000000 });
457
+ const params = {
458
+ txParams: {
459
+ recipients: [
460
+ {
461
+ // Different address than what's in the transaction
462
+ address: 'TTsGwnTLQ4eryFJpDvJSfuGQxPXRCjXvZz',
463
+ amount: '1000000',
464
+ },
465
+ ],
466
+ },
467
+ txPrebuild: {
468
+ txHex: rawDataHex,
469
+ },
470
+ wallet: {},
471
+ walletType: 'tss',
472
+ };
473
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
474
+ message: 'destination address does not match with the recipient address',
475
+ });
476
+ });
477
+ });
478
+ (0, node_test_1.it)('should return true for non-Transfer, non-TriggerSmartContract types in TSS', async function () {
479
+ // AccountPermissionUpdate and other native TRX contracts (freeze, vote, etc.) pass through
480
+ // without recipient validation in the TSS path.
481
+ const rawDataHex = resources_1.UnsignedAccountPermissionUpdateContractTx.raw_data_hex;
482
+ const params = {
483
+ txParams: {
484
+ recipients: [],
485
+ },
486
+ txPrebuild: {
487
+ txHex: rawDataHex,
488
+ },
489
+ wallet: {},
490
+ walletType: 'tss',
491
+ };
492
+ const result = await basecoin.verifyTransaction(params);
493
+ node_assert_1.default.strictEqual(result, true);
494
+ });
495
+ (0, node_test_1.it)('should throw when TSS native TRX verifyTransaction encounters a TriggerSmartContract', async function () {
496
+ // Defense-in-depth: native TRX (Trx) should never verify TriggerSmartContract.
497
+ // TRC20 token transfers must go through TrxToken.verifyTransaction.
498
+ // The raw_data_hex below is a real TRC20 TriggerSmartContract protobuf.
499
+ const trc20RawDataHex = '0a02578b22086113bb9ac351432b4088eae7a6de305aae01081f12a9010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e747261637412740a1541c51fbeea78910b15b1d3e8a9b62914ca94d1a4ac12154142a1e39aefa49290f2b3f9ed688d7cecf86cd6e02244a9059cbb0000000000000000000000008483618ca85c35a9b923d98bebca718f5a1db2790000000000000000000000000000000000000000000000000000000005f5e10070888d8ca5de309001c0c39307';
500
+ const params = {
501
+ txParams: {
502
+ recipients: [{ address: 'TLWh67P93KgtnZNCtGnEHM1H33Nhq2uvvN', amount: '100000000' }],
503
+ },
504
+ txPrebuild: {
505
+ txHex: trc20RawDataHex,
506
+ },
507
+ wallet: {},
508
+ walletType: 'tss',
509
+ };
510
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
511
+ message: 'TriggerSmartContract verification is not supported by native TRX. ' +
512
+ 'TRC20 token transfers must be verified via TrxToken.verifyTransaction.',
513
+ });
514
+ });
515
+ (0, node_test_1.it)('should throw error when txHex is missing for TSS wallet', async function () {
516
+ const params = {
517
+ txParams: {
518
+ recipients: [{ address: 'TQFxDSoXy2yXRE5HtKwAwrNRXGxYxkeSGk', amount: '1000000' }],
519
+ },
520
+ txPrebuild: {},
521
+ wallet: {},
522
+ walletType: 'tss',
523
+ };
524
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
525
+ message: 'missing txHex in txPrebuild',
526
+ });
527
+ });
528
+ (0, node_test_1.describe)('serializedTxHex (JSON string) path', () => {
529
+ // prebuildAndSignTransaction passes txHex as serializedTxHex — a full JSON string
530
+ // containing { txID, raw_data, raw_data_hex }. The TSS branch must handle this format
531
+ // by extracting raw_data_hex before protobuf decoding.
532
+ (0, node_test_1.it)('should validate TSS TransferContract when txHex is a JSON string (serializedTxHex)', async function () {
533
+ const ownerHex = '4173a5993cd182ae152adad8203163f780c65a8aa5';
534
+ const toHex = '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882';
535
+ const amount = 1000000;
536
+ const rawDataHex = buildTssTransferTxHex({ ownerAddress: ownerHex, toAddress: toHex, amount });
537
+ const txID = (0, crypto_1.createHash)('sha256').update(Buffer.from(rawDataHex, 'hex')).digest('hex');
538
+ // Simulate the serializedTxHex format from BitGo API (JSON string with txID + raw_data_hex)
539
+ const serializedTxHex = JSON.stringify({
540
+ txID,
541
+ raw_data_hex: rawDataHex,
542
+ raw_data: {},
543
+ });
544
+ const params = {
545
+ txParams: {
546
+ recipients: [
547
+ {
548
+ address: lib_1.Utils.getBase58AddressFromHex(toHex),
549
+ amount: amount.toString(),
550
+ },
551
+ ],
552
+ },
553
+ txPrebuild: {
554
+ txHex: serializedTxHex,
555
+ },
556
+ wallet: {},
557
+ walletType: 'tss',
558
+ };
559
+ const result = await basecoin.verifyTransaction(params);
560
+ node_assert_1.default.strictEqual(result, true);
561
+ });
562
+ (0, node_test_1.it)('should fail when amount mismatches with JSON txHex', async function () {
563
+ const ownerHex = '4173a5993cd182ae152adad8203163f780c65a8aa5';
564
+ const toHex = '41d6cd6a2c0ff35a319e6abb5b9503ba0278679882';
565
+ const rawDataHex = buildTssTransferTxHex({ ownerAddress: ownerHex, toAddress: toHex, amount: 2000000 });
566
+ const serializedTxHex = JSON.stringify({
567
+ txID: (0, crypto_1.createHash)('sha256').update(Buffer.from(rawDataHex, 'hex')).digest('hex'),
568
+ raw_data_hex: rawDataHex,
569
+ raw_data: {},
570
+ });
571
+ const params = {
572
+ txParams: {
573
+ recipients: [
574
+ {
575
+ address: lib_1.Utils.getBase58AddressFromHex(toHex),
576
+ amount: '1000000', // mismatch
577
+ },
578
+ ],
579
+ },
580
+ txPrebuild: {
581
+ txHex: serializedTxHex,
582
+ },
583
+ wallet: {},
584
+ walletType: 'tss',
585
+ };
586
+ await node_assert_1.default.rejects(basecoin.verifyTransaction(params), {
587
+ message: 'transaction amount in txPrebuild does not match the value given by client',
588
+ });
589
+ });
590
+ });
591
+ });
592
+ });
593
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyaWZ5VHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L3VuaXQvdmVyaWZ5VHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4REFBaUM7QUFDakMsbUNBQW9DO0FBQ3BDLHlDQUFpRDtBQUNqRCxpREFBK0M7QUFDL0MsbURBQStEO0FBQy9ELG1DQUFzQztBQUN0Qyx1Q0FBc0M7QUFDdEMsNENBQW1HO0FBRW5HLElBQUEsb0JBQVEsRUFBQywwQkFBMEIsRUFBRTtJQUNuQyxNQUFNLEtBQUssR0FBaUIsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzNCLEtBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLFNBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM5QyxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxVQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7SUFFaEQsSUFBSSxRQUFRLENBQUM7SUFFYixJQUFBLGtCQUFNLEVBQUM7UUFDTCxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoQyxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsb0JBQVEsRUFBQyxzQkFBc0IsRUFBRSxHQUFHLEVBQUU7UUFDcEMsSUFBQSxjQUFFLEVBQUMsNkNBQTZDLEVBQUUsS0FBSztZQUNyRCxNQUFNLE1BQU0sR0FBRztnQkFDYixVQUFVLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUM7d0JBQ3BCLEdBQUcsb0NBQXdCO3dCQUMzQixRQUFRLEVBQUU7NEJBQ1IsR0FBRyxvQ0FBd0IsQ0FBQyxRQUFROzRCQUNwQyxVQUFVLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLE9BQU87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RSxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUN4RyxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO29CQUNyQyxJQUFJLEVBQUUsSUFBQSxtQkFBVSxFQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7b0JBQy9FLFlBQVksRUFBRSxVQUFVO29CQUN4QixRQUFRLEVBQUUsRUFBRTtpQkFDYixDQUFDLENBQUM7Z0JBRUgsTUFBTSxNQUFNLEdBQUc7b0JBQ2IsUUFBUSxFQUFFO3dCQUNSLFVBQVUsRUFBRTs0QkFDVjtnQ0FDRSxPQUFPLEVBQUUsV0FBSyxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQztnQ0FDN0MsTUFBTSxFQUFFLFNBQVMsRUFBRSxXQUFXOzZCQUMvQjt5QkFDRjtxQkFDRjtvQkFDRCxVQUFVLEVBQUU7d0JBQ1YsS0FBSyxFQUFFLGVBQWU7cUJBQ3ZCO29CQUNELE1BQU0sRUFBRSxFQUFFO29CQUNWLFVBQVUsRUFBRSxLQUFLO2lCQUNsQixDQUFDO2dCQUVGLE1BQU0scUJBQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUN2RCxPQUFPLEVBQUUsMkVBQTJFO2lCQUNyRixDQUFDLENBQUM7WUFDTCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnbm9kZTphc3NlcnQnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBkZXNjcmliZSwgaXQsIGJlZm9yZSB9IGZyb20gJ25vZGU6dGVzdCc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuaW1wb3J0IHsgVGVzdEJpdEdvQVBJLCBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28tYmV0YS9zZGstdGVzdCc7XG5pbXBvcnQgeyBUcngsIFR0cnggfSBmcm9tICcuLi8uLi9zcmMnO1xuaW1wb3J0IHsgVXRpbHMgfSBmcm9tICcuLi8uLi9zcmMvbGliJztcbmltcG9ydCB7IFVuc2lnbmVkQnVpbGRUcmFuc2FjdGlvbiwgVW5zaWduZWRBY2NvdW50UGVybWlzc2lvblVwZGF0ZUNvbnRyYWN0VHggfSBmcm9tICcuLi9yZXNvdXJjZXMnO1xuXG5kZXNjcmliZSgnVFJPTiBWZXJpZnkgVHJhbnNhY3Rpb246JywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBiaXRnbzogVGVzdEJpdEdvQVBJID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0cngnLCBUcnguY3JlYXRlSW5zdGFuY2UpO1xuICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3R0cngnLCBUdHJ4LmNyZWF0ZUluc3RhbmNlKTtcblxuICBsZXQgYmFzZWNvaW47XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiYXNlY29pbiA9IGJpdGdvLmNvaW4oJ3R0cngnKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1BhcmFtZXRlciBWYWxpZGF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eFBhcmFtcyBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIC4uLlVuc2lnbmVkQnVpbGRUcmFuc2FjdGlvbixcbiAgICAgICAgICAgIHJhd19kYXRhOiB7XG4gICAgICAgICAgICAgIC4uLlVuc2lnbmVkQnVpbGRUcmFuc2FjdGlvbi5yYXdfZGF0YSxcbiAgICAgICAgICAgICAgZXhwaXJhdGlvbjogRGF0ZS5ub3coKSArIDM2MDAwMDAsXG4gICAgICAgICAgICAgIHRpbWVzdGFtcDogRGF0ZS5ub3coKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIH0sXG4gICAgICAgIHdhbGxldDoge30sXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXMpLCB7XG4gICAgICAgIG1lc3NhZ2U6ICdtaXNzaW5nIHR4UGFyYW1zJyxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIHdhbGxldCBvciB0eFByZWJ1aWxkIGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJ1RRRnhEU29YeTJ5WFJFNUh0S3dBd3JOUlhHeFl4a2VTR2snLCBhbW91bnQ6ICcxMDAwMDAwJyB9XSxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtcyksIHtcbiAgICAgICAgbWVzc2FnZTogJ21pc3NpbmcgdHhQcmVidWlsZCcsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB0eFByZWJ1aWxkLnR4SGV4IGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJ1RRRnhEU29YeTJ5WFJFNUh0S3dBd3JOUlhHeFl4a2VTR2snLCBhbW91bnQ6ICcxMDAwMDAwJyB9XSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDoge30sXG4gICAgICAgIHdhbGxldDoge30sXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXMpLCB7XG4gICAgICAgIG1lc3NhZ2U6ICdtaXNzaW5nIHR4SGV4IGluIHR4UHJlYnVpbGQnLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdDb250cmFjdCBUeXBlIFZhbGlkYXRpb24nLCAoKSA9PiB7XG4gICAgZGVzY3JpYmUoJ1RyYW5zZmVyQ29udHJhY3QnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIHZhbGlkIFRyYW5zZmVyQ29udHJhY3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHRyYW5zZmVyQ29udHJhY3QgPSB7XG4gICAgICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgICBhbW91bnQ6IDEwMDAwMDAsXG4gICAgICAgICAgICAgIG93bmVyX2FkZHJlc3M6ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnLFxuICAgICAgICAgICAgICB0b19hZGRyZXNzOiAnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgyJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0eXBlX3VybDogJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eXBlOiAnVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmF3RGF0YSA9IHtcbiAgICAgICAgICBjb250cmFjdDogW3RyYW5zZmVyQ29udHJhY3RdLFxuICAgICAgICAgIHJlZl9ibG9ja19ieXRlczogJ2M4Y2YnLFxuICAgICAgICAgIHJlZl9ibG9ja19oYXNoOiAnODkxNzdmZDg0YzVkOTE5NicsXG4gICAgICAgICAgZXhwaXJhdGlvbjogdGltZXN0YW1wICsgMzYwMDAwMCxcbiAgICAgICAgICB0aW1lc3RhbXA6IHRpbWVzdGFtcCxcbiAgICAgICAgICBmZWVfbGltaXQ6IDE1MDAwMDAwMCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBUcmFuc2Zvcm0gcmF3RGF0YSB0byBtYXRjaCB0aGUgZXhwZWN0ZWQgcGFyYW1ldGVyIHN0cnVjdHVyZVxuICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZFJhd0RhdGEgPSB7XG4gICAgICAgICAgY29udHJhY3Q6IHJhd0RhdGEuY29udHJhY3QgYXMgYW55LFxuICAgICAgICAgIHJlZkJsb2NrQnl0ZXM6IHJhd0RhdGEucmVmX2Jsb2NrX2J5dGVzLFxuICAgICAgICAgIHJlZkJsb2NrSGFzaDogcmF3RGF0YS5yZWZfYmxvY2tfaGFzaCxcbiAgICAgICAgICBleHBpcmF0aW9uOiByYXdEYXRhLmV4cGlyYXRpb24sXG4gICAgICAgICAgdGltZXN0YW1wOiByYXdEYXRhLnRpbWVzdGFtcCxcbiAgICAgICAgICBmZWVMaW1pdDogcmF3RGF0YS5mZWVfbGltaXQsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgcmF3X2RhdGFfaGV4IHVzaW5nIHRoZSB1dGlsaXR5IGZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBVdGlscy5nZW5lcmF0ZVJhd0RhdGFIZXgodHJhbnNmb3JtZWRSYXdEYXRhKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdHhJRCBhcyBTSEEyNTYgaGFzaCBvZiByYXdfZGF0YV9oZXhcbiAgICAgICAgY29uc3QgdHhJRCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShCdWZmZXIuZnJvbShyYXdEYXRhSGV4LCAnaGV4JykpLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiBVdGlscy5nZXRCYXNlNThBZGRyZXNzRnJvbUhleCgnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgyJyksXG4gICAgICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgdHhJRCxcbiAgICAgICAgICAgICAgcmF3X2RhdGE6IHJhd0RhdGEsXG4gICAgICAgICAgICAgIHJhd19kYXRhX2hleDogcmF3RGF0YUhleCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgd2FsbGV0OiB7fSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXMpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGZhaWwgd2l0aCBtaXNzaW5nIG93bmVyIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHR4SUQgPSAnMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZic7XG4gICAgICAgIGNvbnN0IHRyYW5zZmVyQ29udHJhY3QgPSB7XG4gICAgICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgICBhbW91bnQ6IDEwMDAwMDAsXG4gICAgICAgICAgICAgIHRvX2FkZHJlc3M6ICc0MWMyNTQyMDI1NWMyYzVhMmRkNTRlZjY5ZjkyZWYyNjFlNmJkNDIxNmEnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHR5cGVfdXJsOiAndHlwZS5nb29nbGVhcGlzLmNvbS9wcm90b2NvbC5UcmFuc2ZlckNvbnRyYWN0JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR5cGU6ICdUcmFuc2ZlckNvbnRyYWN0JyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByYXdEYXRhID0ge1xuICAgICAgICAgIHR4SUQsXG4gICAgICAgICAgY29udHJhY3Q6IFt0cmFuc2ZlckNvbnRyYWN0XSxcbiAgICAgICAgICByZWZfYmxvY2tfYnl0ZXM6ICdjOGNmJyxcbiAgICAgICAgICByZWZfYmxvY2tfaGFzaDogJzg5MTc3ZmQ4NGM1ZDkxOTYnLFxuICAgICAgICAgIGV4cGlyYXRpb246IHRpbWVzdGFtcCArIDM2MDAwMDAsXG4gICAgICAgICAgdGltZXN0YW1wOiB0aW1lc3RhbXAsXG4gICAgICAgICAgZmVlX2xpbWl0OiAxNTAwMDAwMDAsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZWRSYXdEYXRhID0ge1xuICAgICAgICAgIGNvbnRyYWN0OiByYXdEYXRhLmNvbnRyYWN0IGFzIGFueSxcbiAgICAgICAgICByZWZCbG9ja0J5dGVzOiByYXdEYXRhLnJlZl9ibG9ja19ieXRlcyxcbiAgICAgICAgICByZWZCbG9ja0hhc2g6IHJhd0RhdGEucmVmX2Jsb2NrX2hhc2gsXG4gICAgICAgICAgZXhwaXJhdGlvbjogcmF3RGF0YS5leHBpcmF0aW9uLFxuICAgICAgICAgIHRpbWVzdGFtcDogcmF3RGF0YS50aW1lc3RhbXAsXG4gICAgICAgICAgZmVlTGltaXQ6IHJhd0RhdGEuZmVlX2xpbWl0LFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGV4cGVjdGVkUmF3RGF0YUhleCA9IFV0aWxzLmdlbmVyYXRlUmF3RGF0YUhleCh0cmFuc2Zvcm1lZFJhd0RhdGEpO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJ1RMV2g2N1A5M0tndG5aTkN0R25FSE0xSDMzTmhxMnV2dk4nLCBhbW91bnQ6ICcxMDAwMDAwJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIHR4SUQsXG4gICAgICAgICAgICAgIHJhd19kYXRhOiByYXdEYXRhLFxuICAgICAgICAgICAgICByYXdfZGF0YV9oZXg6IGV4cGVjdGVkUmF3RGF0YUhleCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgd2FsbGV0OiB7fSxcbiAgICAgICAgfTtcblxuICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXMpLCB7XG4gICAgICAgICAgbWVzc2FnZTogJ1RyYW5zYWN0aW9uIGhhcyBub3QgaGF2ZSBhIHZhbGlkIGlkJyxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBmYWlsIHdpdGggbWlzc2luZyBkZXN0aW5hdGlvbiBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCB0eElEID0gJzAxMjM0NTY3ODlhYmNkZWYwMTIzNDU2Nzg5YWJjZGVmMDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWYnO1xuICAgICAgICBjb25zdCB0cmFuc2ZlckNvbnRyYWN0ID0ge1xuICAgICAgICAgIHBhcmFtZXRlcjoge1xuICAgICAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgICAgYW1vdW50OiAxMDAwMDAwLFxuICAgICAgICAgICAgICBvd25lcl9hZGRyZXNzOiAnNDE3M2E1OTkzY2QxODJhZTE1MmFkYWQ4MjAzMTYzZjc4MGM2NWE4YWE1JyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0eXBlX3VybDogJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eXBlOiAnVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmF3RGF0YSA9IHtcbiAgICAgICAgICB0eElELFxuICAgICAgICAgIGNvbnRyYWN0OiBbdHJhbnNmZXJDb250cmFjdF0sXG4gICAgICAgICAgcmVmX2Jsb2NrX2J5dGVzOiAnYzhjZicsXG4gICAgICAgICAgcmVmX2Jsb2NrX2hhc2g6ICc4OTE3N2ZkODRjNWQ5MTk2JyxcbiAgICAgICAgICBleHBpcmF0aW9uOiB0aW1lc3RhbXAgKyAzNjAwMDAwLFxuICAgICAgICAgIHRpbWVzdGFtcDogdGltZXN0YW1wLFxuICAgICAgICAgIGZlZV9saW1pdDogMTUwMDAwMDAwLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkUmF3RGF0YSA9IHtcbiAgICAgICAgICBjb250cmFjdDogcmF3RGF0YS5jb250cmFjdCBhcyBhbnksXG4gICAgICAgICAgcmVmQmxvY2tCeXRlczogcmF3RGF0YS5yZWZfYmxvY2tfYnl0ZXMsXG4gICAgICAgICAgcmVmQmxvY2tIYXNoOiByYXdEYXRhLnJlZl9ibG9ja19oYXNoLFxuICAgICAgICAgIGV4cGlyYXRpb246IHJhd0RhdGEuZXhwaXJhdGlvbixcbiAgICAgICAgICB0aW1lc3RhbXA6IHJhd0RhdGEudGltZXN0YW1wLFxuICAgICAgICAgIGZlZUxpbWl0OiByYXdEYXRhLmZlZV9saW1pdCxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBleHBlY3RlZFJhd0RhdGFIZXggPSBVdGlscy5nZW5lcmF0ZVJhd0RhdGFIZXgodHJhbnNmb3JtZWRSYXdEYXRhKTtcblxuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6ICdUTFdoNjdQOTNLZ3RuWk5DdEduRUhNMUgzM05ocTJ1dnZOJywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICB0eElELFxuICAgICAgICAgICAgICByYXdfZGF0YTogcmF3RGF0YSxcbiAgICAgICAgICAgICAgcmF3X2RhdGFfaGV4OiBleHBlY3RlZFJhd0RhdGFIZXgsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdhbGxldDoge30sXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zKSwge1xuICAgICAgICAgIG1lc3NhZ2U6ICdUcmFuc2FjdGlvbiBoYXMgbm90IGhhdmUgYSB2YWxpZCBpZCcsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZmFpbCB3aXRoIG1pc3NpbmcgYW1vdW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCB0cmFuc2ZlckNvbnRyYWN0ID0ge1xuICAgICAgICAgIHBhcmFtZXRlcjoge1xuICAgICAgICAgICAgdmFsdWU6IHtcbiAgICAgICAgICAgICAgb3duZXJfYWRkcmVzczogJzQxNzNhNTk5M2NkMTgyYWUxNTJhZGFkODIwMzE2M2Y3ODBjNjVhOGFhNScsXG4gICAgICAgICAgICAgIHRvX2FkZHJlc3M6ICc0MWMyNTQyMDI1NWMyYzVhMmRkNTRlZjY5ZjkyZWYyNjFlNmJkNDIxNmEnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHR5cGVfdXJsOiAndHlwZS5nb29nbGVhcGlzLmNvbS9wcm90b2NvbC5UcmFuc2ZlckNvbnRyYWN0JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR5cGU6ICdUcmFuc2ZlckNvbnRyYWN0JyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByYXdEYXRhID0ge1xuICAgICAgICAgIGNvbnRyYWN0OiBbdHJhbnNmZXJDb250cmFjdF0sXG4gICAgICAgICAgcmVmX2Jsb2NrX2J5dGVzOiAnYzhjZicsXG4gICAgICAgICAgcmVmX2Jsb2NrX2hhc2g6ICc4OTE3N2ZkODRjNWQ5MTk2JyxcbiAgICAgICAgICBleHBpcmF0aW9uOiB0aW1lc3RhbXAgKyAzNjAwMDAwLFxuICAgICAgICAgIHRpbWVzdGFtcDogdGltZXN0YW1wLFxuICAgICAgICAgIGZlZV9saW1pdDogMTUwMDAwMDAwLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkUmF3RGF0YSA9IHtcbiAgICAgICAgICBjb250cmFjdDogcmF3RGF0YS5jb250cmFjdCBhcyBhbnksXG4gICAgICAgICAgcmVmQmxvY2tCeXRlczogcmF3RGF0YS5yZWZfYmxvY2tfYnl0ZXMsXG4gICAgICAgICAgcmVmQmxvY2tIYXNoOiByYXdEYXRhLnJlZl9ibG9ja19oYXNoLFxuICAgICAgICAgIGV4cGlyYXRpb246IHJhd0RhdGEuZXhwaXJhdGlvbixcbiAgICAgICAgICB0aW1lc3RhbXA6IHJhd0RhdGEudGltZXN0YW1wLFxuICAgICAgICAgIGZlZUxpbWl0OiByYXdEYXRhLmZlZV9saW1pdCxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBleHBlY3RlZFJhd0RhdGFIZXggPSBVdGlscy5nZW5lcmF0ZVJhd0RhdGFIZXgodHJhbnNmb3JtZWRSYXdEYXRhKTtcblxuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6ICdUTFdoNjdQOTNLZ3RuWk5DdEduRUhNMUgzM05ocTJ1dnZOJywgYW1vdW50OiAnMTAwMDAwMCcgfV0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICByYXdfZGF0YTogcmF3RGF0YSxcbiAgICAgICAgICAgICAgcmF3X2RhdGFfaGV4OiBleHBlY3RlZFJhd0RhdGFIZXgsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdhbGxldDoge30sXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zKSwge1xuICAgICAgICAgIG1lc3NhZ2U6ICdBbW91bnQgZG9lcyBub3QgZXhpc3QgaW4gdGhpcyB0cmFuc2ZlciBjb250cmFjdC4nLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGZhaWwgZHVlIHRvIGFtb3VudCBtaXNzbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHRyYW5zZmVyQ29udHJhY3QgPSB7XG4gICAgICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgICBhbW91bnQ6IDIwMDAwMDAsXG4gICAgICAgICAgICAgIG93bmVyX2FkZHJlc3M6ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnLFxuICAgICAgICAgICAgICB0b19hZGRyZXNzOiAnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgyJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0eXBlX3VybDogJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eXBlOiAnVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmF3RGF0YSA9IHtcbiAgICAgICAgICBjb250cmFjdDogW3RyYW5zZmVyQ29udHJhY3RdLFxuICAgICAgICAgIHJlZl9ibG9ja19ieXRlczogJ2M4Y2YnLFxuICAgICAgICAgIHJlZl9ibG9ja19oYXNoOiAnODkxNzdmZDg0YzVkOTE5NicsXG4gICAgICAgICAgZXhwaXJhdGlvbjogdGltZXN0YW1wICsgMzYwMDAwMCxcbiAgICAgICAgICB0aW1lc3RhbXA6IHRpbWVzdGFtcCxcbiAgICAgICAgICBmZWVfbGltaXQ6IDE1MDAwMDAwMCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBUcmFuc2Zvcm0gcmF3RGF0YSB0byBtYXRjaCB0aGUgZXhwZWN0ZWQgcGFyYW1ldGVyIHN0cnVjdHVyZVxuICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZFJhd0RhdGEgPSB7XG4gICAgICAgICAgY29udHJhY3Q6IHJhd0RhdGEuY29udHJhY3QgYXMgYW55LFxuICAgICAgICAgIHJlZkJsb2NrQnl0ZXM6IHJhd0RhdGEucmVmX2Jsb2NrX2J5dGVzLFxuICAgICAgICAgIHJlZkJsb2NrSGFzaDogcmF3RGF0YS5yZWZfYmxvY2tfaGFzaCxcbiAgICAgICAgICBleHBpcmF0aW9uOiByYXdEYXRhLmV4cGlyYXRpb24sXG4gICAgICAgICAgdGltZXN0YW1wOiByYXdEYXRhLnRpbWVzdGFtcCxcbiAgICAgICAgICBmZWVMaW1pdDogcmF3RGF0YS5mZWVfbGltaXQsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgcmF3X2RhdGFfaGV4IHVzaW5nIHRoZSB1dGlsaXR5IGZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBVdGlscy5nZW5lcmF0ZVJhd0RhdGFIZXgodHJhbnNmb3JtZWRSYXdEYXRhKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdHhJRCBhcyBTSEEyNTYgaGFzaCBvZiByYXdfZGF0YV9oZXhcbiAgICAgICAgY29uc3QgdHhJRCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShCdWZmZXIuZnJvbShyYXdEYXRhSGV4LCAnaGV4JykpLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiAnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgyJyxcbiAgICAgICAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICB0eElELFxuICAgICAgICAgICAgICByYXdfZGF0YTogcmF3RGF0YSxcbiAgICAgICAgICAgICAgcmF3X2RhdGFfaGV4OiByYXdEYXRhSGV4LFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3YWxsZXQ6IHt9LFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtcyksIHtcbiAgICAgICAgICBtZXNzYWdlOiAndHJhbnNhY3Rpb24gYW1vdW50IGluIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggdGhlIHZhbHVlIGdpdmVuIGJ5IGNsaWVudCcsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZmFpbCBkdWUgdG8gZGVzdGluYXRpb24gYWRkcmVzcyBtaXNzbWF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IERhdGUubm93KCk7XG4gICAgICAgIGNvbnN0IHRyYW5zZmVyQ29udHJhY3QgPSB7XG4gICAgICAgICAgcGFyYW1ldGVyOiB7XG4gICAgICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgICBhbW91bnQ6IDEwMDAwMDAsXG4gICAgICAgICAgICAgIG93bmVyX2FkZHJlc3M6ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnLFxuICAgICAgICAgICAgICB0b19hZGRyZXNzOiAnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgyJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0eXBlX3VybDogJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eXBlOiAnVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmF3RGF0YSA9IHtcbiAgICAgICAgICBjb250cmFjdDogW3RyYW5zZmVyQ29udHJhY3RdLFxuICAgICAgICAgIHJlZl9ibG9ja19ieXRlczogJ2M4Y2YnLFxuICAgICAgICAgIHJlZl9ibG9ja19oYXNoOiAnODkxNzdmZDg0YzVkOTE5NicsXG4gICAgICAgICAgZXhwaXJhdGlvbjogdGltZXN0YW1wICsgMzYwMDAwMCxcbiAgICAgICAgICB0aW1lc3RhbXA6IHRpbWVzdGFtcCxcbiAgICAgICAgICBmZWVfbGltaXQ6IDE1MDAwMDAwMCxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBUcmFuc2Zvcm0gcmF3RGF0YSB0byBtYXRjaCB0aGUgZXhwZWN0ZWQgcGFyYW1ldGVyIHN0cnVjdHVyZVxuICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZFJhd0RhdGEgPSB7XG4gICAgICAgICAgY29udHJhY3Q6IHJhd0RhdGEuY29udHJhY3QgYXMgYW55LFxuICAgICAgICAgIHJlZkJsb2NrQnl0ZXM6IHJhd0RhdGEucmVmX2Jsb2NrX2J5dGVzLFxuICAgICAgICAgIHJlZkJsb2NrSGFzaDogcmF3RGF0YS5yZWZfYmxvY2tfaGFzaCxcbiAgICAgICAgICBleHBpcmF0aW9uOiByYXdEYXRhLmV4cGlyYXRpb24sXG4gICAgICAgICAgdGltZXN0YW1wOiByYXdEYXRhLnRpbWVzdGFtcCxcbiAgICAgICAgICBmZWVMaW1pdDogcmF3RGF0YS5mZWVfbGltaXQsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgcmF3X2RhdGFfaGV4IHVzaW5nIHRoZSB1dGlsaXR5IGZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBVdGlscy5nZW5lcmF0ZVJhd0RhdGFIZXgodHJhbnNmb3JtZWRSYXdEYXRhKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdHhJRCBhcyBTSEEyNTYgaGFzaCBvZiByYXdfZGF0YV9oZXhcbiAgICAgICAgY29uc3QgdHhJRCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShCdWZmZXIuZnJvbShyYXdEYXRhSGV4LCAnaGV4JykpLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiAnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgzJyxcbiAgICAgICAgICAgICAgICBhbW91bnQ6ICcxMDAwMDAwJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICB0eElELFxuICAgICAgICAgICAgICByYXdfZGF0YTogcmF3RGF0YSxcbiAgICAgICAgICAgICAgcmF3X2RhdGFfaGV4OiByYXdEYXRhSGV4LFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3YWxsZXQ6IHt9LFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtcyksIHtcbiAgICAgICAgICBtZXNzYWdlOiAnZGVzdGluYXRpb24gYWRkcmVzcyBkb2VzIG5vdCBtYXRjaCB3aXRoIHRoZSByZWNpcGllbnQgYWRkcmVzcycsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUU1MgV2FsbGV0IFZlcmlmaWNhdGlvbicsICgpID0+IHtcbiAgICAvKipcbiAgICAgKiBIZWxwZXIgdG8gYnVpbGQgYSByYXdfZGF0YV9oZXggKHByb3RvYnVmKSBmb3IgYSBUcmFuc2ZlckNvbnRyYWN0LlxuICAgICAqIEZvciBUU1MsIHR4UHJlYnVpbGQudHhIZXggaXMgdGhlIHJhd19kYXRhX2hleCBkaXJlY3RseSAobm90IGEgSlNPTiBzdHJpbmcpLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJ1aWxkVHNzVHJhbnNmZXJUeEhleChwYXJhbXM6IHtcbiAgICAgIG93bmVyQWRkcmVzczogc3RyaW5nO1xuICAgICAgdG9BZGRyZXNzOiBzdHJpbmc7XG4gICAgICBhbW91bnQ6IG51bWJlcjtcbiAgICAgIHRpbWVzdGFtcD86IG51bWJlcjtcbiAgICAgIGV4cGlyYXRpb24/OiBudW1iZXI7XG4gICAgfSk6IHN0cmluZyB7XG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSBwYXJhbXMudGltZXN0YW1wIHx8IERhdGUubm93KCk7XG4gICAgICBjb25zdCB0cmFuc2ZlckNvbnRyYWN0ID0ge1xuICAgICAgICBwYXJhbWV0ZXI6IHtcbiAgICAgICAgICB2YWx1ZToge1xuICAgICAgICAgICAgYW1vdW50OiBwYXJhbXMuYW1vdW50LFxuICAgICAgICAgICAgb3duZXJfYWRkcmVzczogcGFyYW1zLm93bmVyQWRkcmVzcyxcbiAgICAgICAgICAgIHRvX2FkZHJlc3M6IHBhcmFtcy50b0FkZHJlc3MsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eXBlX3VybDogJ3R5cGUuZ29vZ2xlYXBpcy5jb20vcHJvdG9jb2wuVHJhbnNmZXJDb250cmFjdCcsXG4gICAgICAgIH0sXG4gICAgICAgIHR5cGU6ICdUcmFuc2ZlckNvbnRyYWN0JyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVkUmF3RGF0YSA9IHtcbiAgICAgICAgY29udHJhY3Q6IFt0cmFuc2ZlckNvbnRyYWN0XSBhcyBhbnksXG4gICAgICAgIHJlZkJsb2NrQnl0ZXM6ICdjOGNmJyxcbiAgICAgICAgcmVmQmxvY2tIYXNoOiAnODkxNzdmZDg0YzVkOTE5NicsXG4gICAgICAgIGV4cGlyYXRpb246IHBhcmFtcy5leHBpcmF0aW9uIHx8IHRpbWVzdGFtcCArIDM2MDAwMDAsXG4gICAgICAgIHRpbWVzdGFtcDogdGltZXN0YW1wLFxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIFV0aWxzLmdlbmVyYXRlUmF3RGF0YUhleCh0cmFuc2Zvcm1lZFJhd0RhdGEpO1xuICAgIH1cblxuICAgIGRlc2NyaWJlKCdUcmFuc2ZlckNvbnRyYWN0JywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhIHZhbGlkIFRTUyBUcmFuc2ZlckNvbnRyYWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBvd25lckhleCA9ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnO1xuICAgICAgICBjb25zdCB0b0hleCA9ICc0MWQ2Y2Q2YTJjMGZmMzVhMzE5ZTZhYmI1Yjk1MDNiYTAyNzg2Nzk4ODInO1xuICAgICAgICBjb25zdCBhbW91bnQgPSAxMDAwMDAwO1xuXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBidWlsZFRzc1RyYW5zZmVyVHhIZXgoeyBvd25lckFkZHJlc3M6IG93bmVySGV4LCB0b0FkZHJlc3M6IHRvSGV4LCBhbW91bnQgfSk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAvLyBUU1MgcGF0aDogcmVjaXBpZW50cyB1c2UgYmFzZTU4IGFkZHJlc3Nlc1xuICAgICAgICAgICAgICAgIGFkZHJlc3M6IFV0aWxzLmdldEJhc2U1OEFkZHJlc3NGcm9tSGV4KHRvSGV4KSxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIC8vIFRTUyBwYXRoOiB0eEhleCBpcyB0aGUgcmF3IHByb3RvYnVmIGhleCwgbm90IGEgSlNPTiBzdHJpbmdcbiAgICAgICAgICAgIHR4SGV4OiByYXdEYXRhSGV4LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgd2FsbGV0OiB7fSxcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXMpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGZhaWwgVFNTIHZlcmlmaWNhdGlvbiB3aGVuIGFtb3VudCBkb2VzIG5vdCBtYXRjaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgb3duZXJIZXggPSAnNDE3M2E1OTkzY2QxODJhZTE1MmFkYWQ4MjAzMTYzZjc4MGM2NWE4YWE1JztcbiAgICAgICAgY29uc3QgdG9IZXggPSAnNDFkNmNkNmEyYzBmZjM1YTMxOWU2YWJiNWI5NTAzYmEwMjc4Njc5ODgyJztcblxuICAgICAgICBjb25zdCByYXdEYXRhSGV4ID0gYnVpbGRUc3NUcmFuc2ZlclR4SGV4KHsgb3duZXJBZGRyZXNzOiBvd25lckhleCwgdG9BZGRyZXNzOiB0b0hleCwgYW1vdW50OiAyMDAwMDAwIH0pO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWRkcmVzczogVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodG9IZXgpLFxuICAgICAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAnLCAvLyBtaXNtYXRjaDogdHhIZXggaGFzIDIwMDAwMDBcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICB0eEhleDogcmF3RGF0YUhleCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdhbGxldDoge30sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zKSwge1xuICAgICAgICAgIG1lc3NhZ2U6ICd0cmFuc2FjdGlvbiBhbW91bnQgaW4gdHhQcmVidWlsZCBkb2VzIG5vdCBtYXRjaCB0aGUgdmFsdWUgZ2l2ZW4gYnkgY2xpZW50JyxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBmYWlsIFRTUyB2ZXJpZmljYXRpb24gd2hlbiBkZXN0aW5hdGlvbiBhZGRyZXNzIGRvZXMgbm90IG1hdGNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBvd25lckhleCA9ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnO1xuICAgICAgICBjb25zdCB0b0hleCA9ICc0MWQ2Y2Q2YTJjMGZmMzVhMzE5ZTZhYmI1Yjk1MDNiYTAyNzg2Nzk4ODInO1xuXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBidWlsZFRzc1RyYW5zZmVyVHhIZXgoeyBvd25lckFkZHJlc3M6IG93bmVySGV4LCB0b0FkZHJlc3M6IHRvSGV4LCBhbW91bnQ6IDEwMDAwMDAgfSk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAvLyBEaWZmZXJlbnQgYWRkcmVzcyB0aGFuIHdoYXQncyBpbiB0aGUgdHJhbnNhY3Rpb25cbiAgICAgICAgICAgICAgICBhZGRyZXNzOiAnVFRzR3duVExRNGVyeUZKcER2SlNmdUdReFBYUkNqWHZaeicsXG4gICAgICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAwMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IHJhd0RhdGFIZXgsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3YWxsZXQ6IHt9LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtcyksIHtcbiAgICAgICAgICBtZXNzYWdlOiAnZGVzdGluYXRpb24gYWRkcmVzcyBkb2VzIG5vdCBtYXRjaCB3aXRoIHRoZSByZWNpcGllbnQgYWRkcmVzcycsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBub24tVHJhbnNmZXIsIG5vbi1UcmlnZ2VyU21hcnRDb250cmFjdCB0eXBlcyBpbiBUU1MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBBY2NvdW50UGVybWlzc2lvblVwZGF0ZSBhbmQgb3RoZXIgbmF0aXZlIFRSWCBjb250cmFjdHMgKGZyZWV6ZSwgdm90ZSwgZXRjLikgcGFzcyB0aHJvdWdoXG4gICAgICAvLyB3aXRob3V0IHJlY2lwaWVudCB2YWxpZGF0aW9uIGluIHRoZSBUU1MgcGF0aC5cbiAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBVbnNpZ25lZEFjY291bnRQZXJtaXNzaW9uVXBkYXRlQ29udHJhY3RUeC5yYXdfZGF0YV9oZXg7XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4OiByYXdEYXRhSGV4LFxuICAgICAgICB9LFxuICAgICAgICB3YWxsZXQ6IHt9LFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBUU1MgbmF0aXZlIFRSWCB2ZXJpZnlUcmFuc2FjdGlvbiBlbmNvdW50ZXJzIGEgVHJpZ2dlclNtYXJ0Q29udHJhY3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBEZWZlbnNlLWluLWRlcHRoOiBuYXRpdmUgVFJYIChUcngpIHNob3VsZCBuZXZlciB2ZXJpZnkgVHJpZ2dlclNtYXJ0Q29udHJhY3QuXG4gICAgICAvLyBUUkMyMCB0b2tlbiB0cmFuc2ZlcnMgbXVzdCBnbyB0aHJvdWdoIFRyeFRva2VuLnZlcmlmeVRyYW5zYWN0aW9uLlxuICAgICAgLy8gVGhlIHJhd19kYXRhX2hleCBiZWxvdyBpcyBhIHJlYWwgVFJDMjAgVHJpZ2dlclNtYXJ0Q29udHJhY3QgcHJvdG9idWYuXG4gICAgICBjb25zdCB0cmMyMFJhd0RhdGFIZXggPVxuICAgICAgICAnMGEwMjU3OGIyMjA4NjExM2JiOWFjMzUxNDMyYjQwODhlYWU3YTZkZTMwNWFhZTAxMDgxZjEyYTkwMTBhMzE3NDc5NzA2NTJlNjc2ZjZmNjc2YzY1NjE3MDY5NzMyZTYzNmY2ZDJmNzA3MjZmNzQ2ZjYzNmY2YzJlNTQ3MjY5Njc2NzY1NzI1MzZkNjE3Mjc0NDM2ZjZlNzQ3MjYxNjM3NDEyNzQwYTE1NDFjNTFmYmVlYTc4OTEwYjE1YjFkM2U4YTliNjI5MTRjYTk0ZDFhNGFjMTIxNTQxNDJhMWUzOWFlZmE0OTI5MGYyYjNmOWVkNjg4ZDdjZWNmODZjZDZlMDIyNDRhOTA1OWNiYjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDg0ODM2MThjYTg1YzM1YTliOTIzZDk4YmViY2E3MThmNWExZGIyNzkwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA1ZjVlMTAwNzA4ODhkOGNhNWRlMzA5MDAxYzBjMzkzMDcnO1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJ1RMV2g2N1A5M0tndG5aTkN0R25FSE0xSDMzTmhxMnV2dk4nLCBhbW91bnQ6ICcxMDAwMDAwMDAnIH1dLFxuICAgICAgICB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgdHhIZXg6IHRyYzIwUmF3RGF0YUhleCxcbiAgICAgICAgfSxcbiAgICAgICAgd2FsbGV0OiB7fSxcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhiYXNlY29pbi52ZXJpZnlUcmFuc2FjdGlvbihwYXJhbXMpLCB7XG4gICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgJ1RyaWdnZXJTbWFydENvbnRyYWN0IHZlcmlmaWNhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIGJ5IG5hdGl2ZSBUUlguICcgK1xuICAgICAgICAgICdUUkMyMCB0b2tlbiB0cmFuc2ZlcnMgbXVzdCBiZSB2ZXJpZmllZCB2aWEgVHJ4VG9rZW4udmVyaWZ5VHJhbnNhY3Rpb24uJyxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIHR4SGV4IGlzIG1pc3NpbmcgZm9yIFRTUyB3YWxsZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJ1RRRnhEU29YeTJ5WFJFNUh0S3dBd3JOUlhHeFl4a2VTR2snLCBhbW91bnQ6ICcxMDAwMDAwJyB9XSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDoge30sXG4gICAgICAgIHdhbGxldDoge30sXG4gICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zKSwge1xuICAgICAgICBtZXNzYWdlOiAnbWlzc2luZyB0eEhleCBpbiB0eFByZWJ1aWxkJyxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3NlcmlhbGl6ZWRUeEhleCAoSlNPTiBzdHJpbmcpIHBhdGgnLCAoKSA9PiB7XG4gICAgICAvLyBwcmVidWlsZEFuZFNpZ25UcmFuc2FjdGlvbiBwYXNzZXMgdHhIZXggYXMgc2VyaWFsaXplZFR4SGV4IOKAlCBhIGZ1bGwgSlNPTiBzdHJpbmdcbiAgICAgIC8vIGNvbnRhaW5pbmcgeyB0eElELCByYXdfZGF0YSwgcmF3X2RhdGFfaGV4IH0uIFRoZSBUU1MgYnJhbmNoIG11c3QgaGFuZGxlIHRoaXMgZm9ybWF0XG4gICAgICAvLyBieSBleHRyYWN0aW5nIHJhd19kYXRhX2hleCBiZWZvcmUgcHJvdG9idWYgZGVjb2RpbmcuXG5cbiAgICAgIGl0KCdzaG91bGQgdmFsaWRhdGUgVFNTIFRyYW5zZmVyQ29udHJhY3Qgd2hlbiB0eEhleCBpcyBhIEpTT04gc3RyaW5nIChzZXJpYWxpemVkVHhIZXgpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBvd25lckhleCA9ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnO1xuICAgICAgICBjb25zdCB0b0hleCA9ICc0MWQ2Y2Q2YTJjMGZmMzVhMzE5ZTZhYmI1Yjk1MDNiYTAyNzg2Nzk4ODInO1xuICAgICAgICBjb25zdCBhbW91bnQgPSAxMDAwMDAwO1xuXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBidWlsZFRzc1RyYW5zZmVyVHhIZXgoeyBvd25lckFkZHJlc3M6IG93bmVySGV4LCB0b0FkZHJlc3M6IHRvSGV4LCBhbW91bnQgfSk7XG4gICAgICAgIGNvbnN0IHR4SUQgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoQnVmZmVyLmZyb20ocmF3RGF0YUhleCwgJ2hleCcpKS5kaWdlc3QoJ2hleCcpO1xuXG4gICAgICAgIC8vIFNpbXVsYXRlIHRoZSBzZXJpYWxpemVkVHhIZXggZm9ybWF0IGZyb20gQml0R28gQVBJIChKU09OIHN0cmluZyB3aXRoIHR4SUQgKyByYXdfZGF0YV9oZXgpXG4gICAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUeEhleCA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICB0eElELFxuICAgICAgICAgIHJhd19kYXRhX2hleDogcmF3RGF0YUhleCxcbiAgICAgICAgICByYXdfZGF0YToge30sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWRkcmVzczogVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodG9IZXgpLFxuICAgICAgICAgICAgICAgIGFtb3VudDogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgdHhIZXg6IHNlcmlhbGl6ZWRUeEhleCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHdhbGxldDoge30sXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZWNvaW4udmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zKTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBmYWlsIHdoZW4gYW1vdW50IG1pc21hdGNoZXMgd2l0aCBKU09OIHR4SGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBvd25lckhleCA9ICc0MTczYTU5OTNjZDE4MmFlMTUyYWRhZDgyMDMxNjNmNzgwYzY1YThhYTUnO1xuICAgICAgICBjb25zdCB0b0hleCA9ICc0MWQ2Y2Q2YTJjMGZmMzVhMzE5ZTZhYmI1Yjk1MDNiYTAyNzg2Nzk4ODInO1xuXG4gICAgICAgIGNvbnN0IHJhd0RhdGFIZXggPSBidWlsZFRzc1RyYW5zZmVyVHhIZXgoeyBvd25lckFkZHJlc3M6IG93bmVySGV4LCB0b0FkZHJlc3M6IHRvSGV4LCBhbW91bnQ6IDIwMDAwMDAgfSk7XG4gICAgICAgIGNvbnN0IHNlcmlhbGl6ZWRUeEhleCA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICB0eElEOiBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoQnVmZmVyLmZyb20ocmF3RGF0YUhleCwgJ2hleCcpKS5kaWdlc3QoJ2hleCcpLFxuICAgICAgICAgIHJhd19kYXRhX2hleDogcmF3RGF0YUhleCxcbiAgICAgICAgICByYXdfZGF0YToge30sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWRkcmVzczogVXRpbHMuZ2V0QmFzZTU4QWRkcmVzc0Zyb21IZXgodG9IZXgpLFxuICAgICAgICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAnLCAvLyBtaXNtYXRjaFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHtcbiAgICAgICAgICAgIHR4SGV4OiBzZXJpYWxpemVkVHhIZXgsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB3YWxsZXQ6IHt9LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGJhc2Vjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHBhcmFtcyksIHtcbiAgICAgICAgICBtZXNzYWdlOiAndHJhbnNhY3Rpb24gYW1vdW50IGluIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggdGhlIHZhbHVlIGdpdmVuIGJ5IGNsaWVudCcsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=