@bitgo-beta/sdk-coin-sui 3.0.3-beta.182 → 3.0.3-beta.1821

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +7 -2
  4. package/dist/src/lib/compareTransactionBlocks.js +2 -3
  5. package/dist/src/lib/constants.d.ts +9 -2
  6. package/dist/src/lib/constants.d.ts.map +1 -1
  7. package/dist/src/lib/constants.js +18 -2
  8. package/dist/src/lib/customTransaction.js +3 -3
  9. package/dist/src/lib/customTransactionBuilder.js +5 -5
  10. package/dist/src/lib/iface.d.ts +80 -12
  11. package/dist/src/lib/iface.d.ts.map +1 -1
  12. package/dist/src/lib/iface.js +34 -5
  13. package/dist/src/lib/index.d.ts +6 -0
  14. package/dist/src/lib/index.d.ts.map +1 -1
  15. package/dist/src/lib/index.js +36 -10
  16. package/dist/src/lib/keyPair.js +24 -10
  17. package/dist/src/lib/mystenlab/builder/Inputs.d.ts +64 -11
  18. package/dist/src/lib/mystenlab/builder/Inputs.d.ts.map +1 -1
  19. package/dist/src/lib/mystenlab/builder/Inputs.js +63 -19
  20. package/dist/src/lib/mystenlab/builder/TransactionBlock.d.ts +88 -355
  21. package/dist/src/lib/mystenlab/builder/TransactionBlock.d.ts.map +1 -1
  22. package/dist/src/lib/mystenlab/builder/TransactionBlock.js +44 -25
  23. package/dist/src/lib/mystenlab/builder/TransactionDataBlock.d.ts +152 -77
  24. package/dist/src/lib/mystenlab/builder/TransactionDataBlock.d.ts.map +1 -1
  25. package/dist/src/lib/mystenlab/builder/TransactionDataBlock.js +54 -44
  26. package/dist/src/lib/mystenlab/builder/Transactions.d.ts +133 -188
  27. package/dist/src/lib/mystenlab/builder/Transactions.d.ts.map +1 -1
  28. package/dist/src/lib/mystenlab/builder/Transactions.js +52 -53
  29. package/dist/src/lib/mystenlab/builder/bcs.d.ts +1 -1
  30. package/dist/src/lib/mystenlab/builder/bcs.d.ts.map +1 -1
  31. package/dist/src/lib/mystenlab/builder/bcs.js +2 -2
  32. package/dist/src/lib/mystenlab/builder/index.js +6 -2
  33. package/dist/src/lib/mystenlab/builder/serializer.js +6 -8
  34. package/dist/src/lib/mystenlab/builder/utils.d.ts +1 -1
  35. package/dist/src/lib/mystenlab/builder/utils.d.ts.map +1 -1
  36. package/dist/src/lib/mystenlab/builder/utils.js +4 -4
  37. package/dist/src/lib/mystenlab/cryptography/hash.js +3 -4
  38. package/dist/src/lib/mystenlab/framework/framework.d.ts +6 -6
  39. package/dist/src/lib/mystenlab/framework/framework.d.ts.map +1 -1
  40. package/dist/src/lib/mystenlab/framework/framework.js +22 -25
  41. package/dist/src/lib/mystenlab/framework/index.js +6 -2
  42. package/dist/src/lib/mystenlab/framework/sui-system-state.js +2 -2
  43. package/dist/src/lib/mystenlab/txn-data-serializers/type-tag-serializer.js +2 -2
  44. package/dist/src/lib/mystenlab/types/coin.d.ts +13 -11
  45. package/dist/src/lib/mystenlab/types/coin.d.ts.map +1 -1
  46. package/dist/src/lib/mystenlab/types/coin.js +20 -19
  47. package/dist/src/lib/mystenlab/types/common.d.ts +8 -8
  48. package/dist/src/lib/mystenlab/types/common.d.ts.map +1 -1
  49. package/dist/src/lib/mystenlab/types/common.js +22 -22
  50. package/dist/src/lib/mystenlab/types/events.d.ts +15 -15
  51. package/dist/src/lib/mystenlab/types/events.d.ts.map +1 -1
  52. package/dist/src/lib/mystenlab/types/events.js +17 -17
  53. package/dist/src/lib/mystenlab/types/index.js +6 -2
  54. package/dist/src/lib/mystenlab/types/normalized.d.ts +21 -21
  55. package/dist/src/lib/mystenlab/types/normalized.d.ts.map +1 -1
  56. package/dist/src/lib/mystenlab/types/normalized.js +41 -41
  57. package/dist/src/lib/mystenlab/types/objects.d.ts +51 -51
  58. package/dist/src/lib/mystenlab/types/objects.d.ts.map +1 -1
  59. package/dist/src/lib/mystenlab/types/objects.js +96 -106
  60. package/dist/src/lib/mystenlab/types/option.d.ts +1 -1
  61. package/dist/src/lib/mystenlab/types/option.d.ts.map +1 -1
  62. package/dist/src/lib/mystenlab/types/option.js +2 -3
  63. package/dist/src/lib/mystenlab/types/sui-bcs.d.ts +55 -29
  64. package/dist/src/lib/mystenlab/types/sui-bcs.d.ts.map +1 -1
  65. package/dist/src/lib/mystenlab/types/sui-bcs.js +29 -5
  66. package/dist/src/lib/mystenlab/types/transactions.d.ts +625 -625
  67. package/dist/src/lib/mystenlab/types/transactions.d.ts.map +1 -1
  68. package/dist/src/lib/mystenlab/types/transactions.js +178 -194
  69. package/dist/src/lib/mystenlab/types/validator.d.ts +13 -13
  70. package/dist/src/lib/mystenlab/types/validator.d.ts.map +1 -1
  71. package/dist/src/lib/mystenlab/types/validator.js +124 -124
  72. package/dist/src/lib/resources/walrusConfig.d.ts +22 -0
  73. package/dist/src/lib/resources/walrusConfig.d.ts.map +1 -0
  74. package/dist/src/lib/resources/walrusConfig.js +37 -0
  75. package/dist/src/lib/rpcClient.d.ts +5 -0
  76. package/dist/src/lib/rpcClient.d.ts.map +1 -0
  77. package/dist/src/lib/rpcClient.js +74 -0
  78. package/dist/src/lib/stakingBuilder.d.ts.map +1 -1
  79. package/dist/src/lib/stakingBuilder.js +23 -7
  80. package/dist/src/lib/stakingTransaction.d.ts +0 -1
  81. package/dist/src/lib/stakingTransaction.d.ts.map +1 -1
  82. package/dist/src/lib/stakingTransaction.js +26 -15
  83. package/dist/src/lib/tokenTransferBuilder.d.ts +66 -0
  84. package/dist/src/lib/tokenTransferBuilder.d.ts.map +1 -0
  85. package/dist/src/lib/tokenTransferBuilder.js +202 -0
  86. package/dist/src/lib/tokenTransferTransaction.d.ts +59 -0
  87. package/dist/src/lib/tokenTransferTransaction.d.ts.map +1 -0
  88. package/dist/src/lib/tokenTransferTransaction.js +272 -0
  89. package/dist/src/lib/transaction.d.ts +21 -4
  90. package/dist/src/lib/transaction.d.ts.map +1 -1
  91. package/dist/src/lib/transaction.js +129 -17
  92. package/dist/src/lib/transactionBuilder.d.ts +13 -4
  93. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  94. package/dist/src/lib/transactionBuilder.js +34 -4
  95. package/dist/src/lib/transactionBuilderFactory.d.ts +11 -2
  96. package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -1
  97. package/dist/src/lib/transactionBuilderFactory.js +32 -1
  98. package/dist/src/lib/transferBuilder.d.ts +58 -1
  99. package/dist/src/lib/transferBuilder.d.ts.map +1 -1
  100. package/dist/src/lib/transferBuilder.js +310 -24
  101. package/dist/src/lib/transferTransaction.d.ts +6 -1
  102. package/dist/src/lib/transferTransaction.d.ts.map +1 -1
  103. package/dist/src/lib/transferTransaction.js +129 -12
  104. package/dist/src/lib/unstakingBuilder.js +6 -6
  105. package/dist/src/lib/unstakingTransaction.d.ts +0 -1
  106. package/dist/src/lib/unstakingTransaction.d.ts.map +1 -1
  107. package/dist/src/lib/unstakingTransaction.js +31 -17
  108. package/dist/src/lib/utils.d.ts +24 -3
  109. package/dist/src/lib/utils.d.ts.map +1 -1
  110. package/dist/src/lib/utils.js +254 -21
  111. package/dist/src/lib/walrusStakingBuilder.d.ts +66 -0
  112. package/dist/src/lib/walrusStakingBuilder.d.ts.map +1 -0
  113. package/dist/src/lib/walrusStakingBuilder.js +200 -0
  114. package/dist/src/lib/walrusStakingTransaction.d.ts +52 -0
  115. package/dist/src/lib/walrusStakingTransaction.d.ts.map +1 -0
  116. package/dist/src/lib/walrusStakingTransaction.js +269 -0
  117. package/dist/src/lib/walrusWithdrawStakeBuilder.d.ts +36 -0
  118. package/dist/src/lib/walrusWithdrawStakeBuilder.d.ts.map +1 -0
  119. package/dist/src/lib/walrusWithdrawStakeBuilder.js +173 -0
  120. package/dist/src/lib/walrusWithdrawStakeTransaction.d.ts +21 -0
  121. package/dist/src/lib/walrusWithdrawStakeTransaction.d.ts.map +1 -0
  122. package/dist/src/lib/walrusWithdrawStakeTransaction.js +190 -0
  123. package/dist/src/register.d.ts.map +1 -1
  124. package/dist/src/register.js +5 -1
  125. package/dist/src/sui.d.ts +46 -8
  126. package/dist/src/sui.d.ts.map +1 -1
  127. package/dist/src/sui.js +525 -37
  128. package/dist/src/suiToken.d.ts +22 -0
  129. package/dist/src/suiToken.d.ts.map +1 -0
  130. package/dist/src/suiToken.js +61 -0
  131. package/dist/src/tsui.js +1 -1
  132. package/dist/test/integration/index.d.ts +1 -0
  133. package/dist/test/integration/index.d.ts.map +1 -0
  134. package/dist/test/integration/index.js +1 -0
  135. package/dist/test/local_fullnode/RpcClient.d.ts +60 -0
  136. package/dist/test/local_fullnode/RpcClient.d.ts.map +1 -0
  137. package/dist/test/local_fullnode/RpcClient.js +111 -0
  138. package/dist/test/local_fullnode/faucet.d.ts +6 -0
  139. package/dist/test/local_fullnode/faucet.d.ts.map +1 -0
  140. package/dist/test/local_fullnode/faucet.js +17 -0
  141. package/dist/test/local_fullnode/transactions.d.ts +2 -0
  142. package/dist/test/local_fullnode/transactions.d.ts.map +1 -0
  143. package/dist/test/local_fullnode/transactions.js +190 -0
  144. package/dist/test/resources/sui.d.ts +458 -0
  145. package/dist/test/resources/sui.d.ts.map +1 -0
  146. package/dist/test/resources/sui.js +632 -0
  147. package/dist/test/unit/compareTransactionBlocks.d.ts +2 -0
  148. package/dist/test/unit/compareTransactionBlocks.d.ts.map +1 -0
  149. package/dist/test/unit/compareTransactionBlocks.js +64 -0
  150. package/dist/test/unit/getBuilderFactory.d.ts +3 -0
  151. package/dist/test/unit/getBuilderFactory.d.ts.map +1 -0
  152. package/dist/test/unit/getBuilderFactory.js +10 -0
  153. package/dist/test/unit/keyPair.d.ts +2 -0
  154. package/dist/test/unit/keyPair.d.ts.map +1 -0
  155. package/dist/test/unit/keyPair.js +72 -0
  156. package/dist/test/unit/sui.d.ts +2 -0
  157. package/dist/test/unit/sui.d.ts.map +1 -0
  158. package/dist/test/unit/sui.js +2423 -0
  159. package/dist/test/unit/suiToken.d.ts +2 -0
  160. package/dist/test/unit/suiToken.d.ts.map +1 -0
  161. package/dist/test/unit/suiToken.js +39 -0
  162. package/dist/test/unit/transactionBuilder/customTransactionBuilder.d.ts +2 -0
  163. package/dist/test/unit/transactionBuilder/customTransactionBuilder.d.ts.map +1 -0
  164. package/dist/test/unit/transactionBuilder/customTransactionBuilder.js +106 -0
  165. package/dist/test/unit/transactionBuilder/stakingBuilder.d.ts +2 -0
  166. package/dist/test/unit/transactionBuilder/stakingBuilder.d.ts.map +1 -0
  167. package/dist/test/unit/transactionBuilder/stakingBuilder.js +152 -0
  168. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts +2 -0
  169. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.d.ts.map +1 -0
  170. package/dist/test/unit/transactionBuilder/tokenTransferBuilder.js +255 -0
  171. package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts +2 -0
  172. package/dist/test/unit/transactionBuilder/transactionBuilder.d.ts.map +1 -0
  173. package/dist/test/unit/transactionBuilder/transactionBuilder.js +639 -0
  174. package/dist/test/unit/transactionBuilder/transferBuilder.d.ts +2 -0
  175. package/dist/test/unit/transactionBuilder/transferBuilder.d.ts.map +1 -0
  176. package/dist/test/unit/transactionBuilder/transferBuilder.js +1055 -0
  177. package/dist/test/unit/transactionBuilder/unstakingBuilder.d.ts +2 -0
  178. package/dist/test/unit/transactionBuilder/unstakingBuilder.d.ts.map +1 -0
  179. package/dist/test/unit/transactionBuilder/unstakingBuilder.js +115 -0
  180. package/dist/test/unit/transactionBuilder/walrusStakingBuilder.d.ts +2 -0
  181. package/dist/test/unit/transactionBuilder/walrusStakingBuilder.d.ts.map +1 -0
  182. package/dist/test/unit/transactionBuilder/walrusStakingBuilder.js +162 -0
  183. package/dist/test/unit/transactionBuilder/walrusWithdrawBuilder.d.ts +2 -0
  184. package/dist/test/unit/transactionBuilder/walrusWithdrawBuilder.d.ts.map +1 -0
  185. package/dist/test/unit/transactionBuilder/walrusWithdrawBuilder.js +181 -0
  186. package/dist/test/unit/transferTransaction.d.ts +2 -0
  187. package/dist/test/unit/transferTransaction.d.ts.map +1 -0
  188. package/dist/test/unit/transferTransaction.js +94 -0
  189. package/dist/test/unit/utils.d.ts +2 -0
  190. package/dist/test/unit/utils.d.ts.map +1 -0
  191. package/dist/test/unit/utils.js +186 -0
  192. package/dist/tsconfig.tsbuildinfo +1 -0
  193. package/package.json +16 -12
  194. package/.eslintignore +0 -6
  195. package/.mocharc.yml +0 -7
  196. package/CHANGELOG.md +0 -420
