@bitgo-beta/sdk-coin-eth 4.4.1-beta.21 → 4.4.1-beta.2100

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