@@ -0,0 +1,1055 @@
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
+ const assert_1 = __importDefault(require("assert"));
40
+ const getBuilderFactory_1 = require("../getBuilderFactory");
41
+ const testData = __importStar(require("../../resources/sui"));
42
+ const should_1 = __importDefault(require("should"));
43
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
44
+ const utils_1 = __importDefault(require("../../../src/lib/utils"));
45
+ const transaction_1 = require("../../../src/lib/transaction");
46
+ const iface_1 = require("../../../src/lib/iface");
47
+ const constants_1 = require("../../../src/lib/constants");
48
+ describe('Sui Transfer Builder', () => {
49
+ const factory = (0, getBuilderFactory_1.getBuilderFactory)('tsui');
50
+ describe('Succeed', () => {
51
+ it('should build a transfer tx', async function () {
52
+ const txBuilder = factory.getTransferBuilder();
53
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
54
+ txBuilder.sender(testData.sender.address);
55
+ txBuilder.send(testData.recipients);
56
+ txBuilder.gasData(testData.gasData);
57
+ const tx = await txBuilder.build();
58
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
59
+ tx.suiTransaction.gasData.payment.should.deepEqual(testData.coinsGasPayment);
60
+ tx.inputs.length.should.equal(1);
61
+ tx.inputs[0].should.deepEqual({
62
+ address: testData.sender.address,
63
+ value: (testData.AMOUNT * 2).toString(),
64
+ coin: 'tsui',
65
+ });
66
+ tx.outputs.length.should.equal(2);
67
+ tx.outputs[0].should.deepEqual({
68
+ address: testData.recipients[0].address,
69
+ value: testData.recipients[0].amount,
70
+ coin: 'tsui',
71
+ });
72
+ tx.outputs[1].should.deepEqual({
73
+ address: testData.recipients[1].address,
74
+ value: testData.recipients[1].amount,
75
+ coin: 'tsui',
76
+ });
77
+ const rawTx = tx.toBroadcastFormat();
78
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
79
+ should_1.default.equal(rawTx, testData.TRANSFER);
80
+ });
81
+ it('should build a sponsored transfer tx with inputObjects', async function () {
82
+ const inputObjects = [
83
+ {
84
+ objectId: '0000000000000000000000001234567890abcdef1234567890abcdef12345678',
85
+ version: 100,
86
+ digest: '2B8XKQJ7mfxQPUWqJJAGjzBAzivkWKq2cEa3W8LLz1yB',
87
+ },
88
+ {
89
+ objectId: '000000000000000000000000abcdef1234567890abcdef1234567890abcdef12',
90
+ version: 200,
91
+ digest: 'DoJwXuz9oU5Y5v5vBRiTgisVTQuZQLmHZWeqJzzD5QUE',
92
+ },
93
+ ];
94
+ // Create gas data with different owner (sponsor)
95
+ const sponsoredGasData = {
96
+ ...testData.gasData,
97
+ owner: testData.feePayer.address, // Different from sender
98
+ };
99
+ const txBuilder = factory.getTransferBuilder();
100
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
101
+ txBuilder.sender(testData.sender.address); // Sender
102
+ txBuilder.send(testData.recipients);
103
+ txBuilder.gasData(sponsoredGasData); // Gas paid by sponsor
104
+ txBuilder.inputObjects(inputObjects); // Required for sponsored tx
105
+ const tx = await txBuilder.build();
106
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
107
+ const suiTx = tx;
108
+ // Verify transaction structure for sponsored transaction
109
+ const programmableTx = suiTx.suiTransaction.tx;
110
+ programmableTx.transactions.length.should.be.greaterThan(0);
111
+ // Verify sponsored transaction characteristics
112
+ suiTx.suiTransaction.sender.should.equal(testData.sender.address);
113
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
114
+ // Should have transactions for merging/splitting and transferring when using inputObjects
115
+ programmableTx.transactions.length.should.be.greaterThan(0);
116
+ // Verify we have transfer operations (the exact structure varies with API versions)
117
+ should_1.default.exist(programmableTx.transactions);
118
+ // Verify inputObjects are not used in gas payment (they're separate)
119
+ suiTx.suiTransaction.gasData.payment.should.not.containDeep(inputObjects);
120
+ const rawTx = tx.toBroadcastFormat();
121
+ should_1.default.exist(rawTx);
122
+ should_1.default.equal(typeof rawTx, 'string');
123
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
124
+ });
125
+ it('should build a split coin tx', async function () {
126
+ const txBuilder = factory.getTransferBuilder();
127
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
128
+ txBuilder.sender(testData.sender.address);
129
+ const amount = 1000000000;
130
+ const recipients = new Array(100).fill({ address: testData.sender.address, amount: amount.toString() });
131
+ txBuilder.send(recipients);
132
+ txBuilder.gasData(testData.gasData);
133
+ const tx = await txBuilder.build();
134
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
135
+ tx.suiTransaction.gasData.payment.should.deepEqual(testData.coinsGasPayment);
136
+ tx.inputs.length.should.equal(1);
137
+ tx.inputs[0].should.deepEqual({
138
+ address: testData.sender.address,
139
+ value: (amount * 100).toString(),
140
+ coin: 'tsui',
141
+ });
142
+ tx.outputs.length.should.equal(100);
143
+ tx.outputs.forEach((output) => output.should.deepEqual({
144
+ address: testData.sender.address,
145
+ value: amount.toString(),
146
+ coin: 'tsui',
147
+ }));
148
+ });
149
+ it('should build a split coin tx with more than 255 input objects', async function () {
150
+ const amount = 1000000000;
151
+ const numberOfRecipients = 10;
152
+ const numberOfPaymentObjects = 1000;
153
+ const txBuilder = factory.getTransferBuilder();
154
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
155
+ txBuilder.sender(testData.sender.address);
156
+ const recipients = new Array(numberOfRecipients).fill({
157
+ address: testData.sender.address,
158
+ amount: amount.toString(),
159
+ });
160
+ const gasData = {
161
+ ...testData.gasData,
162
+ payment: testData.generateObjects(numberOfPaymentObjects),
163
+ };
164
+ txBuilder.send(recipients);
165
+ txBuilder.gasData(gasData);
166
+ const tx = await txBuilder.build();
167
+ (0, assert_1.default)(tx instanceof transaction_1.Transaction);
168
+ tx.type.should.equal(sdk_core_1.TransactionType.Send);
169
+ tx.inputs.length.should.equal(1);
170
+ tx.inputs[0].should.deepEqual({
171
+ address: testData.sender.address,
172
+ value: (amount * 10).toString(),
173
+ coin: 'tsui',
174
+ });
175
+ tx.outputs.length.should.equal(10);
176
+ tx.outputs.forEach((output) => output.should.deepEqual({
177
+ coin: 'tsui',
178
+ address: testData.sender.address,
179
+ value: amount.toString(),
180
+ }));
181
+ tx.suiTransaction.gasData.owner.should.equal(gasData.owner);
182
+ tx.suiTransaction.gasData.price.should.equal(gasData.price);
183
+ tx.suiTransaction.gasData.budget.should.equal(gasData.budget);
184
+ tx.suiTransaction.gasData.payment.length.should.equal(constants_1.MAX_GAS_OBJECTS - 1);
185
+ const programmableTx = tx.suiTransaction.tx;
186
+ // total objects - objects sent as gas payment + no. of recipient amounts(pure)
187
+ // + no. of unique recipient addresses(de-duped objects)
188
+ programmableTx.inputs.length.should.equal(numberOfPaymentObjects - (constants_1.MAX_GAS_OBJECTS - 1) + numberOfRecipients + 1);
189
+ programmableTx.transactions[0].kind.should.equal('MergeCoins');
190
+ programmableTx.transactions[0].sources.length.should.equal(constants_1.MAX_COMMAND_ARGS - 1);
191
+ programmableTx.transactions[1].kind.should.equal('MergeCoins');
192
+ programmableTx.transactions[1].sources.length.should.equal(numberOfPaymentObjects - (constants_1.MAX_COMMAND_ARGS - 1) - (constants_1.MAX_GAS_OBJECTS - 1));
193
+ const rawTx = tx.toBroadcastFormat();
194
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
195
+ const rebuilder = factory.from(rawTx);
196
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
197
+ const rebuiltTx = await rebuilder.build();
198
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
199
+ rebuiltTx.toJson().gasData.payment.length.should.equal(numberOfPaymentObjects);
200
+ });
201
+ });
202
+ describe('Fail', () => {
203
+ it('should fail for invalid sender', async function () {
204
+ const builder = factory.getTransferBuilder();
205
+ (0, should_1.default)(() => builder.sender('randomString')).throwError('Invalid or missing sender, got: randomString');
206
+ });
207
+ it('should fail for invalid payTx', async function () {
208
+ const builder = factory.getTransferBuilder();
209
+ (0, should_1.default)(() => builder.send([testData.invalidRecipients[0]])).throwError('Invalid or missing address, got: randomString');
210
+ (0, should_1.default)(() => builder.send([testData.invalidRecipients[1]])).throwError('Invalid recipient amount');
211
+ });
212
+ it('should fail for invalid gasData', function () {
213
+ const builder = factory.getTransferBuilder();
214
+ (0, should_1.default)(() => builder.gasData(testData.invalidGasOwner)).throwError(`Invalid gas address ${testData.invalidGasOwner.owner}`);
215
+ });
216
+ it('should fail for invalid gasBudget', function () {
217
+ const builder = factory.getTransferBuilder();
218
+ (0, should_1.default)(() => builder.gasData(testData.invalidGasBudget)).throwError('Invalid gas budget -1');
219
+ });
220
+ it('should fail for invalid gasPayment', function () {
221
+ const builder = factory.getTransferBuilder();
222
+ const invalidGasPayment = {
223
+ ...testData.gasDataWithoutGasPayment,
224
+ payment: [
225
+ {
226
+ objectId: '',
227
+ version: -1,
228
+ digest: '',
229
+ },
230
+ ],
231
+ };
232
+ (0, should_1.default)(() => builder.gasData(invalidGasPayment)).throwError('Invalid payment, invalid or missing version');
233
+ });
234
+ it('should fail for invalid inputObjects', function () {
235
+ const builder = factory.getTransferBuilder();
236
+ const invalidInputObjects = [
237
+ {
238
+ objectId: '',
239
+ version: -1,
240
+ digest: '',
241
+ },
242
+ ];
243
+ (0, should_1.default)(() => builder.inputObjects(invalidInputObjects)).throwError('Invalid input object, invalid or missing version');
244
+ });
245
+ it('should build transfer with different gas owner but no inputObjects', async function () {
246
+ const sponsoredGasData = {
247
+ ...testData.gasData,
248
+ owner: testData.feePayer.address, // Different from sender
249
+ };
250
+ const txBuilder = factory.getTransferBuilder();
251
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
252
+ txBuilder.sender(testData.sender.address); // Sender
253
+ txBuilder.send(testData.recipients);
254
+ txBuilder.gasData(sponsoredGasData); // Gas paid by sponsor
255
+ // Note: NOT providing inputObjects - should still work (fee sponsorship without coin sponsorship)
256
+ const tx = await txBuilder.build();
257
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
258
+ const suiTx = tx;
259
+ should_1.default.not.exist(suiTx.suiTransaction.inputObjects);
260
+ const rawTx = tx.toBroadcastFormat();
261
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
262
+ });
263
+ it('should extract inputObjects from transaction data via toJson', async function () {
264
+ const inputObjects = [
265
+ {
266
+ objectId: '0x1234567890abcdef1234567890abcdef12345678',
267
+ version: 100,
268
+ digest: '2B8XKQJ7mfxQPUWqJJAGjzBAzivkWKq2cEa3W8LLz1yB',
269
+ },
270
+ ];
271
+ const sponsoredGasData = {
272
+ ...testData.gasData,
273
+ owner: testData.feePayer.address, // Different from sender
274
+ };
275
+ const txBuilder = factory.getTransferBuilder();
276
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
277
+ txBuilder.sender(testData.sender.address);
278
+ txBuilder.send(testData.recipients);
279
+ txBuilder.gasData(sponsoredGasData);
280
+ txBuilder.inputObjects(inputObjects);
281
+ const tx = await txBuilder.build();
282
+ // Test that toJson extracts inputObjects from transaction structure
283
+ const txData = tx.toJson();
284
+ should_1.default.exist(txData.inputObjects);
285
+ // The toJson should extract the inputObjects from the transaction structure
286
+ // This tests our new getInputObjectsFromTx method
287
+ should_1.default.exist(txData.inputObjects);
288
+ Array.isArray(txData.inputObjects).should.equal(true);
289
+ });
290
+ });
291
+ describe('fundsInAddressBalance', () => {
292
+ const FUNDS_IN_ADDRESS_BALANCE = '5000000000'; // 5 SUI
293
+ it('should build Path 2b: self-pay, address-balance only — uses withdrawal+redeem_funds, not SplitCoins(GasCoin)', async function () {
294
+ // Regression for production InsufficientCoinBalance failures on consolidation.
295
+ // With payment=[], GasCoin only has gas-budget-worth of balance for PTB operations;
296
+ // SplitCoins(GasCoin, [large_amount]) always fails at command 0.
297
+ // Path 2b must use withdrawal+redeem_funds to materialise the address balance as a
298
+ // coin object and split from that coin instead.
299
+ const gasDataNoPayment = {
300
+ ...testData.gasDataWithoutGasPayment,
301
+ payment: [],
302
+ };
303
+ const txBuilder = factory.getTransferBuilder();
304
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
305
+ txBuilder.sender(testData.sender.address);
306
+ txBuilder.send(testData.recipients); // 2 recipients
307
+ txBuilder.gasData(gasDataNoPayment);
308
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
309
+ const tx = await txBuilder.build();
310
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
311
+ const suiTx = tx;
312
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
313
+ // Path 2b PTB command sequence (2 recipients):
314
+ // 0: MoveCall(redeem_funds) — materialise addrCoin from address balance
315
+ // 1: SplitCoins(addrCoin, [amount0]) — split for recipient 0
316
+ // 2: TransferObjects — send to recipient 0
317
+ // 3: SplitCoins(addrCoin, [amount1]) — split for recipient 1
318
+ // 4: TransferObjects — send to recipient 1
319
+ // 5: MergeCoins(GasCoin, [addrCoin]) — destroy 0-balance addrCoin; gas from accumulator
320
+ const cmds = suiTx.suiTransaction.tx.transactions;
321
+ cmds[0].kind.should.equal('MoveCall', 'command 0 must be MoveCall(redeem_funds)');
322
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
323
+ cmds[1].kind.should.equal('SplitCoins', 'command 1 must be SplitCoins(addrCoin)');
324
+ cmds[2].kind.should.equal('TransferObjects', 'command 2 must be TransferObjects');
325
+ cmds[3].kind.should.equal('SplitCoins', 'command 3 must be SplitCoins(addrCoin)');
326
+ cmds[4].kind.should.equal('TransferObjects', 'command 4 must be TransferObjects');
327
+ cmds[5].kind.should.equal('MergeCoins', 'command 5 must be MergeCoins(GasCoin, [addrCoin])');
328
+ cmds.length.should.equal(6);
329
+ suiTx.suiTransaction.fundsInAddressBalance.should.equal(FUNDS_IN_ADDRESS_BALANCE);
330
+ // Transaction parser must correctly identify recipients despite the MoveCall preamble
331
+ const parsedRecipients = utils_1.default.getRecipients(suiTx.suiTransaction);
332
+ parsedRecipients.length.should.equal(testData.recipients.length);
333
+ parsedRecipients[0].address.should.equal(testData.recipients[0].address);
334
+ parsedRecipients[0].amount.should.equal(testData.recipients[0].amount);
335
+ const rawTx = tx.toBroadcastFormat();
336
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
337
+ // Round-trip: rebuilt transaction must be bit-for-bit identical
338
+ const rebuilder = factory.from(rawTx);
339
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
340
+ const rebuiltTx = await rebuilder.build();
341
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
342
+ });
343
+ it('should build Path 2b with a single recipient', async function () {
344
+ const SEND_AMOUNT = '1275170993710'; // realistic consolidation amount (~1275 SUI)
345
+ const ADDR_BAL = '1275177540910'; // fundsInAddressBalance > SEND_AMOUNT + gas budget
346
+ const gasDataNoPayment = {
347
+ ...testData.gasDataWithoutGasPayment,
348
+ payment: [],
349
+ };
350
+ const txBuilder = factory.getTransferBuilder();
351
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
352
+ txBuilder.sender(testData.sender.address);
353
+ txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
354
+ txBuilder.gasData(gasDataNoPayment);
355
+ txBuilder.fundsInAddressBalance(ADDR_BAL);
356
+ const tx = await txBuilder.build();
357
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
358
+ const suiTx = tx;
359
+ const cmds = suiTx.suiTransaction.tx.transactions;
360
+ // Command sequence for 1 recipient:
361
+ // 0: MoveCall(redeem_funds)
362
+ // 1: SplitCoins(addrCoin, [SEND_AMOUNT])
363
+ // 2: TransferObjects
364
+ // 3: MergeCoins(GasCoin, [addrCoin])
365
+ cmds[0].kind.should.equal('MoveCall');
366
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
367
+ cmds[1].kind.should.equal('SplitCoins');
368
+ cmds[2].kind.should.equal('TransferObjects');
369
+ cmds[3].kind.should.equal('MergeCoins', 'expected MergeCoins to consume 0-balance addrCoin');
370
+ cmds.length.should.equal(4);
371
+ const parsedRecipients = utils_1.default.getRecipients(suiTx.suiTransaction);
372
+ parsedRecipients.length.should.equal(1);
373
+ parsedRecipients[0].address.should.equal(testData.recipients[0].address);
374
+ parsedRecipients[0].amount.should.equal(SEND_AMOUNT);
375
+ const rawTx = tx.toBroadcastFormat();
376
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
377
+ const rebuilder = factory.from(rawTx);
378
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
379
+ const rebuiltTx = await rebuilder.build();
380
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
381
+ });
382
+ it('should build Path 2b with ValidDuring expiration (production consolidation scenario)', async function () {
383
+ // Mirrors the real on-chain consolidation that failed: address index 10, wallet
384
+ // 67fe3f15..., txid JDbnybotg3axfjtB53LrnV1YtvGLFBVG8o2Xz5xX1m6Z.
385
+ // The recover() code sets ValidDuring when coinObjectsBalance=0 and
386
+ // fundsInAddressBalance>0 (Case 2). This test verifies both the expiration survives
387
+ // serialization and the PTB uses Path 2b (not the broken SplitCoins(GasCoin) path).
388
+ const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
389
+ const SEND_AMOUNT = '1275170993710';
390
+ const ADDR_BAL = '1275177540910';
391
+ const gasDataNoPayment = {
392
+ ...testData.gasDataWithoutGasPayment,
393
+ payment: [],
394
+ };
395
+ const txBuilder = factory.getTransferBuilder();
396
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
397
+ txBuilder.sender(testData.sender.address);
398
+ txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
399
+ txBuilder.gasData(gasDataNoPayment);
400
+ txBuilder.fundsInAddressBalance(ADDR_BAL);
401
+ txBuilder.expiration({
402
+ ValidDuring: {
403
+ minEpoch: { Some: 1156 },
404
+ maxEpoch: { Some: 1157 },
405
+ minTimestamp: { None: null },
406
+ maxTimestamp: { None: null },
407
+ chain: GENESIS_CHAIN_ID,
408
+ nonce: 12345678,
409
+ },
410
+ });
411
+ const tx = await txBuilder.build();
412
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
413
+ const suiTx = tx;
414
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
415
+ // Must use Path 2b (MoveCall first), never SplitCoins(GasCoin) first
416
+ const cmds = suiTx.suiTransaction.tx.transactions;
417
+ cmds[0].kind.should.equal('MoveCall', 'Path 2b must start with MoveCall(redeem_funds), not SplitCoins(GasCoin)');
418
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
419
+ cmds[cmds.length - 1].kind.should.equal('MergeCoins', 'Path 2b must end with MergeCoins to destroy 0-balance addrCoin');
420
+ // ValidDuring expiration must survive BCS round-trip
421
+ const rawTx = tx.toBroadcastFormat();
422
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
423
+ const rebuilder = factory.from(rawTx);
424
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
425
+ const rebuiltTx = await rebuilder.build();
426
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
427
+ const expiration = rebuiltTx.toJson().expiration?.ValidDuring;
428
+ should_1.default.exist(expiration, 'ValidDuring expiration must survive round-trip');
429
+ Number(expiration.minEpoch.Some).should.equal(1156);
430
+ Number(expiration.maxEpoch.Some).should.equal(1157);
431
+ });
432
+ it('should build a self-pay transfer with coin objects + address balance (Path 2c)', async function () {
433
+ // Regression test for COINS-331: when both gasData.payment (coin objects) and
434
+ // fundsInAddressBalance are set, Sui does NOT automatically merge address balance into
435
+ // the gas coin. Path 2c must explicitly call redeem_funds + MergeCoins(gas, [addrCoin])
436
+ // before SplitCoins so that the gas coin holds the full spendable amount.
437
+ const txBuilder = factory.getTransferBuilder();
438
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
439
+ txBuilder.sender(testData.sender.address);
440
+ txBuilder.send(testData.recipients);
441
+ txBuilder.gasData(testData.gasData); // non-empty payment — triggers Path 2c
442
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
443
+ const tx = await txBuilder.build();
444
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
445
+ const suiTx = tx;
446
+ // Path 2c PTB command sequence (for 2 recipients):
447
+ // 0: MoveCall(redeem_funds) — materialize addrCoin from address balance
448
+ // 1: MergeCoins(gas, [addrCoin])— gas coin = coinObjects + addrBal (full spendable amount)
449
+ // 2: SplitCoins(gas) — split for recipient 0
450
+ // 3: TransferObjects — send to recipient 0
451
+ // 4: SplitCoins(gas) — split for recipient 1
452
+ // 5: TransferObjects — send to recipient 1
453
+ const programmableTx = suiTx.suiTransaction.tx;
454
+ const cmds = programmableTx.transactions;
455
+ cmds[0].kind.should.equal('MoveCall', 'command 0 must be MoveCall(redeem_funds)');
456
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
457
+ cmds[1].kind.should.equal('MergeCoins', 'command 1 must be MergeCoins(gas, [addrCoin])');
458
+ cmds[2].kind.should.equal('SplitCoins', 'command 2 must be SplitCoins(gas, [amount0])');
459
+ cmds[3].kind.should.equal('TransferObjects');
460
+ cmds[4].kind.should.equal('SplitCoins', 'command 4 must be SplitCoins(gas, [amount1])');
461
+ cmds[5].kind.should.equal('TransferObjects');
462
+ // fundsInAddressBalance must be persisted in the serialized transaction
463
+ suiTx.suiTransaction.fundsInAddressBalance.should.equal(FUNDS_IN_ADDRESS_BALANCE);
464
+ const rawTx = tx.toBroadcastFormat();
465
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
466
+ // Round-trip: rebuilt transaction must be bit-for-bit identical
467
+ const rebuilder = factory.from(rawTx);
468
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
469
+ const rebuiltTx = await rebuilder.build();
470
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
471
+ });
472
+ it('should build a sponsored transfer with coin objects + address balance', async function () {
473
+ const inputObjects = testData.generateObjects(2);
474
+ const sponsoredGasData = {
475
+ ...testData.gasData,
476
+ owner: testData.feePayer.address,
477
+ };
478
+ const txBuilder = factory.getTransferBuilder();
479
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
480
+ txBuilder.sender(testData.sender.address);
481
+ txBuilder.send(testData.recipients);
482
+ txBuilder.gasData(sponsoredGasData);
483
+ txBuilder.inputObjects(inputObjects);
484
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
485
+ const tx = await txBuilder.build();
486
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
487
+ const suiTx = tx;
488
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
489
+ // Sponsored path: MoveCall(redeem_funds) + MergeCoins + SplitCoins
490
+ const programmableTx = suiTx.suiTransaction.tx;
491
+ programmableTx.transactions[0].kind.should.equal('MoveCall');
492
+ programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
493
+ programmableTx.transactions[1].kind.should.equal('MergeCoins');
494
+ programmableTx.transactions[2].kind.should.equal('SplitCoins');
495
+ const rawTx = tx.toBroadcastFormat();
496
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
497
+ // Round-trip
498
+ const rebuilder = factory.from(rawTx);
499
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
500
+ const rebuiltTx = await rebuilder.build();
501
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
502
+ });
503
+ it('should build a sponsored transfer with address balance only (no coin inputObjects)', async function () {
504
+ const sponsoredGasData = {
505
+ ...testData.gasData,
506
+ owner: testData.feePayer.address,
507
+ };
508
+ const txBuilder = factory.getTransferBuilder();
509
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
510
+ txBuilder.sender(testData.sender.address);
511
+ txBuilder.send(testData.recipients);
512
+ txBuilder.gasData(sponsoredGasData);
513
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
514
+ const tx = await txBuilder.build();
515
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
516
+ // Path 1b: withdrawal → redeem_funds → SplitCoins(addrCoin) → TransferObjects
517
+ // Sponsor's gas coins remain in gasData.payment; tx.gas is NOT used for the transfer amount.
518
+ const suiTx = tx;
519
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
520
+ const programmableTx = suiTx.suiTransaction.tx;
521
+ programmableTx.transactions[0].kind.should.equal('MoveCall');
522
+ programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
523
+ programmableTx.transactions[1].kind.should.equal('SplitCoins');
524
+ const rawTx = tx.toBroadcastFormat();
525
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
526
+ // Round-trip: rebuild from raw
527
+ const rebuilder = factory.from(rawTx);
528
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
529
+ const rebuiltTx = await rebuilder.build();
530
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
531
+ });
532
+ it('should build Path 1b send-all: sponsored addr-balance-only, no change (MergeCoins consumes addrCoin)', async function () {
533
+ // Reproduces the real on-chain failure: UnusedValueWithoutDrop { result_idx: 0 }
534
+ // Occurs when redeem_funds returns addrCoin, SplitCoins drains it completely, and the
535
+ // 0-balance source coin is never consumed. Fix: MergeCoins(gas, [addrCoin]) at the end.
536
+ const SEND_AMOUNT = '1000000'; // 0.001 SUI — same as the failing tx
537
+ const sponsoredGasData = {
538
+ ...testData.gasData,
539
+ owner: testData.feePayer.address,
540
+ };
541
+ const txBuilder = factory.getTransferBuilder();
542
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
543
+ txBuilder.sender(testData.sender.address);
544
+ txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
545
+ txBuilder.gasData(sponsoredGasData);
546
+ txBuilder.fundsInAddressBalance(SEND_AMOUNT); // send-all: balance == recipient amount
547
+ const tx = await txBuilder.build();
548
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
549
+ const suiTx = tx;
550
+ const cmds = suiTx.suiTransaction.tx.transactions;
551
+ // Expected command sequence for Path 1b send-all:
552
+ // 0: MoveCall (redeem_funds) — withdraw addrCoin
553
+ // 1: SplitCoins(addrCoin) — split recipient amount off addrCoin
554
+ // 2: TransferObjects([split]) — send to recipient
555
+ // 3: MergeCoins(gas, [addrCoin]) — consume the now-zero-balance addrCoin
556
+ cmds[0].kind.should.equal('MoveCall');
557
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
558
+ cmds[1].kind.should.equal('SplitCoins');
559
+ cmds[2].kind.should.equal('TransferObjects');
560
+ cmds[3].kind.should.equal('MergeCoins', 'expected MergeCoins to consume 0-balance addrCoin after send-all');
561
+ // Recipient parsing must not be affected by the trailing MergeCoins
562
+ const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
563
+ recipients.length.should.equal(1);
564
+ recipients[0].address.should.equal(testData.recipients[0].address);
565
+ recipients[0].amount.should.equal(SEND_AMOUNT);
566
+ // Round-trip
567
+ const rawTx = tx.toBroadcastFormat();
568
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
569
+ const rebuilder = factory.from(rawTx);
570
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
571
+ const rebuiltTx = await rebuilder.build();
572
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
573
+ });
574
+ it('should build Path 1b with change: sponsored addr-balance-only, excess returned to sender', async function () {
575
+ // fundsInAddressBalance exceeds the total recipient amount → change must be returned to
576
+ // the sender as an extra TransferObjects([addrCoin], sender). The transaction parser must
577
+ // skip this change transfer and only report actual recipients.
578
+ const SEND_AMOUNT = '100'; // each of the two testData.recipients gets 100
579
+ const EXCESS = '9999900'; // fundsInAddressBalance = 10_000_000, total send = 200
580
+ const FUNDS_BALANCE = (Number(SEND_AMOUNT) * testData.recipients.length + Number(EXCESS)).toString();
581
+ const sponsoredGasData = {
582
+ ...testData.gasData,
583
+ owner: testData.feePayer.address,
584
+ };
585
+ const txBuilder = factory.getTransferBuilder();
586
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
587
+ txBuilder.sender(testData.sender.address);
588
+ txBuilder.send(testData.recipients); // 2 recipients × 100 MIST = 200 MIST total
589
+ txBuilder.gasData(sponsoredGasData);
590
+ txBuilder.fundsInAddressBalance(FUNDS_BALANCE); // 10_000_000 > 200 → has change
591
+ const tx = await txBuilder.build();
592
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
593
+ const suiTx = tx;
594
+ const cmds = suiTx.suiTransaction.tx.transactions;
595
+ // Expected sequence for Path 1b with change (2 recipients):
596
+ // 0: MoveCall (redeem_funds)
597
+ // 1: SplitCoins — recipient 0
598
+ // 2: TransferObjects — recipient 0
599
+ // 3: SplitCoins — recipient 1
600
+ // 4: TransferObjects — recipient 1
601
+ // 5: TransferObjects([addrCoin], sender) — change back to sender
602
+ cmds[0].kind.should.equal('MoveCall');
603
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
604
+ const lastCmd = cmds[cmds.length - 1];
605
+ lastCmd.kind.should.equal('TransferObjects', 'last command must be the change transfer');
606
+ // The last TransferObjects returns change to the *sender*, not a recipient
607
+ const changeAddrInput = suiTx.suiTransaction.tx.inputs[lastCmd.address.index];
608
+ const changeAddr = utils_1.default.getAddress(changeAddrInput);
609
+ changeAddr.should.equal(testData.sender.address, 'change must go back to sender');
610
+ // Parser must return only the actual recipients, not the change transfer
611
+ const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
612
+ recipients.length.should.equal(testData.recipients.length);
613
+ recipients[0].address.should.equal(testData.recipients[0].address);
614
+ recipients[0].amount.should.equal(SEND_AMOUNT);
615
+ recipients[1].address.should.equal(testData.recipients[1].address);
616
+ recipients[1].amount.should.equal(SEND_AMOUNT);
617
+ // Round-trip
618
+ const rawTx = tx.toBroadcastFormat();
619
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
620
+ const rebuilder = factory.from(rawTx);
621
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
622
+ const rebuiltTx = await rebuilder.build();
623
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
624
+ });
625
+ it('should build a sponsored tx gas paid from sponsor address balance (empty payment)', async function () {
626
+ const inputObjects = testData.generateObjects(1);
627
+ const sponsoredGasDataNoPayment = {
628
+ payment: [],
629
+ owner: testData.feePayer.address,
630
+ price: testData.gasData.price,
631
+ budget: testData.gasData.budget,
632
+ };
633
+ const txBuilder = factory.getTransferBuilder();
634
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
635
+ txBuilder.sender(testData.sender.address);
636
+ txBuilder.send(testData.recipients);
637
+ txBuilder.gasData(sponsoredGasDataNoPayment);
638
+ txBuilder.inputObjects(inputObjects);
639
+ const tx = await txBuilder.build();
640
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
641
+ const suiTx = tx;
642
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
643
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
644
+ // Sponsored path with coin objects, no address balance withdrawal
645
+ const programmableTx = suiTx.suiTransaction.tx;
646
+ programmableTx.transactions[0].kind.should.equal('SplitCoins');
647
+ const rawTx = tx.toBroadcastFormat();
648
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
649
+ });
650
+ it('should round-trip a self-pay transfer with Epoch expiration via fromBytes', async function () {
651
+ // Regression test for the BigInt round-trip bug:
652
+ // BCS.U64 deserializes u64 as BigInt, but the previous superstruct schema used integer()
653
+ // which rejected BigInt, causing fromBytes() to throw a StructError at "expiration".
654
+ // StringEncodedBigint now accepts string | number | bigint, fixing the round-trip.
655
+ const gasDataNoPayment = {
656
+ ...testData.gasDataWithoutGasPayment,
657
+ payment: [],
658
+ };
659
+ const txBuilder = factory.getTransferBuilder();
660
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
661
+ txBuilder.sender(testData.sender.address);
662
+ txBuilder.send(testData.recipients);
663
+ txBuilder.gasData(gasDataNoPayment);
664
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
665
+ txBuilder.expiration({ Epoch: 324 }); // number input
666
+ const tx = await txBuilder.build();
667
+ const rawTx = tx.toBroadcastFormat();
668
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
669
+ // fromBytes must not throw StructError — this was the failing case before the fix
670
+ should_1.default.doesNotThrow(() => {
671
+ const rebuilder = factory.from(rawTx);
672
+ should_1.default.exist(rebuilder);
673
+ });
674
+ // Full round-trip: rebuilt tx must serialize identically
675
+ const rebuilder = factory.from(rawTx);
676
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
677
+ const rebuiltTx = await rebuilder.build();
678
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
679
+ // Epoch value must survive the round-trip regardless of BigInt/number representation
680
+ const rebuiltJson = rebuiltTx.toJson();
681
+ const epochVal = rebuiltJson.expiration?.Epoch;
682
+ should_1.default.exist(epochVal);
683
+ Number(epochVal).should.equal(324);
684
+ });
685
+ it('should round-trip a self-pay transfer with ValidDuring expiration via fromBytes', async function () {
686
+ // Verifies the full 6-field ValidDuringExpiration BCS schema:
687
+ // minEpoch/maxEpoch as Option<u64>, minTimestamp/maxTimestamp as Option<u64> (None),
688
+ // chain as 32-byte Base58 ObjectDigest, nonce as u32.
689
+ // Uses a real mainnet genesis checkpoint digest (32 bytes, Base58).
690
+ const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
691
+ const FUNDS_IN_ADDRESS_BALANCE = '5000000000';
692
+ const gasDataNoPayment = {
693
+ ...testData.gasDataWithoutGasPayment,
694
+ payment: [],
695
+ };
696
+ const txBuilder = factory.getTransferBuilder();
697
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
698
+ txBuilder.sender(testData.sender.address);
699
+ txBuilder.send(testData.recipients);
700
+ txBuilder.gasData(gasDataNoPayment);
701
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
702
+ txBuilder.expiration({
703
+ ValidDuring: {
704
+ minEpoch: { Some: 500 },
705
+ maxEpoch: { Some: 501 },
706
+ minTimestamp: { None: null },
707
+ maxTimestamp: { None: null },
708
+ chain: GENESIS_CHAIN_ID,
709
+ nonce: 0xdeadbeef,
710
+ },
711
+ });
712
+ const tx = await txBuilder.build();
713
+ const rawTx = tx.toBroadcastFormat();
714
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
715
+ // fromBytes must not throw — ValidDuring fields must survive deserialization
716
+ const rebuilder = factory.from(rawTx);
717
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
718
+ const rebuiltTx = await rebuilder.build();
719
+ // BCS round-trip: serialized bytes must be identical
720
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
721
+ // All ValidDuring fields must survive the round-trip
722
+ const expiration = rebuiltTx.toJson().expiration?.ValidDuring;
723
+ should_1.default.exist(expiration);
724
+ Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
725
+ Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
726
+ expiration.chain.should.equal(GENESIS_CHAIN_ID);
727
+ Number(expiration.nonce).should.equal(0xdeadbeef);
728
+ });
729
+ });
730
+ describe('large amounts exceeding Number.MAX_SAFE_INTEGER', () => {
731
+ // Number.MAX_SAFE_INTEGER = 9007199254740991.
732
+ // Using Number() for amounts above this silently rounds to the nearest representable float.
733
+ // 9007199254740993 (MAX_SAFE_INTEGER + 2) is NOT exactly representable as a JS Number — it
734
+ // rounds down to 9007199254740992 — so BCS would encode the wrong value.
735
+ // BigInt preserves the exact value and is the correct type for BCS u64 encoding.
736
+ //
737
+ // The core check in each test is tx.outputs[0].value === LARGE_AMOUNT: this reads from the
738
+ // in-memory builder state (a BigInt, not BCS-decoded), so it accurately distinguishes
739
+ // BigInt() vs Number() encoding at build time.
740
+ const LARGE_AMOUNT = '9007199254740993'; // MAX_SAFE_INTEGER + 2
741
+ it('should build a self-pay transfer (Path 2) with amount > Number.MAX_SAFE_INTEGER and encode it precisely', async function () {
742
+ const txBuilder = factory.getTransferBuilder();
743
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
744
+ txBuilder.sender(testData.sender.address);
745
+ txBuilder.send([{ address: testData.recipients[0].address, amount: LARGE_AMOUNT }]);
746
+ txBuilder.gasData(testData.gasData);
747
+ const tx = await txBuilder.build();
748
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
749
+ // With Number() the amount would be silently rounded to 9007199254740992 — BigInt preserves the exact value
750
+ tx.outputs.length.should.equal(1);
751
+ tx.outputs[0].value.should.equal(LARGE_AMOUNT);
752
+ const rawTx = tx.toBroadcastFormat();
753
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
754
+ });
755
+ it('should build a sponsored transfer with coin objects (Path 1a) with amount > Number.MAX_SAFE_INTEGER and encode it precisely', async function () {
756
+ const inputObjects = testData.generateObjects(2);
757
+ const sponsoredGasData = {
758
+ ...testData.gasData,
759
+ owner: testData.feePayer.address,
760
+ };
761
+ const txBuilder = factory.getTransferBuilder();
762
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
763
+ txBuilder.sender(testData.sender.address);
764
+ txBuilder.send([{ address: testData.recipients[0].address, amount: LARGE_AMOUNT }]);
765
+ txBuilder.gasData(sponsoredGasData);
766
+ txBuilder.inputObjects(inputObjects);
767
+ const tx = await txBuilder.build();
768
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
769
+ // With Number() the amount would be silently rounded to 9007199254740992 — BigInt preserves the exact value
770
+ tx.outputs.length.should.equal(1);
771
+ tx.outputs[0].value.should.equal(LARGE_AMOUNT);
772
+ const rawTx = tx.toBroadcastFormat();
773
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
774
+ });
775
+ it('should build a sponsored addr-balance-only transfer (Path 1b) with amount > Number.MAX_SAFE_INTEGER and round-trip correctly', async function () {
776
+ const sponsoredGasData = {
777
+ ...testData.gasData,
778
+ owner: testData.feePayer.address,
779
+ };
780
+ const txBuilder = factory.getTransferBuilder();
781
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
782
+ txBuilder.sender(testData.sender.address);
783
+ txBuilder.send([{ address: testData.recipients[0].address, amount: LARGE_AMOUNT }]);
784
+ txBuilder.gasData(sponsoredGasData);
785
+ txBuilder.fundsInAddressBalance(LARGE_AMOUNT);
786
+ const tx = await txBuilder.build();
787
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
788
+ // With Number() the amount would be silently rounded to 9007199254740992 — BigInt preserves the exact value
789
+ tx.outputs.length.should.equal(1);
790
+ tx.outputs[0].value.should.equal(LARGE_AMOUNT);
791
+ const rawTx = tx.toBroadcastFormat();
792
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
793
+ // Full round-trip: rebuilding from BCS bytes must produce identical bytes
794
+ const rebuilder = factory.from(rawTx);
795
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
796
+ const rebuiltTx = await rebuilder.build();
797
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
798
+ const recipients = utils_1.default.getRecipients(rebuiltTx.suiTransaction);
799
+ recipients[0].amount.should.equal(LARGE_AMOUNT);
800
+ });
801
+ });
802
+ describe('prod address balance consolidation (CECHO-1210)', () => {
803
+ // Failed prod consolidation 6a19cb8bcd4751dbd891a722ee04e552 (txRequest ee5d60d7-fa53-4fa4-adcf-26435c9317bf).
804
+ // Broadcast failed with stale coin object version; the amount must still encode losslessly.
805
+ const CONSOLIDATION_AMOUNT = '18536797842613700'; // ~18.5M SUI in MIST (sendAccounting.amountString)
806
+ const CONSOLIDATION_SENDER = '0x46a53e2712561f4e0d8272bd27a396b6bf9325f92f34b949041b8783d57469dd';
807
+ const CONSOLIDATION_RECIPIENT = '0x3da2cb67c887c9a03d1052d486733a77105824f7413fc3cbbe3641d4b67af102';
808
+ it('should accept the prod consolidation amount in isValidAmount', function () {
809
+ utils_1.default.isValidAmount(CONSOLIDATION_AMOUNT).should.be.true();
810
+ Number.isSafeInteger(Number(CONSOLIDATION_AMOUNT)).should.be.false();
811
+ });
812
+ it('should build address-balance-only consolidation with exact prod amount (Path 2, empty payment)', async function () {
813
+ const gasDataNoPayment = {
814
+ ...testData.gasDataWithoutGasPayment,
815
+ payment: [],
816
+ };
817
+ const txBuilder = factory.getTransferBuilder();
818
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
819
+ txBuilder.sender(CONSOLIDATION_SENDER);
820
+ txBuilder.send([{ address: CONSOLIDATION_RECIPIENT, amount: CONSOLIDATION_AMOUNT }]);
821
+ txBuilder.gasData(gasDataNoPayment);
822
+ txBuilder.fundsInAddressBalance(CONSOLIDATION_AMOUNT);
823
+ const tx = await txBuilder.build();
824
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
825
+ tx.outputs.length.should.equal(1);
826
+ tx.outputs[0].should.deepEqual({
827
+ address: CONSOLIDATION_RECIPIENT,
828
+ value: CONSOLIDATION_AMOUNT,
829
+ coin: 'tsui',
830
+ });
831
+ tx.inputs.length.should.equal(1);
832
+ tx.inputs[0].value.should.equal(CONSOLIDATION_AMOUNT);
833
+ const rawTx = tx.toBroadcastFormat();
834
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
835
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
836
+ const recipients = utils_1.default.getRecipients(deserialized);
837
+ recipients.length.should.equal(1);
838
+ recipients[0].address.should.equal(CONSOLIDATION_RECIPIENT);
839
+ recipients[0].amount.should.equal(CONSOLIDATION_AMOUNT);
840
+ });
841
+ it('should build address-balance consolidation with coin objects and exact prod amount (Path 2)', async function () {
842
+ // Prod failure referenced stale gas/coin object versions between sign and broadcast.
843
+ // Builder must still encode the full consolidation amount in SplitCoins.
844
+ const txBuilder = factory.getTransferBuilder();
845
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
846
+ txBuilder.sender(CONSOLIDATION_SENDER);
847
+ txBuilder.send([{ address: CONSOLIDATION_RECIPIENT, amount: CONSOLIDATION_AMOUNT }]);
848
+ txBuilder.gasData({ ...testData.gasData, owner: CONSOLIDATION_SENDER });
849
+ txBuilder.fundsInAddressBalance(CONSOLIDATION_AMOUNT);
850
+ const tx = await txBuilder.build();
851
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
852
+ tx.outputs[0].value.should.equal(CONSOLIDATION_AMOUNT);
853
+ tx.inputs[0].value.should.equal(CONSOLIDATION_AMOUNT);
854
+ const rawTx = tx.toBroadcastFormat();
855
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
856
+ const rebuilder = factory.from(rawTx);
857
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
858
+ const rebuiltTx = await rebuilder.build();
859
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
860
+ const recipients = utils_1.default.getRecipients(rebuiltTx.suiTransaction);
861
+ recipients[0].address.should.equal(CONSOLIDATION_RECIPIENT);
862
+ recipients[0].amount.should.equal(CONSOLIDATION_AMOUNT);
863
+ });
864
+ });
865
+ describe('BalanceWithdrawal BCS encoding (FundsWithdrawal format)', () => {
866
+ const AMOUNT = '100000000'; // 0.1 SUI in MIST
867
+ const sponsoredGasData = {
868
+ ...testData.gasData,
869
+ owner: testData.feePayer.address,
870
+ };
871
+ async function buildSponsoredTxWithAddressBalance() {
872
+ const txBuilder = factory.getTransferBuilder();
873
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
874
+ txBuilder.sender(testData.sender.address);
875
+ txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
876
+ txBuilder.gasData(sponsoredGasData);
877
+ txBuilder.fundsInAddressBalance(AMOUNT);
878
+ return txBuilder.build();
879
+ }
880
+ it('should encode BalanceWithdrawal input with FundsWithdrawal structure (reservation/typeArg/withdrawFrom)', async function () {
881
+ const tx = await buildSponsoredTxWithAddressBalance();
882
+ const suiTx = tx;
883
+ const inputs = suiTx.suiTransaction.tx.inputs;
884
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
885
+ should_1.default.exist(bwInput, 'BalanceWithdrawal input must be present');
886
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
887
+ should_1.default.exist(bw.reservation, 'reservation field must exist');
888
+ should_1.default.exist(bw.reservation.MaxAmountU64, 'reservation.MaxAmountU64 must exist');
889
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
890
+ should_1.default.exist(bw.typeArg, 'typeArg field must exist');
891
+ should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must exist');
892
+ should_1.default.exist(bw.withdrawFrom, 'withdrawFrom field must exist');
893
+ should_1.default.exist(bw.withdrawFrom.Sender !== undefined || bw.withdrawFrom.Sponsor !== undefined, 'withdrawFrom must be Sender or Sponsor');
894
+ // Old format fields must NOT exist directly on bw
895
+ should_1.default.not.exist(bw.amount, 'old "amount" field must not exist on BalanceWithdrawal');
896
+ should_1.default.not.exist(bw.type_, 'old "type_" field must not exist on BalanceWithdrawal');
897
+ });
898
+ it('should produce BCS bytes that decode back to FundsWithdrawal with correct amount', async function () {
899
+ const tx = await buildSponsoredTxWithAddressBalance();
900
+ const rawTx = tx.toBroadcastFormat();
901
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
902
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
903
+ const inputs = deserialized.tx.inputs;
904
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
905
+ should_1.default.exist(bwInput, 'BalanceWithdrawal must be present in deserialized inputs');
906
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
907
+ // FundsWithdrawal structure (not old {amount, type_})
908
+ should_1.default.exist(bw.reservation, 'reservation must survive BCS round-trip');
909
+ should_1.default.exist(bw.reservation.MaxAmountU64, 'MaxAmountU64 must survive BCS round-trip');
910
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
911
+ should_1.default.exist(bw.typeArg, 'typeArg must survive BCS round-trip');
912
+ should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must survive BCS round-trip');
913
+ should_1.default.exist(bw.withdrawFrom, 'withdrawFrom must survive BCS round-trip');
914
+ });
915
+ it('should serialize toJson() without a BigInt replacer (no TypeError)', async function () {
916
+ const tx = await buildSponsoredTxWithAddressBalance();
917
+ should_1.default.doesNotThrow(() => JSON.stringify(tx.toJson()), 'JSON.stringify(tx.toJson()) must not throw — BalanceWithdrawal amount must not be stored as BigInt');
918
+ });
919
+ it('should preserve fundsInAddressBalance amount through full round-trip', async function () {
920
+ const tx = await buildSponsoredTxWithAddressBalance();
921
+ const rawTx = tx.toBroadcastFormat();
922
+ const rebuilder = factory.from(rawTx);
923
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
924
+ const rebuiltTx = await rebuilder.build();
925
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
926
+ const suiTx = rebuiltTx;
927
+ const inputs = suiTx.suiTransaction.tx.inputs;
928
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
929
+ should_1.default.exist(bwInput);
930
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
931
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
932
+ });
933
+ it('should build Path 2b: self-pay, empty payment — uses withdrawal+redeem_funds instead of SplitCoins(GasCoin)', async function () {
934
+ // With gasData.payment=[] the runtime exposes only the gas-budget amount via GasCoin for
935
+ // PTB SplitCoins operations. SplitCoins(GasCoin, [large_amount]) always fails with
936
+ // InsufficientCoinBalance (confirmed by production failures JDbnybotg3ax..., ATUbeLX3...).
937
+ // Path 2b fixes this by withdrawing from the address accumulator via redeem_funds,
938
+ // splitting from that coin object, and merging the 0-balance remainder into GasCoin.
939
+ const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
940
+ const txBuilder = factory.getTransferBuilder();
941
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
942
+ txBuilder.sender(testData.sender.address);
943
+ txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
944
+ txBuilder.gasData(selfPayNoPayment);
945
+ txBuilder.fundsInAddressBalance(AMOUNT);
946
+ const tx = await txBuilder.build();
947
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
948
+ const suiTx = tx;
949
+ // Gas owner must equal sender (self-pay)
950
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
951
+ // Payment must be empty — gas funded from address balance by the runtime
952
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
953
+ // Path 2b: BalanceWithdrawal input MUST be present (withdrawal+redeem_funds approach)
954
+ const inputs = suiTx.suiTransaction.tx.inputs;
955
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
956
+ should_1.default.exist(bwInput, 'Path 2b: BalanceWithdrawal input must be present');
957
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
958
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
959
+ // First command must be MoveCall(redeem_funds), NOT SplitCoins(GasCoin)
960
+ const commands = suiTx.suiTransaction.tx.transactions;
961
+ commands[0].kind.should.equal('MoveCall');
962
+ commands[0].target.should.equal('0x2::coin::redeem_funds');
963
+ // Followed by: SplitCoins(addrCoin), TransferObjects, MergeCoins(GasCoin, addrCoin)
964
+ commands[1].kind.should.equal('SplitCoins');
965
+ commands[2].kind.should.equal('TransferObjects');
966
+ commands[3].kind.should.equal('MergeCoins');
967
+ const rawTx = tx.toBroadcastFormat();
968
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
969
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
970
+ deserialized.sender.should.equal(testData.sender.address);
971
+ deserialized.gasData.owner.should.equal(testData.sender.address);
972
+ deserialized.gasData.payment.length.should.equal(0);
973
+ // BalanceWithdrawal must survive BCS round-trip
974
+ const decodedInputs = deserialized.tx.inputs;
975
+ const decodedBwInput = decodedInputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
976
+ should_1.default.exist(decodedBwInput, 'BalanceWithdrawal must survive BCS round-trip for Path 2b');
977
+ const rebuilder = factory.from(rawTx);
978
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
979
+ const rebuiltTx = await rebuilder.build();
980
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
981
+ });
982
+ it('should build Path 2b with ValidDuring expiration (self-pay, empty payment)', async function () {
983
+ // Path 2b with ValidDuring expiration — required when gasData.payment=[] to prevent
984
+ // replay attacks. Uses withdrawal+redeem_funds to materialise transfer amount from the
985
+ // address accumulator, NOT SplitCoins(GasCoin) which fails with InsufficientCoinBalance.
986
+ const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
987
+ const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
988
+ const txBuilder = factory.getTransferBuilder();
989
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
990
+ txBuilder.sender(testData.sender.address);
991
+ txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
992
+ txBuilder.gasData(selfPayNoPayment);
993
+ txBuilder.fundsInAddressBalance(AMOUNT);
994
+ txBuilder.expiration({
995
+ ValidDuring: {
996
+ minEpoch: { Some: 500 },
997
+ maxEpoch: { Some: 501 },
998
+ minTimestamp: { None: null },
999
+ maxTimestamp: { None: null },
1000
+ chain: GENESIS_CHAIN_ID,
1001
+ nonce: 0xdeadbeef,
1002
+ },
1003
+ });
1004
+ const tx = await txBuilder.build();
1005
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
1006
+ const suiTx = tx;
1007
+ // Self-pay: owner === sender, payment empty
1008
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
1009
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
1010
+ // Path 2b: BalanceWithdrawal input MUST be present
1011
+ const inputs = suiTx.suiTransaction.tx.inputs;
1012
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
1013
+ should_1.default.exist(bwInput, 'Path 2b: BalanceWithdrawal input must be present');
1014
+ // First command: MoveCall(redeem_funds), NOT SplitCoins(GasCoin)
1015
+ const commands = suiTx.suiTransaction.tx.transactions;
1016
+ commands[0].kind.should.equal('MoveCall');
1017
+ commands[0].target.should.equal('0x2::coin::redeem_funds');
1018
+ const rawTx = tx.toBroadcastFormat();
1019
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
1020
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
1021
+ deserialized.sender.should.equal(testData.sender.address);
1022
+ deserialized.gasData.payment.length.should.equal(0);
1023
+ const expiration = deserialized.expiration?.ValidDuring;
1024
+ should_1.default.exist(expiration, 'ValidDuring expiration must survive BCS round-trip');
1025
+ Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
1026
+ Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
1027
+ expiration.chain.should.equal(GENESIS_CHAIN_ID);
1028
+ Number(expiration.nonce).should.equal(0xdeadbeef);
1029
+ // BalanceWithdrawal must survive BCS round-trip
1030
+ const decodedInputs = deserialized.tx.inputs;
1031
+ const decodedBwInput = decodedInputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
1032
+ should_1.default.exist(decodedBwInput, 'BalanceWithdrawal must survive BCS round-trip for Path 2b');
1033
+ const rebuilder = factory.from(rawTx);
1034
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
1035
+ const rebuiltTx = await rebuilder.build();
1036
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
1037
+ });
1038
+ it('should build and correctly decode a MoveCall to 0x2::coin::redeem_funds with BalanceWithdrawal arg', async function () {
1039
+ const tx = await buildSponsoredTxWithAddressBalance();
1040
+ const suiTx = tx;
1041
+ const commands = suiTx.suiTransaction.tx.transactions;
1042
+ commands[0].kind.should.equal('MoveCall');
1043
+ commands[0].target.should.equal('0x2::coin::redeem_funds');
1044
+ commands[0].typeArguments[0].should.equal('0x2::sui::SUI');
1045
+ // The argument to redeem_funds must reference the BalanceWithdrawal input (index 0)
1046
+ const arg = commands[0].arguments[0];
1047
+ arg.kind.should.equal('Input');
1048
+ arg.index.should.equal(0);
1049
+ arg.type.should.equal('object');
1050
+ const rawTx = tx.toBroadcastFormat();
1051
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
1052
+ });
1053
+ });
1054
+ });
1055
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJCdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci90cmFuc2ZlckJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsNERBQXlEO0FBQ3pELDhEQUFnRDtBQUNoRCxvREFBNEI7QUFDNUIsbURBQXVEO0FBQ3ZELG1FQUEyQztBQUMzQyw4REFBNkU7QUFDN0Usa0RBQTZGO0FBQzdGLDBEQUErRTtBQUUvRSxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO0lBQ3BDLE1BQU0sT0FBTyxHQUFHLElBQUEscUNBQWlCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFFMUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUU7UUFDdkIsRUFBRSxDQUFDLDRCQUE0QixFQUFFLEtBQUs7WUFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDL0MsU0FBUyxDQUFDLElBQUksQ0FBQywwQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1QyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEMsTUFBTSxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSwwQkFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNDLEVBQXNELENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFRLENB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QUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUUzRCxvRkFBb0Y7WUFDcEYsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNyQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDL0IsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFCLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUVoQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUNyQyxnQkFBTSxDQUFDLEtBQUssQ0FBQyxlQUFLLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgZ2V0QnVpbGRlckZhY3RvcnkgfSBmcm9tICcuLi9nZXRCdWlsZGVyRmFjdG9yeSc7XG5pbXBvcnQgKiBhcyB0ZXN0RGF0YSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvc3VpJztcbmltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uVHlwZSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB1dGlscyBmcm9tICcuLi8uLi8uLi9zcmMvbGliL3V0aWxzJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIGFzIFN1aVRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBTdWlUcmFuc2FjdGlvblR5cGUsIFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24gfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL2lmYWNlJztcbmltcG9ydCB7IE1BWF9DT01NQU5EX0FSR1MsIE1BWF9HQVNfT0JKRUNUUyB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWIvY29uc3RhbnRzJztcblxuZGVzY3JpYmUoJ1N1aSBUcmFuc2ZlciBCdWlsZGVyJywgKCkgPT4ge1xuICBjb25zdCBmYWN0b3J5ID0gZ2V0QnVpbGRlckZhY3RvcnkoJ3RzdWknKTtcblxuICBkZXNjcmliZSgnU3VjY2VlZCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgdHJhbnNmZXIgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YSh0ZXN0RGF0YS5nYXNEYXRhKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgKHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+KS5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQhLnNob3VsZC5kZWVwRXF1YWwoXG4gICAgICAgIHRlc3REYXRhLmNvaW5zR2FzUGF5bWVudFxuICAgICAgKTtcblxuICAgICAgdHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogKHRlc3REYXRhLkFNT1VOVCAqIDIpLnRvU3RyaW5nKCksXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgdHgub3V0cHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogdGVzdERhdGEucmVjaXBpZW50c1swXS5hbW91bnQsXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0c1sxXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1sxXS5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogdGVzdERhdGEucmVjaXBpZW50c1sxXS5hbW91bnQsXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgc2hvdWxkLmVxdWFsKHJhd1R4LCB0ZXN0RGF0YS5UUkFOU0ZFUik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHRyYW5zZmVyIHR4IHdpdGggaW5wdXRPYmplY3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW5wdXRPYmplY3RzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgb2JqZWN0SWQ6ICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4JyxcbiAgICAgICAgICB2ZXJzaW9uOiAxMDAsXG4gICAgICAgICAgZGlnZXN0OiAnMkI4WEtRSjdtZnhRUFVXcUpKQUdqekJBeml2a1dLcTJjRWEzVzhMTHoxeUInLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgb2JqZWN0SWQ6ICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyJyxcbiAgICAgICAgICB2ZXJzaW9uOiAyMDAsXG4gICAgICAgICAgZGlnZXN0OiAnRG9Kd1h1ejlvVTVZNXY1dkJSaVRnaXNWVFF1WlFMbUhaV2VxSnp6RDVRVUUnLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgLy8gQ3JlYXRlIGdhcyBkYXRhIHdpdGggZGlmZmVyZW50IG93bmVyIChzcG9uc29yKVxuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsIC8vIERpZmZlcmVudCBmcm9tIHNlbmRlclxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTsgLy8gU2VuZGVyXG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpOyAvLyBHYXMgcGFpZCBieSBzcG9uc29yXG4gICAgICB0eEJ1aWxkZXIuaW5wdXRPYmplY3RzKGlucHV0T2JqZWN0cyk7IC8vIFJlcXVpcmVkIGZvciBzcG9uc29yZWQgdHhcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG5cbiAgICAgIC8vIFZlcmlmeSB0cmFuc2FjdGlvbiBzdHJ1Y3R1cmUgZm9yIHNwb25zb3JlZCB0cmFuc2FjdGlvblxuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9ucy5sZW5ndGguc2hvdWxkLmJlLmdyZWF0ZXJUaGFuKDApO1xuXG4gICAgICAvLyBWZXJpZnkgc3BvbnNvcmVkIHRyYW5zYWN0aW9uIGNoYXJhY3RlcmlzdGljc1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uc2VuZGVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzKTtcblxuICAgICAgLy8gU2hvdWxkIGhhdmUgdHJhbnNhY3Rpb25zIGZvciBtZXJnaW5nL3NwbGl0dGluZyBhbmQgdHJhbnNmZXJyaW5nIHdoZW4gdXNpbmcgaW5wdXRPYmplY3RzXG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbigwKTtcblxuICAgICAgLy8gVmVyaWZ5IHdlIGhhdmUgdHJhbnNmZXIgb3BlcmF0aW9ucyAodGhlIGV4YWN0IHN0cnVjdHVyZSB2YXJpZXMgd2l0aCBBUEkgdmVyc2lvbnMpXG4gICAgICBzaG91bGQuZXhpc3QocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zKTtcblxuICAgICAgLy8gVmVyaWZ5IGlucHV0T2JqZWN0cyBhcmUgbm90IHVzZWQgaW4gZ2FzIHBheW1lbnQgKHRoZXkncmUgc2VwYXJhdGUpXG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQuc2hvdWxkLm5vdC5jb250YWluRGVlcChpbnB1dE9iamVjdHMpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXhpc3QocmF3VHgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR5cGVvZiByYXdUeCwgJ3N0cmluZycpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwbGl0IGNvaW4gdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgY29uc3QgYW1vdW50ID0gMTAwMDAwMDAwMDtcbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBuZXcgQXJyYXkoMTAwKS5maWxsKHsgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsIGFtb3VudDogYW1vdW50LnRvU3RyaW5nKCkgfSk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChyZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmdhc0RhdGEpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICAodHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj4pLnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudCEuc2hvdWxkLmRlZXBFcXVhbChcbiAgICAgICAgdGVzdERhdGEuY29pbnNHYXNQYXltZW50XG4gICAgICApO1xuXG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgIHZhbHVlOiAoYW1vdW50ICogMTAwKS50b1N0cmluZygpLFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxMDApO1xuICAgICAgdHgub3V0cHV0cy5mb3JFYWNoKChvdXRwdXQpID0+XG4gICAgICAgIG91dHB1dC5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyxcbiAgICAgICAgICB2YWx1ZTogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcGxpdCBjb2luIHR4IHdpdGggbW9yZSB0aGFuIDI1NSBpbnB1dCBvYmplY3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYW1vdW50ID0gMTAwMDAwMDAwMDtcbiAgICAgIGNvbnN0IG51bWJlck9mUmVjaXBpZW50cyA9IDEwO1xuICAgICAgY29uc3QgbnVtYmVyT2ZQYXltZW50T2JqZWN0cyA9IDEwMDA7XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG5cbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSBuZXcgQXJyYXkobnVtYmVyT2ZSZWNpcGllbnRzKS5maWxsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogYW1vdW50LnRvU3RyaW5nKCksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZ2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgcGF5bWVudDogdGVzdERhdGEuZ2VuZXJhdGVPYmplY3RzKG51bWJlck9mUGF5bWVudE9iamVjdHMpLFxuICAgICAgfTtcblxuICAgICAgdHhCdWlsZGVyLnNlbmQocmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIGFzc2VydCh0eCBpbnN0YW5jZW9mIFN1aVRyYW5zYWN0aW9uKTtcbiAgICAgIHR4LnR5cGUuc2hvdWxkLmVxdWFsKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IChhbW91bnQgKiAxMCkudG9TdHJpbmcoKSxcbiAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgfSk7XG4gICAgICB0eC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMTApO1xuICAgICAgdHgub3V0cHV0cy5mb3JFYWNoKChvdXRwdXQpID0+XG4gICAgICAgIG91dHB1dC5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgICAgdmFsdWU6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICAgIHR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKGdhc0RhdGEub3duZXIpO1xuICAgICAgdHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wcmljZS5zaG91bGQuZXF1YWwoZ2FzRGF0YS5wcmljZSk7XG4gICAgICB0eC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLmJ1ZGdldC5zaG91bGQuZXF1YWwoZ2FzRGF0YS5idWRnZXQpO1xuICAgICAgdHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoTUFYX0dBU19PQkpFQ1RTIC0gMSk7XG5cbiAgICAgIGNvbnN0IHByb2dyYW1tYWJsZVR4ID0gdHguc3VpVHJhbnNhY3Rpb24udHg7XG5cbiAgICAgIC8vIHRvdGFsIG9iamVjdHMgLSBvYmplY3RzIHNlbnQgYXMgZ2FzIHBheW1lbnQgKyBuby4gb2YgcmVjaXBpZW50IGFtb3VudHMocHVyZSlcbiAgICAgIC8vICsgbm8uIG9mIHVuaXF1ZSByZWNpcGllbnQgYWRkcmVzc2VzKGRlLWR1cGVkIG9iamVjdHMpXG4gICAgICBwcm9ncmFtbWFibGVUeC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbChcbiAgICAgICAgbnVtYmVyT2ZQYXltZW50T2JqZWN0cyAtIChNQVhfR0FTX09CSkVDVFMgLSAxKSArIG51bWJlck9mUmVjaXBpZW50cyArIDFcbiAgICAgICk7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnKTtcbiAgICAgIHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXS5zb3VyY2VzLmxlbmd0aC5zaG91bGQuZXF1YWwoTUFYX0NPTU1BTkRfQVJHUyAtIDEpO1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJyk7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMV0uc291cmNlcy5sZW5ndGguc2hvdWxkLmVxdWFsKFxuICAgICAgICBudW1iZXJPZlBheW1lbnRPYmplY3RzIC0gKE1BWF9DT01NQU5EX0FSR1MgLSAxKSAtIChNQVhfR0FTX09CSkVDVFMgLSAxKVxuICAgICAgKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgICAgcmVidWlsdFR4LnRvSnNvbigpLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKG51bWJlck9mUGF5bWVudE9iamVjdHMpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRmFpbCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGZhaWwgZm9yIGludmFsaWQgc2VuZGVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5zZW5kZXIoJ3JhbmRvbVN0cmluZycpKS50aHJvd0Vycm9yKCdJbnZhbGlkIG9yIG1pc3Npbmcgc2VuZGVyLCBnb3Q6IHJhbmRvbVN0cmluZycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIHBheVR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5zZW5kKFt0ZXN0RGF0YS5pbnZhbGlkUmVjaXBpZW50c1swXV0pKS50aHJvd0Vycm9yKFxuICAgICAgICAnSW52YWxpZCBvciBtaXNzaW5nIGFkZHJlc3MsIGdvdDogcmFuZG9tU3RyaW5nJ1xuICAgICAgKTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLnNlbmQoW3Rlc3REYXRhLmludmFsaWRSZWNpcGllbnRzWzFdXSkpLnRocm93RXJyb3IoJ0ludmFsaWQgcmVjaXBpZW50IGFtb3VudCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIGdhc0RhdGEnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLmdhc0RhdGEodGVzdERhdGEuaW52YWxpZEdhc093bmVyKSkudGhyb3dFcnJvcihcbiAgICAgICAgYEludmFsaWQgZ2FzIGFkZHJlc3MgJHt0ZXN0RGF0YS5pbnZhbGlkR2FzT3duZXIub3duZXJ9YFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBnYXNCdWRnZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLmdhc0RhdGEodGVzdERhdGEuaW52YWxpZEdhc0J1ZGdldCkpLnRocm93RXJyb3IoJ0ludmFsaWQgZ2FzIGJ1ZGdldCAtMScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIGdhc1BheW1lbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIGNvbnN0IGludmFsaWRHYXNQYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBvYmplY3RJZDogJycsXG4gICAgICAgICAgICB2ZXJzaW9uOiAtMSxcbiAgICAgICAgICAgIGRpZ2VzdDogJycsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5nYXNEYXRhKGludmFsaWRHYXNQYXltZW50KSkudGhyb3dFcnJvcignSW52YWxpZCBwYXltZW50LCBpbnZhbGlkIG9yIG1pc3NpbmcgdmVyc2lvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIGlucHV0T2JqZWN0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgY29uc3QgaW52YWxpZElucHV0T2JqZWN0cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnJyxcbiAgICAgICAgICB2ZXJzaW9uOiAtMSxcbiAgICAgICAgICBkaWdlc3Q6ICcnLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIHNob3VsZCgoKSA9PiBidWlsZGVyLmlucHV0T2JqZWN0cyhpbnZhbGlkSW5wdXRPYmplY3RzKSkudGhyb3dFcnJvcihcbiAgICAgICAgJ0ludmFsaWQgaW5wdXQgb2JqZWN0LCBpbnZhbGlkIG9yIG1pc3NpbmcgdmVyc2lvbidcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHRyYW5zZmVyIHdpdGggZGlmZmVyZW50IGdhcyBvd25lciBidXQgbm8gaW5wdXRPYmplY3RzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsIC8vIERpZmZlcmVudCBmcm9tIHNlbmRlclxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTsgLy8gU2VuZGVyXG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpOyAvLyBHYXMgcGFpZCBieSBzcG9uc29yXG4gICAgICAvLyBOb3RlOiBOT1QgcHJvdmlkaW5nIGlucHV0T2JqZWN0cyAtIHNob3VsZCBzdGlsbCB3b3JrIChmZWUgc3BvbnNvcnNoaXAgd2l0aG91dCBjb2luIHNwb25zb3JzaGlwKVxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHNob3VsZC5ub3QuZXhpc3Qoc3VpVHguc3VpVHJhbnNhY3Rpb24uaW5wdXRPYmplY3RzKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBleHRyYWN0IGlucHV0T2JqZWN0cyBmcm9tIHRyYW5zYWN0aW9uIGRhdGEgdmlhIHRvSnNvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0T2JqZWN0cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnMHgxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4JyxcbiAgICAgICAgICB2ZXJzaW9uOiAxMDAsXG4gICAgICAgICAgZGlnZXN0OiAnMkI4WEtRSjdtZnhRUFVXcUpKQUdqekJBeml2a1dLcTJjRWEzVzhMTHoxeUInLFxuICAgICAgICB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLCAvLyBEaWZmZXJlbnQgZnJvbSBzZW5kZXJcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgICAvLyBUZXN0IHRoYXQgdG9Kc29uIGV4dHJhY3RzIGlucHV0T2JqZWN0cyBmcm9tIHRyYW5zYWN0aW9uIHN0cnVjdHVyZVxuICAgICAgY29uc3QgdHhEYXRhID0gKHR4IGFzIGFueSkudG9Kc29uKCk7XG4gICAgICBzaG91bGQuZXhpc3QodHhEYXRhLmlucHV0T2JqZWN0cyk7XG5cbiAgICAgIC8vIFRoZSB0b0pzb24gc2hvdWxkIGV4dHJhY3QgdGhlIGlucHV0T2JqZWN0cyBmcm9tIHRoZSB0cmFuc2FjdGlvbiBzdHJ1Y3R1cmVcbiAgICAgIC8vIFRoaXMgdGVzdHMgb3VyIG5ldyBnZXRJbnB1dE9iamVjdHNGcm9tVHggbWV0aG9kXG4gICAgICBzaG91bGQuZXhpc3QodHhEYXRhLmlucHV0T2JqZWN0cyk7XG4gICAgICBBcnJheS5pc0FycmF5KHR4RGF0YS5pbnB1dE9iamVjdHMpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Z1bmRzSW5BZGRyZXNzQmFsYW5jZScsICgpID0+IHtcbiAgICBjb25zdCBGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UgPSAnNTAwMDAwMDAwMCc7IC8vIDUgU1VJXG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMmI6IHNlbGYtcGF5LCBhZGRyZXNzLWJhbGFuY2Ugb25seSDigJQgdXNlcyB3aXRoZHJhd2FsK3JlZGVlbV9mdW5kcywgbm90IFNwbGl0Q29pbnMoR2FzQ29pbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBSZWdyZXNzaW9uIGZvciBwcm9kdWN0aW9uIEluc3VmZmljaWVudENvaW5CYWxhbmNlIGZhaWx1cmVzIG9uIGNvbnNvbGlkYXRpb24uXG4gICAgICAvLyBXaXRoIHBheW1lbnQ9W10sIEdhc0NvaW4gb25seSBoYXMgZ2FzLWJ1ZGdldC13b3J0aCBvZiBiYWxhbmNlIGZvciBQVEIgb3BlcmF0aW9ucztcbiAgICAgIC8vIFNwbGl0Q29pbnMoR2FzQ29pbiwgW2xhcmdlX2Ftb3VudF0pIGFsd2F5cyBmYWlscyBhdCBjb21tYW5kIDAuXG4gICAgICAvLyBQYXRoIDJiIG11c3QgdXNlIHdpdGhkcmF3YWwrcmVkZWVtX2Z1bmRzIHRvIG1hdGVyaWFsaXNlIHRoZSBhZGRyZXNzIGJhbGFuY2UgYXMgYVxuICAgICAgLy8gY29pbiBvYmplY3QgYW5kIHNwbGl0IGZyb20gdGhhdCBjb2luIGluc3RlYWQuXG4gICAgICBjb25zdCBnYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpOyAvLyAyIHJlY2lwaWVudHNcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKGdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBQYXRoIDJiIFBUQiBjb21tYW5kIHNlcXVlbmNlICgyIHJlY2lwaWVudHMpOlxuICAgICAgLy8gICAwOiBNb3ZlQ2FsbChyZWRlZW1fZnVuZHMpICAgICAgICAgIOKAlCBtYXRlcmlhbGlzZSBhZGRyQ29pbiBmcm9tIGFkZHJlc3MgYmFsYW5jZVxuICAgICAgLy8gICAxOiBTcGxpdENvaW5zKGFkZHJDb2luLCBbYW1vdW50MF0pIOKAlCBzcGxpdCBmb3IgcmVjaXBpZW50IDBcbiAgICAgIC8vICAgMjogVHJhbnNmZXJPYmplY3RzICAgICAgICAgICAgICAgICDigJQgc2VuZCB0byByZWNpcGllbnQgMFxuICAgICAgLy8gICAzOiBTcGxpdENvaW5zKGFkZHJDb2luLCBbYW1vdW50MV0pIOKAlCBzcGxpdCBmb3IgcmVjaXBpZW50IDFcbiAgICAgIC8vICAgNDogVHJhbnNmZXJPYmplY3RzICAgICAgICAgICAgICAgICDigJQgc2VuZCB0byByZWNpcGllbnQgMVxuICAgICAgLy8gICA1OiBNZXJnZUNvaW5zKEdhc0NvaW4sIFthZGRyQ29pbl0pIOKAlCBkZXN0cm95IDAtYmFsYW5jZSBhZGRyQ29pbjsgZ2FzIGZyb20gYWNjdW11bGF0b3JcbiAgICAgIGNvbnN0IGNtZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG4gICAgICBjbWRzWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcsICdjb21tYW5kIDAgbXVzdCBiZSBNb3ZlQ2FsbChyZWRlZW1fZnVuZHMpJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJywgJ2NvbW1hbmQgMSBtdXN0IGJlIFNwbGl0Q29pbnMoYWRkckNvaW4pJyk7XG4gICAgICBjbWRzWzJdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnLCAnY29tbWFuZCAyIG11c3QgYmUgVHJhbnNmZXJPYmplY3RzJyk7XG4gICAgICBjbWRzWzNdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJywgJ2NvbW1hbmQgMyBtdXN0IGJlIFNwbGl0Q29pbnMoYWRkckNvaW4pJyk7XG4gICAgICBjbWRzWzRdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnLCAnY29tbWFuZCA0IG11c3QgYmUgVHJhbnNmZXJPYmplY3RzJyk7XG4gICAgICBjbWRzWzVdLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJywgJ2NvbW1hbmQgNSBtdXN0IGJlIE1lcmdlQ29pbnMoR2FzQ29pbiwgW2FkZHJDb2luXSknKTtcbiAgICAgIGNtZHMubGVuZ3RoLnNob3VsZC5lcXVhbCg2KTtcblxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZnVuZHNJbkFkZHJlc3NCYWxhbmNlIS5zaG91bGQuZXF1YWwoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgLy8gVHJhbnNhY3Rpb24gcGFyc2VyIG11c3QgY29ycmVjdGx5IGlkZW50aWZ5IHJlY2lwaWVudHMgZGVzcGl0ZSB0aGUgTW92ZUNhbGwgcHJlYW1ibGVcbiAgICAgIGNvbnN0IHBhcnNlZFJlY2lwaWVudHMgPSB1dGlscy5nZXRSZWNpcGllbnRzKHN1aVR4LnN1aVRyYW5zYWN0aW9uKTtcbiAgICAgIHBhcnNlZFJlY2lwaWVudHMubGVuZ3RoLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5yZWNpcGllbnRzLmxlbmd0aCk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50c1swXS5hbW91bnQpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXA6IHJlYnVpbHQgdHJhbnNhY3Rpb24gbXVzdCBiZSBiaXQtZm9yLWJpdCBpZGVudGljYWxcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgUGF0aCAyYiB3aXRoIGEgc2luZ2xlIHJlY2lwaWVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IFNFTkRfQU1PVU5UID0gJzEyNzUxNzA5OTM3MTAnOyAvLyByZWFsaXN0aWMgY29uc29saWRhdGlvbiBhbW91bnQgKH4xMjc1IFNVSSlcbiAgICAgIGNvbnN0IEFERFJfQkFMID0gJzEyNzUxNzc1NDA5MTAnOyAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgPiBTRU5EX0FNT1VOVCArIGdhcyBidWRnZXRcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IFNFTkRfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKGdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBRERSX0JBTCk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgY29uc3QgY21kcyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LnRyYW5zYWN0aW9ucyBhcyBhbnlbXTtcblxuICAgICAgLy8gQ29tbWFuZCBzZXF1ZW5jZSBmb3IgMSByZWNpcGllbnQ6XG4gICAgICAvLyAgIDA6IE1vdmVDYWxsKHJlZGVlbV9mdW5kcylcbiAgICAgIC8vICAgMTogU3BsaXRDb2lucyhhZGRyQ29pbiwgW1NFTkRfQU1PVU5UXSlcbiAgICAgIC8vICAgMjogVHJhbnNmZXJPYmplY3RzXG4gICAgICAvLyAgIDM6IE1lcmdlQ29pbnMoR2FzQ29pbiwgW2FkZHJDb2luXSlcbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG4gICAgICBjbWRzWzJdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnKTtcbiAgICAgIGNtZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnLCAnZXhwZWN0ZWQgTWVyZ2VDb2lucyB0byBjb25zdW1lIDAtYmFsYW5jZSBhZGRyQ29pbicpO1xuICAgICAgY21kcy5sZW5ndGguc2hvdWxkLmVxdWFsKDQpO1xuXG4gICAgICBjb25zdCBwYXJzZWRSZWNpcGllbnRzID0gdXRpbHMuZ2V0UmVjaXBpZW50cyhzdWlUeC5zdWlUcmFuc2FjdGlvbik7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICBwYXJzZWRSZWNpcGllbnRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoU0VORF9BTU9VTlQpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgUGF0aCAyYiB3aXRoIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gKHByb2R1Y3Rpb24gY29uc29saWRhdGlvbiBzY2VuYXJpbyknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBNaXJyb3JzIHRoZSByZWFsIG9uLWNoYWluIGNvbnNvbGlkYXRpb24gdGhhdCBmYWlsZWQ6IGFkZHJlc3MgaW5kZXggMTAsIHdhbGxldFxuICAgICAgLy8gNjdmZTNmMTUuLi4sIHR4aWQgSkRibnlib3RnM2F4Zmp0QjUzTHJuVjFZdHZHTEZCVkc4bzJYejV4WDFtNlouXG4gICAgICAvLyBUaGUgcmVjb3ZlcigpIGNvZGUgc2V0cyBWYWxpZER1cmluZyB3aGVuIGNvaW5PYmplY3RzQmFsYW5jZT0wIGFuZFxuICAgICAgLy8gZnVuZHNJbkFkZHJlc3NCYWxhbmNlPjAgKENhc2UgMikuIFRoaXMgdGVzdCB2ZXJpZmllcyBib3RoIHRoZSBleHBpcmF0aW9uIHN1cnZpdmVzXG4gICAgICAvLyBzZXJpYWxpemF0aW9uIGFuZCB0aGUgUFRCIHVzZXMgUGF0aCAyYiAobm90IHRoZSBicm9rZW4gU3BsaXRDb2lucyhHYXNDb2luKSBwYXRoKS5cbiAgICAgIGNvbnN0IEdFTkVTSVNfQ0hBSU5fSUQgPSAnR0FGcENDY1JDeFRkRmZVRU1iUWJrTEJhWnkyUk5pR0FmdkZCaE1OcHEya1QnO1xuICAgICAgY29uc3QgU0VORF9BTU9VTlQgPSAnMTI3NTE3MDk5MzcxMCc7XG4gICAgICBjb25zdCBBRERSX0JBTCA9ICcxMjc1MTc3NTQwOTEwJztcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IFNFTkRfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKGdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBRERSX0JBTCk7XG4gICAgICB0eEJ1aWxkZXIuZXhwaXJhdGlvbih7XG4gICAgICAgIFZhbGlkRHVyaW5nOiB7XG4gICAgICAgICAgbWluRXBvY2g6IHsgU29tZTogMTE1NiB9LFxuICAgICAgICAgIG1heEVwb2NoOiB7IFNvbWU6IDExNTcgfSxcbiAgICAgICAgICBtaW5UaW1lc3RhbXA6IHsgTm9uZTogbnVsbCB9LFxuICAgICAgICAgIG1heFRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgY2hhaW46IEdFTkVTSVNfQ0hBSU5fSUQsXG4gICAgICAgICAgbm9uY2U6IDEyMzQ1Njc4LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIE11c3QgdXNlIFBhdGggMmIgKE1vdmVDYWxsIGZpcnN0KSwgbmV2ZXIgU3BsaXRDb2lucyhHYXNDb2luKSBmaXJzdFxuICAgICAgY29uc3QgY21kcyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LnRyYW5zYWN0aW9ucyBhcyBhbnlbXTtcbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJywgJ1BhdGggMmIgbXVzdCBzdGFydCB3aXRoIE1vdmVDYWxsKHJlZGVlbV9mdW5kcyksIG5vdCBTcGxpdENvaW5zKEdhc0NvaW4pJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzW2NtZHMubGVuZ3RoIC0gMV0ua2luZC5zaG91bGQuZXF1YWwoXG4gICAgICAgICdNZXJnZUNvaW5zJyxcbiAgICAgICAgJ1BhdGggMmIgbXVzdCBlbmQgd2l0aCBNZXJnZUNvaW5zIHRvIGRlc3Ryb3kgMC1iYWxhbmNlIGFkZHJDb2luJ1xuICAgICAgKTtcblxuICAgICAgLy8gVmFsaWREdXJpbmcgZXhwaXJhdGlvbiBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICBjb25zdCBleHBpcmF0aW9uID0gKHJlYnVpbHRUeC50b0pzb24oKS5leHBpcmF0aW9uIGFzIGFueSk/LlZhbGlkRHVyaW5nO1xuICAgICAgc2hvdWxkLmV4aXN0KGV4cGlyYXRpb24sICdWYWxpZER1cmluZyBleHBpcmF0aW9uIG11c3Qgc3Vydml2ZSByb3VuZC10cmlwJyk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5taW5FcG9jaC5Tb21lKS5zaG91bGQuZXF1YWwoMTE1Nik7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5tYXhFcG9jaC5Tb21lKS5zaG91bGQuZXF1YWwoMTE1Nyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc2VsZi1wYXkgdHJhbnNmZXIgd2l0aCBjb2luIG9iamVjdHMgKyBhZGRyZXNzIGJhbGFuY2UgKFBhdGggMmMpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gUmVncmVzc2lvbiB0ZXN0IGZvciBDT0lOUy0zMzE6IHdoZW4gYm90aCBnYXNEYXRhLnBheW1lbnQgKGNvaW4gb2JqZWN0cykgYW5kXG4gICAgICAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgYXJlIHNldCwgU3VpIGRvZXMgTk9UIGF1dG9tYXRpY2FsbHkgbWVyZ2UgYWRkcmVzcyBiYWxhbmNlIGludG9cbiAgICAgIC8vIHRoZSBnYXMgY29pbi4gIFBhdGggMmMgbXVzdCBleHBsaWNpdGx5IGNhbGwgcmVkZWVtX2Z1bmRzICsgTWVyZ2VDb2lucyhnYXMsIFthZGRyQ29pbl0pXG4gICAgICAvLyBiZWZvcmUgU3BsaXRDb2lucyBzbyB0aGF0IHRoZSBnYXMgY29pbiBob2xkcyB0aGUgZnVsbCBzcGVuZGFibGUgYW1vdW50LlxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEodGVzdERhdGEuZ2FzRGF0YSk7IC8vIG5vbi1lbXB0eSBwYXltZW50IOKAlCB0cmlnZ2VycyBQYXRoIDJjXG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuXG4gICAgICAvLyBQYXRoIDJjIFBUQiBjb21tYW5kIHNlcXVlbmNlIChmb3IgMiByZWNpcGllbnRzKTpcbiAgICAgIC8vICAgMDogTW92ZUNhbGwocmVkZWVtX2Z1bmRzKSAgICAg4oCUIG1hdGVyaWFsaXplIGFkZHJDb2luIGZyb20gYWRkcmVzcyBiYWxhbmNlXG4gICAgICAvLyAgIDE6IE1lcmdlQ29pbnMoZ2FzLCBbYWRkckNvaW5dKeKAlCBnYXMgY29pbiA9IGNvaW5PYmplY3RzICsgYWRkckJhbCAoZnVsbCBzcGVuZGFibGUgYW1vdW50KVxuICAgICAgLy8gICAyOiBTcGxpdENvaW5zKGdhcykgICAgICAgICAgICDigJQgc3BsaXQgZm9yIHJlY2lwaWVudCAwXG4gICAgICAvLyAgIDM6IFRyYW5zZmVyT2JqZWN0cyAgICAgICAgICAgIOKAlCBzZW5kIHRvIHJlY2lwaWVudCAwXG4gICAgICAvLyAgIDQ6IFNwbGl0Q29pbnMoZ2FzKSAgICAgICAgICAgIOKAlCBzcGxpdCBmb3IgcmVjaXBpZW50IDFcbiAgICAgIC8vICAgNTogVHJhbnNmZXJPYmplY3RzICAgICAgICAgICAg4oCUIHNlbmQgdG8gcmVjaXBpZW50IDFcbiAgICAgIGNvbnN0IHByb2dyYW1tYWJsZVR4ID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHg7XG4gICAgICBjb25zdCBjbWRzID0gcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuICAgICAgY21kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnLCAnY29tbWFuZCAwIG11c3QgYmUgTW92ZUNhbGwocmVkZWVtX2Z1bmRzKScpO1xuICAgICAgY21kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgY21kc1sxXS5raW5kLnNob3VsZC5lcXVhbCgnTWVyZ2VDb2lucycsICdjb21tYW5kIDEgbXVzdCBiZSBNZXJnZUNvaW5zKGdhcywgW2FkZHJDb2luXSknKTtcbiAgICAgIGNtZHNbMl0ua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnLCAnY29tbWFuZCAyIG11c3QgYmUgU3BsaXRDb2lucyhnYXMsIFthbW91bnQwXSknKTtcbiAgICAgIGNtZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycpO1xuICAgICAgY21kc1s0XS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycsICdjb21tYW5kIDQgbXVzdCBiZSBTcGxpdENvaW5zKGdhcywgW2Ftb3VudDFdKScpO1xuICAgICAgY21kc1s1XS5raW5kLnNob3VsZC5lcXVhbCgnVHJhbnNmZXJPYmplY3RzJyk7XG5cbiAgICAgIC8vIGZ1bmRzSW5BZGRyZXNzQmFsYW5jZSBtdXN0IGJlIHBlcnNpc3RlZCBpbiB0aGUgc2VyaWFsaXplZCB0cmFuc2FjdGlvblxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZnVuZHNJbkFkZHJlc3NCYWxhbmNlIS5zaG91bGQuZXF1YWwoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwOiByZWJ1aWx0IHRyYW5zYWN0aW9uIG11c3QgYmUgYml0LWZvci1iaXQgaWRlbnRpY2FsXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHRyYW5zZmVyIHdpdGggY29pbiBvYmplY3RzICsgYWRkcmVzcyBiYWxhbmNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW5wdXRPYmplY3RzID0gdGVzdERhdGEuZ2VuZXJhdGVPYmplY3RzKDIpO1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5pbnB1dE9iamVjdHMoaW5wdXRPYmplY3RzKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzKTtcblxuICAgICAgLy8gU3BvbnNvcmVkIHBhdGg6IE1vdmVDYWxsKHJlZGVlbV9mdW5kcykgKyBNZXJnZUNvaW5zICsgU3BsaXRDb2luc1xuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1sxXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJyk7XG4gICAgICAocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzJdIGFzIGFueSkua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHRyYW5zZmVyIHdpdGggYWRkcmVzcyBiYWxhbmNlIG9ubHkgKG5vIGNvaW4gaW5wdXRPYmplY3RzKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAvLyBQYXRoIDFiOiB3aXRoZHJhd2FsIOKGkiByZWRlZW1fZnVuZHMg4oaSIFNwbGl0Q29pbnMoYWRkckNvaW4pIOKGkiBUcmFuc2Zlck9iamVjdHNcbiAgICAgIC8vIFNwb25zb3IncyBnYXMgY29pbnMgcmVtYWluIGluIGdhc0RhdGEucGF5bWVudDsgdHguZ2FzIGlzIE5PVCB1c2VkIGZvciB0aGUgdHJhbnNmZXIgYW1vdW50LlxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MpO1xuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1sxXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgLy8gUm91bmQtdHJpcDogcmVidWlsZCBmcm9tIHJhd1xuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBQYXRoIDFiIHNlbmQtYWxsOiBzcG9uc29yZWQgYWRkci1iYWxhbmNlLW9ubHksIG5vIGNoYW5nZSAoTWVyZ2VDb2lucyBjb25zdW1lcyBhZGRyQ29pbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBSZXByb2R1Y2VzIHRoZSByZWFsIG9uLWNoYWluIGZhaWx1cmU6IFVudXNlZFZhbHVlV2l0aG91dERyb3AgeyByZXN1bHRfaWR4OiAwIH1cbiAgICAgIC8vIE9jY3VycyB3aGVuIHJlZGVlbV9mdW5kcyByZXR1cm5zIGFkZHJDb2luLCBTcGxpdENvaW5zIGRyYWlucyBpdCBjb21wbGV0ZWx5LCBhbmQgdGhlXG4gICAgICAvLyAwLWJhbGFuY2Ugc291cmNlIGNvaW4gaXMgbmV2ZXIgY29uc3VtZWQuICBGaXg6IE1lcmdlQ29pbnMoZ2FzLCBbYWRkckNvaW5dKSBhdCB0aGUgZW5kLlxuICAgICAgY29uc3QgU0VORF9BTU9VTlQgPSAnMTAwMDAwMCc7IC8vIDAuMDAxIFNVSSDigJQgc2FtZSBhcyB0aGUgZmFpbGluZyB0eFxuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IFNFTkRfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShTRU5EX0FNT1VOVCk7IC8vIHNlbmQtYWxsOiBiYWxhbmNlID09IHJlY2lwaWVudCBhbW91bnRcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBjbWRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuXG4gICAgICAvLyBFeHBlY3RlZCBjb21tYW5kIHNlcXVlbmNlIGZvciBQYXRoIDFiIHNlbmQtYWxsOlxuICAgICAgLy8gICAwOiBNb3ZlQ2FsbCAocmVkZWVtX2Z1bmRzKSAgICAg4oCUIHdpdGhkcmF3IGFkZHJDb2luXG4gICAgICAvLyAgIDE6IFNwbGl0Q29pbnMoYWRkckNvaW4pICAgICAgICDigJQgc3BsaXQgcmVjaXBpZW50IGFtb3VudCBvZmYgYWRkckNvaW5cbiAgICAgIC8vICAgMjogVHJhbnNmZXJPYmplY3RzKFtzcGxpdF0pICAgIOKAlCBzZW5kIHRvIHJlY2lwaWVudFxuICAgICAgLy8gICAzOiBNZXJnZUNvaW5zKGdhcywgW2FkZHJDb2luXSkg4oCUIGNvbnN1bWUgdGhlIG5vdy16ZXJvLWJhbGFuY2UgYWRkckNvaW5cbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjbWRzWzFdLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG4gICAgICBjbWRzWzJdLmtpbmQuc2hvdWxkLmVxdWFsKCdUcmFuc2Zlck9iamVjdHMnKTtcbiAgICAgIGNtZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnLCAnZXhwZWN0ZWQgTWVyZ2VDb2lucyB0byBjb25zdW1lIDAtYmFsYW5jZSBhZGRyQ29pbiBhZnRlciBzZW5kLWFsbCcpO1xuXG4gICAgICAvLyBSZWNpcGllbnQgcGFyc2luZyBtdXN0IG5vdCBiZSBhZmZlY3RlZCBieSB0aGUgdHJhaWxpbmcgTWVyZ2VDb2luc1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoc3VpVHguc3VpVHJhbnNhY3Rpb24pO1xuICAgICAgcmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgcmVjaXBpZW50c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKFNFTkRfQU1PVU5UKTtcblxuICAgICAgLy8gUm91bmQtdHJpcFxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBQYXRoIDFiIHdpdGggY2hhbmdlOiBzcG9uc29yZWQgYWRkci1iYWxhbmNlLW9ubHksIGV4Y2VzcyByZXR1cm5lZCB0byBzZW5kZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgZXhjZWVkcyB0aGUgdG90YWwgcmVjaXBpZW50IGFtb3VudCDihpIgY2hhbmdlIG11c3QgYmUgcmV0dXJuZWQgdG9cbiAgICAgIC8vIHRoZSBzZW5kZXIgYXMgYW4gZXh0cmEgVHJhbnNmZXJPYmplY3RzKFthZGRyQ29pbl0sIHNlbmRlcikuICBUaGUgdHJhbnNhY3Rpb24gcGFyc2VyIG11c3RcbiAgICAgIC8vIHNraXAgdGhpcyBjaGFuZ2UgdHJhbnNmZXIgYW5kIG9ubHkgcmVwb3J0IGFjdHVhbCByZWNpcGllbnRzLlxuICAgICAgY29uc3QgU0VORF9BTU9VTlQgPSAnMTAwJzsgLy8gZWFjaCBvZiB0aGUgdHdvIHRlc3REYXRhLnJlY2lwaWVudHMgZ2V0cyAxMDBcbiAgICAgIGNvbnN0IEVYQ0VTUyA9ICc5OTk5OTAwJzsgLy8gZnVuZHNJbkFkZHJlc3NCYWxhbmNlID0gMTBfMDAwXzAwMCwgdG90YWwgc2VuZCA9IDIwMFxuICAgICAgY29uc3QgRlVORFNfQkFMQU5DRSA9IChOdW1iZXIoU0VORF9BTU9VTlQpICogdGVzdERhdGEucmVjaXBpZW50cy5sZW5ndGggKyBOdW1iZXIoRVhDRVNTKSkudG9TdHJpbmcoKTtcblxuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7IC8vIDIgcmVjaXBpZW50cyDDlyAxMDAgTUlTVCA9IDIwMCBNSVNUIHRvdGFsXG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfQkFMQU5DRSk7IC8vIDEwXzAwMF8wMDAgPiAyMDAg4oaSIGhhcyBjaGFuZ2VcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBjbWRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuXG4gICAgICAvLyBFeHBlY3RlZCBzZXF1ZW5jZSBmb3IgUGF0aCAxYiB3aXRoIGNoYW5nZSAoMiByZWNpcGllbnRzKTpcbiAgICAgIC8vICAgMDogTW92ZUNhbGwgKHJlZGVlbV9mdW5kcylcbiAgICAgIC8vICAgMTogU3BsaXRDb2lucyAg4oCUICByZWNpcGllbnQgMFxuICAgICAgLy8gICAyOiBUcmFuc2Zlck9iamVjdHMgIOKAlCAgcmVjaXBpZW50IDBcbiAgICAgIC8vICAgMzogU3BsaXRDb2lucyAg4oCUICByZWNpcGllbnQgMVxuICAgICAgLy8gICA0OiBUcmFuc2Zlck9iamVjdHMgIOKAlCAgcmVjaXBpZW50IDFcbiAgICAgIC8vICAgNTogVHJhbnNmZXJPYmplY3RzKFthZGRyQ29pbl0sIHNlbmRlcikgIOKAlCAgY2hhbmdlIGJhY2sgdG8gc2VuZGVyXG4gICAgICBjbWRzWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgY21kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgY29uc3QgbGFzdENtZCA9IGNtZHNbY21kcy5sZW5ndGggLSAxXTtcbiAgICAgIGxhc3RDbWQua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycsICdsYXN0IGNvbW1hbmQgbXVzdCBiZSB0aGUgY2hhbmdlIHRyYW5zZmVyJyk7XG5cbiAgICAgIC8vIFRoZSBsYXN0IFRyYW5zZmVyT2JqZWN0cyByZXR1cm5zIGNoYW5nZSB0byB0aGUgKnNlbmRlciosIG5vdCBhIHJlY2lwaWVudFxuICAgICAgY29uc3QgY2hhbmdlQWRkcklucHV0ID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHguaW5wdXRzW2xhc3RDbWQuYWRkcmVzcy5pbmRleF0gYXMgYW55O1xuICAgICAgY29uc3QgY2hhbmdlQWRkciA9IHV0aWxzLmdldEFkZHJlc3MoY2hhbmdlQWRkcklucHV0KTtcbiAgICAgIGNoYW5nZUFkZHIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLCAnY2hhbmdlIG11c3QgZ28gYmFjayB0byBzZW5kZXInKTtcblxuICAgICAgLy8gUGFyc2VyIG11c3QgcmV0dXJuIG9ubHkgdGhlIGFjdHVhbCByZWNpcGllbnRzLCBub3QgdGhlIGNoYW5nZSB0cmFuc2ZlclxuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoc3VpVHguc3VpVHJhbnNhY3Rpb24pO1xuICAgICAgcmVjaXBpZW50cy5sZW5ndGguc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHMubGVuZ3RoKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbChTRU5EX0FNT1VOVCk7XG4gICAgICByZWNpcGllbnRzWzFdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMV0uYWRkcmVzcyk7XG4gICAgICByZWNpcGllbnRzWzFdLmFtb3VudC5zaG91bGQuZXF1YWwoU0VORF9BTU9VTlQpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BvbnNvcmVkIHR4IGdhcyBwYWlkIGZyb20gc3BvbnNvciBhZGRyZXNzIGJhbGFuY2UgKGVtcHR5IHBheW1lbnQpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW5wdXRPYmplY3RzID0gdGVzdERhdGEuZ2VuZXJhdGVPYmplY3RzKDEpO1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YU5vUGF5bWVudCA9IHtcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgICAgICBwcmljZTogdGVzdERhdGEuZ2FzRGF0YS5wcmljZSxcbiAgICAgICAgYnVkZ2V0OiB0ZXN0RGF0YS5nYXNEYXRhLmJ1ZGdldCxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGFOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MpO1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIFNwb25zb3JlZCBwYXRoIHdpdGggY29pbiBvYmplY3RzLCBubyBhZGRyZXNzIGJhbGFuY2Ugd2l0aGRyYXdhbFxuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJvdW5kLXRyaXAgYSBzZWxmLXBheSB0cmFuc2ZlciB3aXRoIEVwb2NoIGV4cGlyYXRpb24gdmlhIGZyb21CeXRlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFJlZ3Jlc3Npb24gdGVzdCBmb3IgdGhlIEJpZ0ludCByb3VuZC10cmlwIGJ1ZzpcbiAgICAgIC8vIEJDUy5VNjQgZGVzZXJpYWxpemVzIHU2NCBhcyBCaWdJbnQsIGJ1dCB0aGUgcHJldmlvdXMgc3VwZXJzdHJ1Y3Qgc2NoZW1hIHVzZWQgaW50ZWdlcigpXG4gICAgICAvLyB3aGljaCByZWplY3RlZCBCaWdJbnQsIGNhdXNpbmcgZnJvbUJ5dGVzKCkgdG8gdGhyb3cgYSBTdHJ1Y3RFcnJvciBhdCBcImV4cGlyYXRpb25cIi5cbiAgICAgIC8vIFN0cmluZ0VuY29kZWRCaWdpbnQgbm93IGFjY2VwdHMgc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50LCBmaXhpbmcgdGhlIHJvdW5kLXRyaXAuXG4gICAgICBjb25zdCBnYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoZ2FzRGF0YU5vUGF5bWVudCk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG4gICAgICB0eEJ1aWxkZXIuZXhwaXJhdGlvbih7IEVwb2NoOiAzMjQgfSk7IC8vIG51bWJlciBpbnB1dFxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBmcm9tQnl0ZXMgbXVzdCBub3QgdGhyb3cgU3RydWN0RXJyb3Ig4oCUIHRoaXMgd2FzIHRoZSBmYWlsaW5nIGNhc2UgYmVmb3JlIHRoZSBmaXhcbiAgICAgIHNob3VsZC5kb2VzTm90VGhyb3coKCkgPT4ge1xuICAgICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgICBzaG91bGQuZXhpc3QocmVidWlsZGVyKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBGdWxsIHJvdW5kLXRyaXA6IHJlYnVpbHQgdHggbXVzdCBzZXJpYWxpemUgaWRlbnRpY2FsbHlcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcblxuICAgICAgLy8gRXBvY2ggdmFsdWUgbXVzdCBzdXJ2aXZlIHRoZSByb3VuZC10cmlwIHJlZ2FyZGxlc3Mgb2YgQmlnSW50L251bWJlciByZXByZXNlbnRhdGlvblxuICAgICAgY29uc3QgcmVidWlsdEpzb24gPSByZWJ1aWx0VHgudG9Kc29uKCk7XG4gICAgICBjb25zdCBlcG9jaFZhbCA9IChyZWJ1aWx0SnNvbi5leHBpcmF0aW9uIGFzIGFueSk/LkVwb2NoO1xuICAgICAgc2hvdWxkLmV4aXN0KGVwb2NoVmFsKTtcbiAgICAgIE51bWJlcihlcG9jaFZhbCkuc2hvdWxkLmVxdWFsKDMyNCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJvdW5kLXRyaXAgYSBzZWxmLXBheSB0cmFuc2ZlciB3aXRoIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gdmlhIGZyb21CeXRlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFZlcmlmaWVzIHRoZSBmdWxsIDYtZmllbGQgVmFsaWREdXJpbmdFeHBpcmF0aW9uIEJDUyBzY2hlbWE6XG4gICAgICAvLyAgIG1pbkVwb2NoL21heEVwb2NoIGFzIE9wdGlvbjx1NjQ+LCBtaW5UaW1lc3RhbXAvbWF4VGltZXN0YW1wIGFzIE9wdGlvbjx1NjQ+IChOb25lKSxcbiAgICAgIC8vICAgY2hhaW4gYXMgMzItYnl0ZSBCYXNlNTggT2JqZWN0RGlnZXN0LCBub25jZSBhcyB1MzIuXG4gICAgICAvLyBVc2VzIGEgcmVhbCBtYWlubmV0IGdlbmVzaXMgY2hlY2twb2ludCBkaWdlc3QgKDMyIGJ5dGVzLCBCYXNlNTgpLlxuICAgICAgY29uc3QgR0VORVNJU19DSEFJTl9JRCA9ICdHQUZwQ0NjUkN4VGRGZlVFTWJRYmtMQmFaeTJSTmlHQWZ2RkJoTU5wcTJrVCc7XG4gICAgICBjb25zdCBGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UgPSAnNTAwMDAwMDAwMCc7XG4gICAgICBjb25zdCBnYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsXG4gICAgICAgIHBheW1lbnQ6IFtdLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoZ2FzRGF0YU5vUGF5bWVudCk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSk7XG4gICAgICB0eEJ1aWxkZXIuZXhwaXJhdGlvbih7XG4gICAgICAgIFZhbGlkRHVyaW5nOiB7XG4gICAgICAgICAgbWluRXBvY2g6IHsgU29tZTogNTAwIH0sXG4gICAgICAgICAgbWF4RXBvY2g6IHsgU29tZTogNTAxIH0sXG4gICAgICAgICAgbWluVGltZXN0YW1wOiB7IE5vbmU6IG51bGwgfSxcbiAgICAgICAgICBtYXhUaW1lc3RhbXA6IHsgTm9uZTogbnVsbCB9LFxuICAgICAgICAgIGNoYWluOiBHRU5FU0lTX0NIQUlOX0lELFxuICAgICAgICAgIG5vbmNlOiAweGRlYWRiZWVmLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIGZyb21CeXRlcyBtdXN0IG5vdCB0aHJvdyDigJQgVmFsaWREdXJpbmcgZmllbGRzIG11c3Qgc3Vydml2ZSBkZXNlcmlhbGl6YXRpb25cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuXG4gICAgICAvLyBCQ1Mgcm91bmQtdHJpcDogc2VyaWFsaXplZCBieXRlcyBtdXN0IGJlIGlkZW50aWNhbFxuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcblxuICAgICAgLy8gQWxsIFZhbGlkRHVyaW5nIGZpZWxkcyBtdXN0IHN1cnZpdmUgdGhlIHJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IGV4cGlyYXRpb24gPSAocmVidWlsdFR4LnRvSnNvbigpLmV4cGlyYXRpb24gYXMgYW55KT8uVmFsaWREdXJpbmc7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwaXJhdGlvbik7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5taW5FcG9jaD8uU29tZSA/PyBleHBpcmF0aW9uLm1pbkVwb2NoKS5zaG91bGQuZXF1YWwoNTAwKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm1heEVwb2NoPy5Tb21lID8/IGV4cGlyYXRpb24ubWF4RXBvY2gpLnNob3VsZC5lcXVhbCg1MDEpO1xuICAgICAgZXhwaXJhdGlvbi5jaGFpbi5zaG91bGQuZXF1YWwoR0VORVNJU19DSEFJTl9JRCk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5ub25jZSkuc2hvdWxkLmVxdWFsKDB4ZGVhZGJlZWYpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnbGFyZ2UgYW1vdW50cyBleGNlZWRpbmcgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVInLCAoKSA9PiB7XG4gICAgLy8gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIgPSA5MDA3MTk5MjU0NzQwOTkxLlxuICAgIC8vIFVzaW5nIE51bWJlcigpIGZvciBhbW91bnRzIGFib3ZlIHRoaXMgc2lsZW50bHkgcm91bmRzIHRvIHRoZSBuZWFyZXN0IHJlcHJlc2VudGFibGUgZmxvYXQuXG4gICAgLy8gOTAwNzE5OTI1NDc0MDk5MyAoTUFYX1NBRkVfSU5URUdFUiArIDIpIGlzIE5PVCBleGFjdGx5IHJlcHJlc2VudGFibGUgYXMgYSBKUyBOdW1iZXIg4oCUIGl0XG4gICAgLy8gcm91bmRzIGRvd24gdG8gOTAwNzE5OTI1NDc0MDk5MiDigJQgc28gQkNTIHdvdWxkIGVuY29kZSB0aGUgd3JvbmcgdmFsdWUuXG4gICAgLy8gQmlnSW50IHByZXNlcnZlcyB0aGUgZXhhY3QgdmFsdWUgYW5kIGlzIHRoZSBjb3JyZWN0IHR5cGUgZm9yIEJDUyB1NjQgZW5jb2RpbmcuXG4gICAgLy9cbiAgICAvLyBUaGUgY29yZSBjaGVjayBpbiBlYWNoIHRlc3QgaXMgdHgub3V0cHV0c1swXS52YWx1ZSA9PT0gTEFSR0VfQU1PVU5UOiB0aGlzIHJlYWRzIGZyb20gdGhlXG4gICAgLy8gaW4tbWVtb3J5IGJ1aWxkZXIgc3RhdGUgKGEgQmlnSW50LCBub3QgQkNTLWRlY29kZWQpLCBzbyBpdCBhY2N1cmF0ZWx5IGRpc3Rpbmd1aXNoZXNcbiAgICAvLyBCaWdJbnQoKSB2cyBOdW1iZXIoKSBlbmNvZGluZyBhdCBidWlsZCB0aW1lLlxuICAgIGNvbnN0IExBUkdFX0FNT1VOVCA9ICc5MDA3MTk5MjU0NzQwOTkzJzsgLy8gTUFYX1NBRkVfSU5URUdFUiArIDJcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzZWxmLXBheSB0cmFuc2ZlciAoUGF0aCAyKSB3aXRoIGFtb3VudCA+IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSIGFuZCBlbmNvZGUgaXQgcHJlY2lzZWx5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcywgYW1vdW50OiBMQVJHRV9BTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEodGVzdERhdGEuZ2FzRGF0YSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAvLyBXaXRoIE51bWJlcigpIHRoZSBhbW91bnQgd291bGQgYmUgc2lsZW50bHkgcm91bmRlZCB0byA5MDA3MTk5MjU0NzQwOTkyIOKAlCBCaWdJbnQgcHJlc2VydmVzIHRoZSBleGFjdCB2YWx1ZVxuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS52YWx1ZS5zaG91bGQuZXF1YWwoTEFSR0VfQU1PVU5UKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwb25zb3JlZCB0cmFuc2ZlciB3aXRoIGNvaW4gb2JqZWN0cyAoUGF0aCAxYSkgd2l0aCBhbW91bnQgPiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiBhbmQgZW5jb2RlIGl0IHByZWNpc2VseScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0T2JqZWN0cyA9IHRlc3REYXRhLmdlbmVyYXRlT2JqZWN0cygyKTtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcywgYW1vdW50OiBMQVJHRV9BTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuaW5wdXRPYmplY3RzKGlucHV0T2JqZWN0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICAvLyBXaXRoIE51bWJlcigpIHRoZSBhbW91bnQgd291bGQgYmUgc2lsZW50bHkgcm91bmRlZCB0byA5MDA3MTk5MjU0NzQwOTkyIOKAlCBCaWdJbnQgcHJlc2VydmVzIHRoZSBleGFjdCB2YWx1ZVxuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS52YWx1ZS5zaG91bGQuZXF1YWwoTEFSR0VfQU1PVU5UKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwb25zb3JlZCBhZGRyLWJhbGFuY2Utb25seSB0cmFuc2ZlciAoUGF0aCAxYikgd2l0aCBhbW91bnQgPiBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUiBhbmQgcm91bmQtdHJpcCBjb3JyZWN0bHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogTEFSR0VfQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShMQVJHRV9BTU9VTlQpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgLy8gV2l0aCBOdW1iZXIoKSB0aGUgYW1vdW50IHdvdWxkIGJlIHNpbGVudGx5IHJvdW5kZWQgdG8gOTAwNzE5OTI1NDc0MDk5MiDigJQgQmlnSW50IHByZXNlcnZlcyB0aGUgZXhhY3QgdmFsdWVcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4Lm91dHB1dHNbMF0udmFsdWUuc2hvdWxkLmVxdWFsKExBUkdFX0FNT1VOVCk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgLy8gRnVsbCByb3VuZC10cmlwOiByZWJ1aWxkaW5nIGZyb20gQkNTIGJ5dGVzIG11c3QgcHJvZHVjZSBpZGVudGljYWwgYnl0ZXNcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcblxuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoXG4gICAgICAgIChyZWJ1aWx0VHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj4pLnN1aVRyYW5zYWN0aW9uXG4gICAgICApO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKExBUkdFX0FNT1VOVCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwcm9kIGFkZHJlc3MgYmFsYW5jZSBjb25zb2xpZGF0aW9uIChDRUNITy0xMjEwKScsICgpID0+IHtcbiAgICAvLyBGYWlsZWQgcHJvZCBjb25zb2xpZGF0aW9uIDZhMTljYjhiY2Q0NzUxZGJkODkxYTcyMmVlMDRlNTUyICh0eFJlcXVlc3QgZWU1ZDYwZDctZmE1My00ZmE0LWFkY2YtMjY0MzVjOTMxN2JmKS5cbiAgICAvLyBCcm9hZGNhc3QgZmFpbGVkIHdpdGggc3RhbGUgY29pbiBvYmplY3QgdmVyc2lvbjsgdGhlIGFtb3VudCBtdXN0IHN0aWxsIGVuY29kZSBsb3NzbGVzc2x5LlxuICAgIGNvbnN0IENPTlNPTElEQVRJT05fQU1PVU5UID0gJzE4NTM2Nzk3ODQyNjEzNzAwJzsgLy8gfjE4LjVNIFNVSSBpbiBNSVNUIChzZW5kQWNjb3VudGluZy5hbW91bnRTdHJpbmcpXG4gICAgY29uc3QgQ09OU09MSURBVElPTl9TRU5ERVIgPSAnMHg0NmE1M2UyNzEyNTYxZjRlMGQ4MjcyYmQyN2EzOTZiNmJmOTMyNWY5MmYzNGI5NDkwNDFiODc4M2Q1NzQ2OWRkJztcbiAgICBjb25zdCBDT05TT0xJREFUSU9OX1JFQ0lQSUVOVCA9ICcweDNkYTJjYjY3Yzg4N2M5YTAzZDEwNTJkNDg2NzMzYTc3MTA1ODI0Zjc0MTNmYzNjYmJlMzY0MWQ0YjY3YWYxMDInO1xuXG4gICAgaXQoJ3Nob3VsZCBhY2NlcHQgdGhlIHByb2QgY29uc29saWRhdGlvbiBhbW91bnQgaW4gaXNWYWxpZEFtb3VudCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHV0aWxzLmlzVmFsaWRBbW91bnQoQ09OU09MSURBVElPTl9BTU9VTlQpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgICBOdW1iZXIuaXNTYWZlSW50ZWdlcihOdW1iZXIoQ09OU09MSURBVElPTl9BTU9VTlQpKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYWRkcmVzcy1iYWxhbmNlLW9ubHkgY29uc29saWRhdGlvbiB3aXRoIGV4YWN0IHByb2QgYW1vdW50IChQYXRoIDIsIGVtcHR5IHBheW1lbnQpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZ2FzRGF0YU5vUGF5bWVudCA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YVdpdGhvdXRHYXNQYXltZW50LFxuICAgICAgICBwYXltZW50OiBbXSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcihDT05TT0xJREFUSU9OX1NFTkRFUik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiBDT05TT0xJREFUSU9OX1JFQ0lQSUVOVCwgYW1vdW50OiBDT05TT0xJREFUSU9OX0FNT1VOVCB9XSk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoQ09OU09MSURBVElPTl9BTU9VTlQpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHgub3V0cHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogQ09OU09MSURBVElPTl9SRUNJUElFTlQsXG4gICAgICAgIHZhbHVlOiBDT05TT0xJREFUSU9OX0FNT1VOVCxcbiAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgfSk7XG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS52YWx1ZS5zaG91bGQuZXF1YWwoQ09OU09MSURBVElPTl9BTU9VTlQpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IFN1aVRyYW5zYWN0aW9uLmRlc2VyaWFsaXplU3VpVHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHV0aWxzLmdldFJlY2lwaWVudHMoZGVzZXJpYWxpemVkKTtcbiAgICAgIHJlY2lwaWVudHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoQ09OU09MSURBVElPTl9SRUNJUElFTlQpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKENPTlNPTElEQVRJT05fQU1PVU5UKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYWRkcmVzcy1iYWxhbmNlIGNvbnNvbGlkYXRpb24gd2l0aCBjb2luIG9iamVjdHMgYW5kIGV4YWN0IHByb2QgYW1vdW50IChQYXRoIDIpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gUHJvZCBmYWlsdXJlIHJlZmVyZW5jZWQgc3RhbGUgZ2FzL2NvaW4gb2JqZWN0IHZlcnNpb25zIGJldHdlZW4gc2lnbiBhbmQgYnJvYWRjYXN0LlxuICAgICAgLy8gQnVpbGRlciBtdXN0IHN0aWxsIGVuY29kZSB0aGUgZnVsbCBjb25zb2xpZGF0aW9uIGFtb3VudCBpbiBTcGxpdENvaW5zLlxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKENPTlNPTElEQVRJT05fU0VOREVSKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IENPTlNPTElEQVRJT05fUkVDSVBJRU5ULCBhbW91bnQ6IENPTlNPTElEQVRJT05fQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHsgLi4udGVzdERhdGEuZ2FzRGF0YSwgb3duZXI6IENPTlNPTElEQVRJT05fU0VOREVSIH0pO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShDT05TT0xJREFUSU9OX0FNT1VOVCk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICB0eC5vdXRwdXRzWzBdLnZhbHVlLnNob3VsZC5lcXVhbChDT05TT0xJREFUSU9OX0FNT1VOVCk7XG4gICAgICB0eC5pbnB1dHNbMF0udmFsdWUuc2hvdWxkLmVxdWFsKENPTlNPTElEQVRJT05fQU1PVU5UKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG5cbiAgICAgIGNvbnN0IHJlY2lwaWVudHMgPSB1dGlscy5nZXRSZWNpcGllbnRzKFxuICAgICAgICAocmVidWlsdFR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+KS5zdWlUcmFuc2FjdGlvblxuICAgICAgKTtcbiAgICAgIHJlY2lwaWVudHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoQ09OU09MSURBVElPTl9SRUNJUElFTlQpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKENPTlNPTElEQVRJT05fQU1PVU5UKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0JhbGFuY2VXaXRoZHJhd2FsIEJDUyBlbmNvZGluZyAoRnVuZHNXaXRoZHJhd2FsIGZvcm1hdCknLCAoKSA9PiB7XG4gICAgY29uc3QgQU1PVU5UID0gJzEwMDAwMDAwMCc7IC8vIDAuMSBTVUkgaW4gTUlTVFxuICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgfTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKSB7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IEFNT1VOVCB9XSk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoQU1PVU5UKTtcbiAgICAgIHJldHVybiB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9XG5cbiAgICBpdCgnc2hvdWxkIGVuY29kZSBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCB3aXRoIEZ1bmRzV2l0aGRyYXdhbCBzdHJ1Y3R1cmUgKHJlc2VydmF0aW9uL3R5cGVBcmcvd2l0aGRyYXdGcm9tKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRTcG9uc29yZWRUeFdpdGhBZGRyZXNzQmFsYW5jZSgpO1xuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcblxuICAgICAgY29uc3QgYndJbnB1dCA9IGlucHV0cy5maW5kKFxuICAgICAgICAoaW5wKSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChid0lucHV0LCAnQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQgbXVzdCBiZSBwcmVzZW50Jyk7XG5cbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnJlc2VydmF0aW9uLCAncmVzZXJ2YXRpb24gZmllbGQgbXVzdCBleGlzdCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NCwgJ3Jlc2VydmF0aW9uLk1heEFtb3VudFU2NCBtdXN0IGV4aXN0Jyk7XG4gICAgICBidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQU1PVU5UKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnR5cGVBcmcsICd0eXBlQXJnIGZpZWxkIG11c3QgZXhpc3QnKTtcbiAgICAgIHNob3VsZC5leGlzdChidy50eXBlQXJnLkJhbGFuY2UsICd0eXBlQXJnLkJhbGFuY2UgbXVzdCBleGlzdCcpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoYncud2l0aGRyYXdGcm9tLCAnd2l0aGRyYXdGcm9tIGZpZWxkIG11c3QgZXhpc3QnKTtcbiAgICAgIHNob3VsZC5leGlzdChcbiAgICAgICAgYncud2l0aGRyYXdGcm9tLlNlbmRlciAhPT0gdW5kZWZpbmVkIHx8IGJ3LndpdGhkcmF3RnJvbS5TcG9uc29yICE9PSB1bmRlZmluZWQsXG4gICAgICAgICd3aXRoZHJhd0Zyb20gbXVzdCBiZSBTZW5kZXIgb3IgU3BvbnNvcidcbiAgICAgICk7XG5cbiAgICAgIC8vIE9sZCBmb3JtYXQgZmllbGRzIG11c3QgTk9UIGV4aXN0IGRpcmVjdGx5IG9uIGJ3XG4gICAgICBzaG91bGQubm90LmV4aXN0KGJ3LmFtb3VudCwgJ29sZCBcImFtb3VudFwiIGZpZWxkIG11c3Qgbm90IGV4aXN0IG9uIEJhbGFuY2VXaXRoZHJhd2FsJyk7XG4gICAgICBzaG91bGQubm90LmV4aXN0KGJ3LnR5cGVfLCAnb2xkIFwidHlwZV9cIiBmaWVsZCBtdXN0IG5vdCBleGlzdCBvbiBCYWxhbmNlV2l0aGRyYXdhbCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIEJDUyBieXRlcyB0aGF0IGRlY29kZSBiYWNrIHRvIEZ1bmRzV2l0aGRyYXdhbCB3aXRoIGNvcnJlY3QgYW1vdW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IFN1aVRyYW5zYWN0aW9uLmRlc2VyaWFsaXplU3VpVHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgICAgY29uc3QgaW5wdXRzID0gZGVzZXJpYWxpemVkLnR4LmlucHV0cyBhcyBhbnlbXTtcblxuICAgICAgY29uc3QgYndJbnB1dCA9IGlucHV0cy5maW5kKFxuICAgICAgICAoaW5wKSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChid0lucHV0LCAnQmFsYW5jZVdpdGhkcmF3YWwgbXVzdCBiZSBwcmVzZW50IGluIGRlc2VyaWFsaXplZCBpbnB1dHMnKTtcblxuICAgICAgY29uc3QgYncgPSBid0lucHV0LkJhbGFuY2VXaXRoZHJhd2FsID8/IGJ3SW5wdXQudmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsO1xuXG4gICAgICAvLyBGdW5kc1dpdGhkcmF3YWwgc3RydWN0dXJlIChub3Qgb2xkIHthbW91bnQsIHR5cGVffSlcbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbiwgJ3Jlc2VydmF0aW9uIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NCwgJ01heEFtb3VudFU2NCBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcbiAgICAgIGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NC50b1N0cmluZygpLnNob3VsZC5lcXVhbChBTU9VTlQpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoYncudHlwZUFyZywgJ3R5cGVBcmcgbXVzdCBzdXJ2aXZlIEJDUyByb3VuZC10cmlwJyk7XG4gICAgICBzaG91bGQuZXhpc3QoYncudHlwZUFyZy5CYWxhbmNlLCAndHlwZUFyZy5CYWxhbmNlIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuXG4gICAgICBzaG91bGQuZXhpc3QoYncud2l0aGRyYXdGcm9tLCAnd2l0aGRyYXdGcm9tIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXJpYWxpemUgdG9Kc29uKCkgd2l0aG91dCBhIEJpZ0ludCByZXBsYWNlciAobm8gVHlwZUVycm9yKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRTcG9uc29yZWRUeFdpdGhBZGRyZXNzQmFsYW5jZSgpO1xuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdyhcbiAgICAgICAgKCkgPT4gSlNPTi5zdHJpbmdpZnkodHgudG9Kc29uKCkpLFxuICAgICAgICAnSlNPTi5zdHJpbmdpZnkodHgudG9Kc29uKCkpIG11c3Qgbm90IHRocm93IOKAlCBCYWxhbmNlV2l0aGRyYXdhbCBhbW91bnQgbXVzdCBub3QgYmUgc3RvcmVkIGFzIEJpZ0ludCdcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIGZ1bmRzSW5BZGRyZXNzQmFsYW5jZSBhbW91bnQgdGhyb3VnaCBmdWxsIHJvdW5kLXRyaXAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gcmVidWlsdFR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgY29uc3QgaW5wdXRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHguaW5wdXRzIGFzIGFueVtdO1xuICAgICAgY29uc3QgYndJbnB1dCA9IGlucHV0cy5maW5kKFxuICAgICAgICAoaW5wKSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChid0lucHV0KTtcbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcbiAgICAgIGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NC50b1N0cmluZygpLnNob3VsZC5lcXVhbChBTU9VTlQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBQYXRoIDJiOiBzZWxmLXBheSwgZW1wdHkgcGF5bWVudCDigJQgdXNlcyB3aXRoZHJhd2FsK3JlZGVlbV9mdW5kcyBpbnN0ZWFkIG9mIFNwbGl0Q29pbnMoR2FzQ29pbiknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBXaXRoIGdhc0RhdGEucGF5bWVudD1bXSB0aGUgcnVudGltZSBleHBvc2VzIG9ubHkgdGhlIGdhcy1idWRnZXQgYW1vdW50IHZpYSBHYXNDb2luIGZvclxuICAgICAgLy8gUFRCIFNwbGl0Q29pbnMgb3BlcmF0aW9ucy4gU3BsaXRDb2lucyhHYXNDb2luLCBbbGFyZ2VfYW1vdW50XSkgYWx3YXlzIGZhaWxzIHdpdGhcbiAgICAgIC8vIEluc3VmZmljaWVudENvaW5CYWxhbmNlIChjb25maXJtZWQgYnkgcHJvZHVjdGlvbiBmYWlsdXJlcyBKRGJueWJvdGczYXguLi4sIEFUVWJlTFgzLi4uKS5cbiAgICAgIC8vIFBhdGggMmIgZml4ZXMgdGhpcyBieSB3aXRoZHJhd2luZyBmcm9tIHRoZSBhZGRyZXNzIGFjY3VtdWxhdG9yIHZpYSByZWRlZW1fZnVuZHMsXG4gICAgICAvLyBzcGxpdHRpbmcgZnJvbSB0aGF0IGNvaW4gb2JqZWN0LCBhbmQgbWVyZ2luZyB0aGUgMC1iYWxhbmNlIHJlbWFpbmRlciBpbnRvIEdhc0NvaW4uXG4gICAgICBjb25zdCBzZWxmUGF5Tm9QYXltZW50ID0geyAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsIHBheW1lbnQ6IFtdIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNlbGZQYXlOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBTU9VTlQpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gR2FzIG93bmVyIG11c3QgZXF1YWwgc2VuZGVyIChzZWxmLXBheSlcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIC8vIFBheW1lbnQgbXVzdCBiZSBlbXB0eSDigJQgZ2FzIGZ1bmRlZCBmcm9tIGFkZHJlc3MgYmFsYW5jZSBieSB0aGUgcnVudGltZVxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIFBhdGggMmI6IEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IE1VU1QgYmUgcHJlc2VudCAod2l0aGRyYXdhbCtyZWRlZW1fZnVuZHMgYXBwcm9hY2gpXG4gICAgICBjb25zdCBpbnB1dHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHMgYXMgYW55W107XG4gICAgICBjb25zdCBid0lucHV0ID0gaW5wdXRzLmZpbmQoXG4gICAgICAgIChpbnApID0+IGlucD8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZCB8fCBpbnA/LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkXG4gICAgICApO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3SW5wdXQsICdQYXRoIDJiOiBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCBtdXN0IGJlIHByZXNlbnQnKTtcbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcbiAgICAgIGJ3LnJlc2VydmF0aW9uLk1heEFtb3VudFU2NC50b1N0cmluZygpLnNob3VsZC5lcXVhbChBTU9VTlQpO1xuXG4gICAgICAvLyBGaXJzdCBjb21tYW5kIG11c3QgYmUgTW92ZUNhbGwocmVkZWVtX2Z1bmRzKSwgTk9UIFNwbGl0Q29pbnMoR2FzQ29pbilcbiAgICAgIGNvbnN0IGNvbW1hbmRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuICAgICAgY29tbWFuZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjb21tYW5kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgLy8gRm9sbG93ZWQgYnk6IFNwbGl0Q29pbnMoYWRkckNvaW4pLCBUcmFuc2Zlck9iamVjdHMsIE1lcmdlQ29pbnMoR2FzQ29pbiwgYWRkckNvaW4pXG4gICAgICBjb21tYW5kc1sxXS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuICAgICAgY29tbWFuZHNbMl0ua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycpO1xuICAgICAgY29tbWFuZHNbM10ua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSBTdWlUcmFuc2FjdGlvbi5kZXNlcmlhbGl6ZVN1aVRyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICAgIGRlc2VyaWFsaXplZC5zZW5kZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIGRlc2VyaWFsaXplZC5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBkZXNlcmlhbGl6ZWQuZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIEJhbGFuY2VXaXRoZHJhd2FsIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcFxuICAgICAgY29uc3QgZGVjb2RlZElucHV0cyA9IGRlc2VyaWFsaXplZC50eC5pbnB1dHMgYXMgYW55W107XG4gICAgICBjb25zdCBkZWNvZGVkQndJbnB1dCA9IGRlY29kZWRJbnB1dHMuZmluZChcbiAgICAgICAgKGlucDogYW55KSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWQgfHwgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZFxuICAgICAgKTtcbiAgICAgIHNob3VsZC5leGlzdChkZWNvZGVkQndJbnB1dCwgJ0JhbGFuY2VXaXRoZHJhd2FsIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCBmb3IgUGF0aCAyYicpO1xuXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMmIgd2l0aCBWYWxpZER1cmluZyBleHBpcmF0aW9uIChzZWxmLXBheSwgZW1wdHkgcGF5bWVudCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBQYXRoIDJiIHdpdGggVmFsaWREdXJpbmcgZXhwaXJhdGlvbiDigJQgcmVxdWlyZWQgd2hlbiBnYXNEYXRhLnBheW1lbnQ9W10gdG8gcHJldmVudFxuICAgICAgLy8gcmVwbGF5IGF0dGFja3MuIFVzZXMgd2l0aGRyYXdhbCtyZWRlZW1fZnVuZHMgdG8gbWF0ZXJpYWxpc2UgdHJhbnNmZXIgYW1vdW50IGZyb20gdGhlXG4gICAgICAvLyBhZGRyZXNzIGFjY3VtdWxhdG9yLCBOT1QgU3BsaXRDb2lucyhHYXNDb2luKSB3aGljaCBmYWlscyB3aXRoIEluc3VmZmljaWVudENvaW5CYWxhbmNlLlxuICAgICAgY29uc3QgR0VORVNJU19DSEFJTl9JRCA9ICdHQUZwQ0NjUkN4VGRGZlVFTWJRYmtMQmFaeTJSTmlHQWZ2RkJoTU5wcTJrVCc7XG4gICAgICBjb25zdCBzZWxmUGF5Tm9QYXltZW50ID0geyAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsIHBheW1lbnQ6IFtdIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNlbGZQYXlOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBTU9VTlQpO1xuICAgICAgdHhCdWlsZGVyLmV4cGlyYXRpb24oe1xuICAgICAgICBWYWxpZER1cmluZzoge1xuICAgICAgICAgIG1pbkVwb2NoOiB7IFNvbWU6IDUwMCB9LFxuICAgICAgICAgIG1heEVwb2NoOiB7IFNvbWU6IDUwMSB9LFxuICAgICAgICAgIG1pblRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgbWF4VGltZXN0YW1wOiB7IE5vbmU6IG51bGwgfSxcbiAgICAgICAgICBjaGFpbjogR0VORVNJU19DSEFJTl9JRCxcbiAgICAgICAgICBub25jZTogMHhkZWFkYmVlZixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gU2VsZi1wYXk6IG93bmVyID09PSBzZW5kZXIsIHBheW1lbnQgZW1wdHlcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBQYXRoIDJiOiBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCBNVVNUIGJlIHByZXNlbnRcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCwgJ1BhdGggMmI6IEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IG11c3QgYmUgcHJlc2VudCcpO1xuXG4gICAgICAvLyBGaXJzdCBjb21tYW5kOiBNb3ZlQ2FsbChyZWRlZW1fZnVuZHMpLCBOT1QgU3BsaXRDb2lucyhHYXNDb2luKVxuICAgICAgY29uc3QgY29tbWFuZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG4gICAgICBjb21tYW5kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIGNvbW1hbmRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgY29uc3QgZGVzZXJpYWxpemVkID0gU3VpVHJhbnNhY3Rpb24uZGVzZXJpYWxpemVTdWlUcmFuc2FjdGlvbihyYXdUeCk7XG4gICAgICBkZXNlcmlhbGl6ZWQuc2VuZGVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBkZXNlcmlhbGl6ZWQuZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIGNvbnN0IGV4cGlyYXRpb24gPSAoZGVzZXJpYWxpemVkLmV4cGlyYXRpb24gYXMgYW55KT8uVmFsaWREdXJpbmc7XG4gICAgICBzaG91bGQuZXhpc3QoZXhwaXJhdGlvbiwgJ1ZhbGlkRHVyaW5nIGV4cGlyYXRpb24gbXVzdCBzdXJ2aXZlIEJDUyByb3VuZC10cmlwJyk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5taW5FcG9jaD8uU29tZSA/PyBleHBpcmF0aW9uLm1pbkVwb2NoKS5zaG91bGQuZXF1YWwoNTAwKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm1heEVwb2NoPy5Tb21lID8/IGV4cGlyYXRpb24ubWF4RXBvY2gpLnNob3VsZC5lcXVhbCg1MDEpO1xuICAgICAgZXhwaXJhdGlvbi5jaGFpbi5zaG91bGQuZXF1YWwoR0VORVNJU19DSEFJTl9JRCk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5ub25jZSkuc2hvdWxkLmVxdWFsKDB4ZGVhZGJlZWYpO1xuXG4gICAgICAvLyBCYWxhbmNlV2l0aGRyYXdhbCBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IGRlY29kZWRJbnB1dHMgPSBkZXNlcmlhbGl6ZWQudHguaW5wdXRzIGFzIGFueVtdO1xuICAgICAgY29uc3QgZGVjb2RlZEJ3SW5wdXQgPSBkZWNvZGVkSW5wdXRzLmZpbmQoXG4gICAgICAgIChpbnA6IGFueSkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoZGVjb2RlZEJ3SW5wdXQsICdCYWxhbmNlV2l0aGRyYXdhbCBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAgZm9yIFBhdGggMmInKTtcblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhbmQgY29ycmVjdGx5IGRlY29kZSBhIE1vdmVDYWxsIHRvIDB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzIHdpdGggQmFsYW5jZVdpdGhkcmF3YWwgYXJnJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCk7XG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgY29uc3QgY29tbWFuZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG5cbiAgICAgIGNvbW1hbmRzWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgY29tbWFuZHNbMF0udGFyZ2V0LnNob3VsZC5lcXVhbCgnMHgyOjpjb2luOjpyZWRlZW1fZnVuZHMnKTtcbiAgICAgIGNvbW1hbmRzWzBdLnR5cGVBcmd1bWVudHNbMF0uc2hvdWxkLmVxdWFsKCcweDI6OnN1aTo6U1VJJyk7XG5cbiAgICAgIC8vIFRoZSBhcmd1bWVudCB0byByZWRlZW1fZnVuZHMgbXVzdCByZWZlcmVuY2UgdGhlIEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IChpbmRleCAwKVxuICAgICAgY29uc3QgYXJnID0gY29tbWFuZHNbMF0uYXJndW1lbnRzWzBdO1xuICAgICAgYXJnLmtpbmQuc2hvdWxkLmVxdWFsKCdJbnB1dCcpO1xuICAgICAgYXJnLmluZGV4LnNob3VsZC5lcXVhbCgwKTtcbiAgICAgIGFyZy50eXBlLnNob3VsZC5lcXVhbCgnb2JqZWN0Jyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==