@bitgo-beta/sdk-coin-sui 3.0.3-beta.172 → 3.0.3-beta.1721

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 +264 -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 +44 -1
  99. package/dist/src/lib/transferBuilder.d.ts.map +1 -1
  100. package/dist/src/lib/transferBuilder.js +208 -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 +125 -10
  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 +250 -20
  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 +463 -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 +774 -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 -390
@@ -0,0 +1,774 @@
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 a self-pay transfer using only address balance (empty payment)', async function () {
294
+ const gasDataNoPayment = {
295
+ ...testData.gasDataWithoutGasPayment,
296
+ payment: [],
297
+ };
298
+ const txBuilder = factory.getTransferBuilder();
299
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
300
+ txBuilder.sender(testData.sender.address);
301
+ txBuilder.send(testData.recipients);
302
+ txBuilder.gasData(gasDataNoPayment);
303
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
304
+ const tx = await txBuilder.build();
305
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
306
+ const suiTx = tx;
307
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
308
+ // Self-pay path: SplitCoins(GasCoin, [amount]) — no MoveCall needed
309
+ const programmableTx = suiTx.suiTransaction.tx;
310
+ programmableTx.transactions[0].kind.should.equal('SplitCoins');
311
+ const rawTx = tx.toBroadcastFormat();
312
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
313
+ // Round-trip: rebuild from raw
314
+ const rebuilder = factory.from(rawTx);
315
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
316
+ const rebuiltTx = await rebuilder.build();
317
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
318
+ });
319
+ it('should build a self-pay transfer with coin objects + address balance', async function () {
320
+ const txBuilder = factory.getTransferBuilder();
321
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
322
+ txBuilder.sender(testData.sender.address);
323
+ txBuilder.send(testData.recipients);
324
+ txBuilder.gasData(testData.gasData);
325
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
326
+ const tx = await txBuilder.build();
327
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
328
+ const suiTx = tx;
329
+ // Self-pay path: SplitCoins(GasCoin) — protocol merges coin objects + address balance automatically
330
+ const programmableTx = suiTx.suiTransaction.tx;
331
+ programmableTx.transactions[0].kind.should.equal('SplitCoins');
332
+ const rawTx = tx.toBroadcastFormat();
333
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
334
+ });
335
+ it('should build a sponsored transfer with coin objects + address balance', async function () {
336
+ const inputObjects = testData.generateObjects(2);
337
+ const sponsoredGasData = {
338
+ ...testData.gasData,
339
+ owner: testData.feePayer.address,
340
+ };
341
+ const txBuilder = factory.getTransferBuilder();
342
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
343
+ txBuilder.sender(testData.sender.address);
344
+ txBuilder.send(testData.recipients);
345
+ txBuilder.gasData(sponsoredGasData);
346
+ txBuilder.inputObjects(inputObjects);
347
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
348
+ const tx = await txBuilder.build();
349
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
350
+ const suiTx = tx;
351
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
352
+ // Sponsored path: MoveCall(redeem_funds) + MergeCoins + SplitCoins
353
+ const programmableTx = suiTx.suiTransaction.tx;
354
+ programmableTx.transactions[0].kind.should.equal('MoveCall');
355
+ programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
356
+ programmableTx.transactions[1].kind.should.equal('MergeCoins');
357
+ programmableTx.transactions[2].kind.should.equal('SplitCoins');
358
+ const rawTx = tx.toBroadcastFormat();
359
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
360
+ // Round-trip
361
+ const rebuilder = factory.from(rawTx);
362
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
363
+ const rebuiltTx = await rebuilder.build();
364
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
365
+ });
366
+ it('should build a sponsored transfer with address balance only (no coin inputObjects)', async function () {
367
+ const sponsoredGasData = {
368
+ ...testData.gasData,
369
+ owner: testData.feePayer.address,
370
+ };
371
+ const txBuilder = factory.getTransferBuilder();
372
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
373
+ txBuilder.sender(testData.sender.address);
374
+ txBuilder.send(testData.recipients);
375
+ txBuilder.gasData(sponsoredGasData);
376
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
377
+ const tx = await txBuilder.build();
378
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
379
+ // Path 1b: withdrawal → redeem_funds → SplitCoins(addrCoin) → TransferObjects
380
+ // Sponsor's gas coins remain in gasData.payment; tx.gas is NOT used for the transfer amount.
381
+ const suiTx = tx;
382
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
383
+ const programmableTx = suiTx.suiTransaction.tx;
384
+ programmableTx.transactions[0].kind.should.equal('MoveCall');
385
+ programmableTx.transactions[0].target.should.equal('0x2::coin::redeem_funds');
386
+ programmableTx.transactions[1].kind.should.equal('SplitCoins');
387
+ const rawTx = tx.toBroadcastFormat();
388
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
389
+ // Round-trip: rebuild from raw
390
+ const rebuilder = factory.from(rawTx);
391
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
392
+ const rebuiltTx = await rebuilder.build();
393
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
394
+ });
395
+ it('should build Path 1b send-all: sponsored addr-balance-only, no change (MergeCoins consumes addrCoin)', async function () {
396
+ // Reproduces the real on-chain failure: UnusedValueWithoutDrop { result_idx: 0 }
397
+ // Occurs when redeem_funds returns addrCoin, SplitCoins drains it completely, and the
398
+ // 0-balance source coin is never consumed. Fix: MergeCoins(gas, [addrCoin]) at the end.
399
+ const SEND_AMOUNT = '1000000'; // 0.001 SUI — same as the failing tx
400
+ const sponsoredGasData = {
401
+ ...testData.gasData,
402
+ owner: testData.feePayer.address,
403
+ };
404
+ const txBuilder = factory.getTransferBuilder();
405
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
406
+ txBuilder.sender(testData.sender.address);
407
+ txBuilder.send([{ address: testData.recipients[0].address, amount: SEND_AMOUNT }]);
408
+ txBuilder.gasData(sponsoredGasData);
409
+ txBuilder.fundsInAddressBalance(SEND_AMOUNT); // send-all: balance == recipient amount
410
+ const tx = await txBuilder.build();
411
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
412
+ const suiTx = tx;
413
+ const cmds = suiTx.suiTransaction.tx.transactions;
414
+ // Expected command sequence for Path 1b send-all:
415
+ // 0: MoveCall (redeem_funds) — withdraw addrCoin
416
+ // 1: SplitCoins(addrCoin) — split recipient amount off addrCoin
417
+ // 2: TransferObjects([split]) — send to recipient
418
+ // 3: MergeCoins(gas, [addrCoin]) — consume the now-zero-balance addrCoin
419
+ cmds[0].kind.should.equal('MoveCall');
420
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
421
+ cmds[1].kind.should.equal('SplitCoins');
422
+ cmds[2].kind.should.equal('TransferObjects');
423
+ cmds[3].kind.should.equal('MergeCoins', 'expected MergeCoins to consume 0-balance addrCoin after send-all');
424
+ // Recipient parsing must not be affected by the trailing MergeCoins
425
+ const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
426
+ recipients.length.should.equal(1);
427
+ recipients[0].address.should.equal(testData.recipients[0].address);
428
+ recipients[0].amount.should.equal(SEND_AMOUNT);
429
+ // Round-trip
430
+ const rawTx = tx.toBroadcastFormat();
431
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
432
+ const rebuilder = factory.from(rawTx);
433
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
434
+ const rebuiltTx = await rebuilder.build();
435
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
436
+ });
437
+ it('should build Path 1b with change: sponsored addr-balance-only, excess returned to sender', async function () {
438
+ // fundsInAddressBalance exceeds the total recipient amount → change must be returned to
439
+ // the sender as an extra TransferObjects([addrCoin], sender). The transaction parser must
440
+ // skip this change transfer and only report actual recipients.
441
+ const SEND_AMOUNT = '100'; // each of the two testData.recipients gets 100
442
+ const EXCESS = '9999900'; // fundsInAddressBalance = 10_000_000, total send = 200
443
+ const FUNDS_BALANCE = (Number(SEND_AMOUNT) * testData.recipients.length + Number(EXCESS)).toString();
444
+ const sponsoredGasData = {
445
+ ...testData.gasData,
446
+ owner: testData.feePayer.address,
447
+ };
448
+ const txBuilder = factory.getTransferBuilder();
449
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
450
+ txBuilder.sender(testData.sender.address);
451
+ txBuilder.send(testData.recipients); // 2 recipients × 100 MIST = 200 MIST total
452
+ txBuilder.gasData(sponsoredGasData);
453
+ txBuilder.fundsInAddressBalance(FUNDS_BALANCE); // 10_000_000 > 200 → has change
454
+ const tx = await txBuilder.build();
455
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
456
+ const suiTx = tx;
457
+ const cmds = suiTx.suiTransaction.tx.transactions;
458
+ // Expected sequence for Path 1b with change (2 recipients):
459
+ // 0: MoveCall (redeem_funds)
460
+ // 1: SplitCoins — recipient 0
461
+ // 2: TransferObjects — recipient 0
462
+ // 3: SplitCoins — recipient 1
463
+ // 4: TransferObjects — recipient 1
464
+ // 5: TransferObjects([addrCoin], sender) — change back to sender
465
+ cmds[0].kind.should.equal('MoveCall');
466
+ cmds[0].target.should.equal('0x2::coin::redeem_funds');
467
+ const lastCmd = cmds[cmds.length - 1];
468
+ lastCmd.kind.should.equal('TransferObjects', 'last command must be the change transfer');
469
+ // The last TransferObjects returns change to the *sender*, not a recipient
470
+ const changeAddrInput = suiTx.suiTransaction.tx.inputs[lastCmd.address.index];
471
+ const changeAddr = utils_1.default.getAddress(changeAddrInput);
472
+ changeAddr.should.equal(testData.sender.address, 'change must go back to sender');
473
+ // Parser must return only the actual recipients, not the change transfer
474
+ const recipients = utils_1.default.getRecipients(suiTx.suiTransaction);
475
+ recipients.length.should.equal(testData.recipients.length);
476
+ recipients[0].address.should.equal(testData.recipients[0].address);
477
+ recipients[0].amount.should.equal(SEND_AMOUNT);
478
+ recipients[1].address.should.equal(testData.recipients[1].address);
479
+ recipients[1].amount.should.equal(SEND_AMOUNT);
480
+ // Round-trip
481
+ const rawTx = tx.toBroadcastFormat();
482
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
483
+ const rebuilder = factory.from(rawTx);
484
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
485
+ const rebuiltTx = await rebuilder.build();
486
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
487
+ });
488
+ it('should build a sponsored tx gas paid from sponsor address balance (empty payment)', async function () {
489
+ const inputObjects = testData.generateObjects(1);
490
+ const sponsoredGasDataNoPayment = {
491
+ payment: [],
492
+ owner: testData.feePayer.address,
493
+ price: testData.gasData.price,
494
+ budget: testData.gasData.budget,
495
+ };
496
+ const txBuilder = factory.getTransferBuilder();
497
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
498
+ txBuilder.sender(testData.sender.address);
499
+ txBuilder.send(testData.recipients);
500
+ txBuilder.gasData(sponsoredGasDataNoPayment);
501
+ txBuilder.inputObjects(inputObjects);
502
+ const tx = await txBuilder.build();
503
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
504
+ const suiTx = tx;
505
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.feePayer.address);
506
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
507
+ // Sponsored path with coin objects, no address balance withdrawal
508
+ const programmableTx = suiTx.suiTransaction.tx;
509
+ programmableTx.transactions[0].kind.should.equal('SplitCoins');
510
+ const rawTx = tx.toBroadcastFormat();
511
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
512
+ });
513
+ it('should round-trip a self-pay transfer with Epoch expiration via fromBytes', async function () {
514
+ // Regression test for the BigInt round-trip bug:
515
+ // BCS.U64 deserializes u64 as BigInt, but the previous superstruct schema used integer()
516
+ // which rejected BigInt, causing fromBytes() to throw a StructError at "expiration".
517
+ // StringEncodedBigint now accepts string | number | bigint, fixing the round-trip.
518
+ const gasDataNoPayment = {
519
+ ...testData.gasDataWithoutGasPayment,
520
+ payment: [],
521
+ };
522
+ const txBuilder = factory.getTransferBuilder();
523
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
524
+ txBuilder.sender(testData.sender.address);
525
+ txBuilder.send(testData.recipients);
526
+ txBuilder.gasData(gasDataNoPayment);
527
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
528
+ txBuilder.expiration({ Epoch: 324 }); // number input
529
+ const tx = await txBuilder.build();
530
+ const rawTx = tx.toBroadcastFormat();
531
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
532
+ // fromBytes must not throw StructError — this was the failing case before the fix
533
+ should_1.default.doesNotThrow(() => {
534
+ const rebuilder = factory.from(rawTx);
535
+ should_1.default.exist(rebuilder);
536
+ });
537
+ // Full round-trip: rebuilt tx must serialize identically
538
+ const rebuilder = factory.from(rawTx);
539
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
540
+ const rebuiltTx = await rebuilder.build();
541
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
542
+ // Epoch value must survive the round-trip regardless of BigInt/number representation
543
+ const rebuiltJson = rebuiltTx.toJson();
544
+ const epochVal = rebuiltJson.expiration?.Epoch;
545
+ should_1.default.exist(epochVal);
546
+ Number(epochVal).should.equal(324);
547
+ });
548
+ it('should round-trip a self-pay transfer with ValidDuring expiration via fromBytes', async function () {
549
+ // Verifies the full 6-field ValidDuringExpiration BCS schema:
550
+ // minEpoch/maxEpoch as Option<u64>, minTimestamp/maxTimestamp as Option<u64> (None),
551
+ // chain as 32-byte Base58 ObjectDigest, nonce as u32.
552
+ // Uses a real mainnet genesis checkpoint digest (32 bytes, Base58).
553
+ const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
554
+ const FUNDS_IN_ADDRESS_BALANCE = '5000000000';
555
+ const gasDataNoPayment = {
556
+ ...testData.gasDataWithoutGasPayment,
557
+ payment: [],
558
+ };
559
+ const txBuilder = factory.getTransferBuilder();
560
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
561
+ txBuilder.sender(testData.sender.address);
562
+ txBuilder.send(testData.recipients);
563
+ txBuilder.gasData(gasDataNoPayment);
564
+ txBuilder.fundsInAddressBalance(FUNDS_IN_ADDRESS_BALANCE);
565
+ txBuilder.expiration({
566
+ ValidDuring: {
567
+ minEpoch: { Some: 500 },
568
+ maxEpoch: { Some: 501 },
569
+ minTimestamp: { None: null },
570
+ maxTimestamp: { None: null },
571
+ chain: GENESIS_CHAIN_ID,
572
+ nonce: 0xdeadbeef,
573
+ },
574
+ });
575
+ const tx = await txBuilder.build();
576
+ const rawTx = tx.toBroadcastFormat();
577
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
578
+ // fromBytes must not throw — ValidDuring fields must survive deserialization
579
+ const rebuilder = factory.from(rawTx);
580
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
581
+ const rebuiltTx = await rebuilder.build();
582
+ // BCS round-trip: serialized bytes must be identical
583
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
584
+ // All ValidDuring fields must survive the round-trip
585
+ const expiration = rebuiltTx.toJson().expiration?.ValidDuring;
586
+ should_1.default.exist(expiration);
587
+ Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
588
+ Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
589
+ expiration.chain.should.equal(GENESIS_CHAIN_ID);
590
+ Number(expiration.nonce).should.equal(0xdeadbeef);
591
+ });
592
+ });
593
+ describe('BalanceWithdrawal BCS encoding (FundsWithdrawal format)', () => {
594
+ const AMOUNT = '100000000'; // 0.1 SUI in MIST
595
+ const sponsoredGasData = {
596
+ ...testData.gasData,
597
+ owner: testData.feePayer.address,
598
+ };
599
+ async function buildSponsoredTxWithAddressBalance() {
600
+ const txBuilder = factory.getTransferBuilder();
601
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
602
+ txBuilder.sender(testData.sender.address);
603
+ txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
604
+ txBuilder.gasData(sponsoredGasData);
605
+ txBuilder.fundsInAddressBalance(AMOUNT);
606
+ return txBuilder.build();
607
+ }
608
+ it('should encode BalanceWithdrawal input with FundsWithdrawal structure (reservation/typeArg/withdrawFrom)', async function () {
609
+ const tx = await buildSponsoredTxWithAddressBalance();
610
+ const suiTx = tx;
611
+ const inputs = suiTx.suiTransaction.tx.inputs;
612
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
613
+ should_1.default.exist(bwInput, 'BalanceWithdrawal input must be present');
614
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
615
+ should_1.default.exist(bw.reservation, 'reservation field must exist');
616
+ should_1.default.exist(bw.reservation.MaxAmountU64, 'reservation.MaxAmountU64 must exist');
617
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
618
+ should_1.default.exist(bw.typeArg, 'typeArg field must exist');
619
+ should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must exist');
620
+ should_1.default.exist(bw.withdrawFrom, 'withdrawFrom field must exist');
621
+ should_1.default.exist(bw.withdrawFrom.Sender !== undefined || bw.withdrawFrom.Sponsor !== undefined, 'withdrawFrom must be Sender or Sponsor');
622
+ // Old format fields must NOT exist directly on bw
623
+ should_1.default.not.exist(bw.amount, 'old "amount" field must not exist on BalanceWithdrawal');
624
+ should_1.default.not.exist(bw.type_, 'old "type_" field must not exist on BalanceWithdrawal');
625
+ });
626
+ it('should produce BCS bytes that decode back to FundsWithdrawal with correct amount', async function () {
627
+ const tx = await buildSponsoredTxWithAddressBalance();
628
+ const rawTx = tx.toBroadcastFormat();
629
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
630
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
631
+ const inputs = deserialized.tx.inputs;
632
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
633
+ should_1.default.exist(bwInput, 'BalanceWithdrawal must be present in deserialized inputs');
634
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
635
+ // FundsWithdrawal structure (not old {amount, type_})
636
+ should_1.default.exist(bw.reservation, 'reservation must survive BCS round-trip');
637
+ should_1.default.exist(bw.reservation.MaxAmountU64, 'MaxAmountU64 must survive BCS round-trip');
638
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
639
+ should_1.default.exist(bw.typeArg, 'typeArg must survive BCS round-trip');
640
+ should_1.default.exist(bw.typeArg.Balance, 'typeArg.Balance must survive BCS round-trip');
641
+ should_1.default.exist(bw.withdrawFrom, 'withdrawFrom must survive BCS round-trip');
642
+ });
643
+ it('should serialize toJson() without a BigInt replacer (no TypeError)', async function () {
644
+ const tx = await buildSponsoredTxWithAddressBalance();
645
+ should_1.default.doesNotThrow(() => JSON.stringify(tx.toJson()), 'JSON.stringify(tx.toJson()) must not throw — BalanceWithdrawal amount must not be stored as BigInt');
646
+ });
647
+ it('should preserve fundsInAddressBalance amount through full round-trip', async function () {
648
+ const tx = await buildSponsoredTxWithAddressBalance();
649
+ const rawTx = tx.toBroadcastFormat();
650
+ const rebuilder = factory.from(rawTx);
651
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
652
+ const rebuiltTx = await rebuilder.build();
653
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
654
+ const suiTx = rebuiltTx;
655
+ const inputs = suiTx.suiTransaction.tx.inputs;
656
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
657
+ should_1.default.exist(bwInput);
658
+ const bw = bwInput.BalanceWithdrawal ?? bwInput.value?.BalanceWithdrawal;
659
+ bw.reservation.MaxAmountU64.toString().should.equal(AMOUNT);
660
+ });
661
+ it('should encode gas-from-address-balance (self-pay, empty payment) with no FundsWithdrawal input', async function () {
662
+ // When gasData.payment=[] and sender===gasData.owner, the Sui runtime automatically
663
+ // uses address balance to fund both gas and the transfer via GasCoin.
664
+ // No BalanceWithdrawal CallArg is needed — the runtime handles it implicitly.
665
+ const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
666
+ const txBuilder = factory.getTransferBuilder();
667
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
668
+ txBuilder.sender(testData.sender.address);
669
+ txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
670
+ txBuilder.gasData(selfPayNoPayment);
671
+ txBuilder.fundsInAddressBalance(AMOUNT);
672
+ const tx = await txBuilder.build();
673
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
674
+ const suiTx = tx;
675
+ // Gas owner must equal sender (self-pay)
676
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
677
+ // Payment must be empty — gas funded from address balance by the runtime
678
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
679
+ // No BalanceWithdrawal input — runtime handles address balance automatically
680
+ const inputs = suiTx.suiTransaction.tx.inputs;
681
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
682
+ should_1.default.not.exist(bwInput, 'self-pay must NOT have a BalanceWithdrawal input — runtime handles it');
683
+ // First command must be SplitCoins(GasCoin) — no redeem_funds needed
684
+ const commands = suiTx.suiTransaction.tx.transactions;
685
+ commands[0].kind.should.equal('SplitCoins');
686
+ const rawTx = tx.toBroadcastFormat();
687
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
688
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
689
+ deserialized.sender.should.equal(testData.sender.address);
690
+ deserialized.gasData.owner.should.equal(testData.sender.address);
691
+ deserialized.gasData.payment.length.should.equal(0);
692
+ // No FundsWithdrawal in decoded inputs — only Pure args
693
+ const decodedInputs = deserialized.tx.inputs;
694
+ decodedInputs
695
+ .every((inp) => inp?.BalanceWithdrawal === undefined && inp?.value?.BalanceWithdrawal === undefined)
696
+ .should.be.true('decoded inputs must contain no FundsWithdrawal for self-pay path');
697
+ const rebuilder = factory.from(rawTx);
698
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
699
+ const rebuiltTx = await rebuilder.build();
700
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
701
+ });
702
+ it('should encode gas-from-address-balance with ValidDuring expiration (self-pay, empty payment)', async function () {
703
+ // When gasData.payment=[] the Sui node requires a ValidDuring expiration to prevent
704
+ // replay attacks. Gas and transfer are both funded from address balance via GasCoin.
705
+ const GENESIS_CHAIN_ID = 'GAFpCCcRCxTdFfUEMbQbkLBaZy2RNiGAfvFBhMNpq2kT';
706
+ const selfPayNoPayment = { ...testData.gasDataWithoutGasPayment, payment: [] };
707
+ const txBuilder = factory.getTransferBuilder();
708
+ txBuilder.type(iface_1.SuiTransactionType.Transfer);
709
+ txBuilder.sender(testData.sender.address);
710
+ txBuilder.send([{ address: testData.recipients[0].address, amount: AMOUNT }]);
711
+ txBuilder.gasData(selfPayNoPayment);
712
+ txBuilder.fundsInAddressBalance(AMOUNT);
713
+ txBuilder.expiration({
714
+ ValidDuring: {
715
+ minEpoch: { Some: 500 },
716
+ maxEpoch: { Some: 501 },
717
+ minTimestamp: { None: null },
718
+ maxTimestamp: { None: null },
719
+ chain: GENESIS_CHAIN_ID,
720
+ nonce: 0xdeadbeef,
721
+ },
722
+ });
723
+ const tx = await txBuilder.build();
724
+ should_1.default.equal(tx.type, sdk_core_1.TransactionType.Send);
725
+ const suiTx = tx;
726
+ // Self-pay: owner === sender, payment empty
727
+ suiTx.suiTransaction.gasData.owner.should.equal(testData.sender.address);
728
+ suiTx.suiTransaction.gasData.payment.length.should.equal(0);
729
+ // No BalanceWithdrawal input — runtime handles GasCoin from address balance
730
+ const inputs = suiTx.suiTransaction.tx.inputs;
731
+ const bwInput = inputs.find((inp) => inp?.BalanceWithdrawal !== undefined || inp?.value?.BalanceWithdrawal !== undefined);
732
+ should_1.default.not.exist(bwInput, 'self-pay must NOT have a BalanceWithdrawal input');
733
+ // First command: SplitCoins(GasCoin) — no redeem_funds for self-pay
734
+ const commands = suiTx.suiTransaction.tx.transactions;
735
+ commands[0].kind.should.equal('SplitCoins');
736
+ const rawTx = tx.toBroadcastFormat();
737
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
738
+ const deserialized = transaction_1.Transaction.deserializeSuiTransaction(rawTx);
739
+ deserialized.sender.should.equal(testData.sender.address);
740
+ deserialized.gasData.payment.length.should.equal(0);
741
+ const expiration = deserialized.expiration?.ValidDuring;
742
+ should_1.default.exist(expiration, 'ValidDuring expiration must survive BCS round-trip');
743
+ Number(expiration.minEpoch?.Some ?? expiration.minEpoch).should.equal(500);
744
+ Number(expiration.maxEpoch?.Some ?? expiration.maxEpoch).should.equal(501);
745
+ expiration.chain.should.equal(GENESIS_CHAIN_ID);
746
+ Number(expiration.nonce).should.equal(0xdeadbeef);
747
+ // Inputs must contain no FundsWithdrawal — only Pure args
748
+ const decodedInputs = deserialized.tx.inputs;
749
+ decodedInputs
750
+ .every((inp) => inp?.BalanceWithdrawal === undefined && inp?.value?.BalanceWithdrawal === undefined)
751
+ .should.be.true('decoded inputs must contain no FundsWithdrawal for self-pay path');
752
+ const rebuilder = factory.from(rawTx);
753
+ rebuilder.addSignature({ pub: testData.sender.publicKey }, Buffer.from(testData.sender.signatureHex));
754
+ const rebuiltTx = await rebuilder.build();
755
+ rebuiltTx.toBroadcastFormat().should.equal(rawTx);
756
+ });
757
+ it('should build and correctly decode a MoveCall to 0x2::coin::redeem_funds with BalanceWithdrawal arg', async function () {
758
+ const tx = await buildSponsoredTxWithAddressBalance();
759
+ const suiTx = tx;
760
+ const commands = suiTx.suiTransaction.tx.transactions;
761
+ commands[0].kind.should.equal('MoveCall');
762
+ commands[0].target.should.equal('0x2::coin::redeem_funds');
763
+ commands[0].typeArguments[0].should.equal('0x2::sui::SUI');
764
+ // The argument to redeem_funds must reference the BalanceWithdrawal input (index 0)
765
+ const arg = commands[0].arguments[0];
766
+ arg.kind.should.equal('Input');
767
+ arg.index.should.equal(0);
768
+ arg.type.should.equal('object');
769
+ const rawTx = tx.toBroadcastFormat();
770
+ should_1.default.equal(utils_1.default.isValidRawTransaction(rawTx), true);
771
+ });
772
+ });
773
+ });
774
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJCdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci90cmFuc2ZlckJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsNERBQXlEO0FBQ3pELDhEQUFnRDtBQUNoRCxvREFBNEI7QUFDNUIsbURBQXVEO0FBQ3ZELG1FQUEyQztBQUMzQyw4REFBNkU7QUFDN0Usa0RBQTZGO0FBQzdGLDBEQUErRTtBQUUvRSxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO0lBQ3BDLE1BQU0sT0FBTyxHQUFHLElBQUEscUNBQWlCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFFMUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUU7UUFDdkIsRUFBRSxDQUFDLDRCQUE0QixFQUFFLEtBQUs7WUFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDL0MsU0FBUyxDQUFDLElBQUksQ0FBQywwQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1QyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDMUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEMsTUFBTSxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSwwQkFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNDLEVBQXNELENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFRLENB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cG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGdldEJ1aWxkZXJGYWN0b3J5IH0gZnJvbSAnLi4vZ2V0QnVpbGRlckZhY3RvcnknO1xuaW1wb3J0ICogYXMgdGVzdERhdGEgZnJvbSAnLi4vLi4vcmVzb3VyY2VzL3N1aSc7XG5pbXBvcnQgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblR5cGUgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vLi4vLi4vc3JjL2xpYi91dGlscyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiBhcyBTdWlUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWIvdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgU3VpVHJhbnNhY3Rpb25UeXBlLCBUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vc3JjL2xpYi9pZmFjZSc7XG5pbXBvcnQgeyBNQVhfQ09NTUFORF9BUkdTLCBNQVhfR0FTX09CSkVDVFMgfSBmcm9tICcuLi8uLi8uLi9zcmMvbGliL2NvbnN0YW50cyc7XG5cbmRlc2NyaWJlKCdTdWkgVHJhbnNmZXIgQnVpbGRlcicsICgpID0+IHtcbiAgY29uc3QgZmFjdG9yeSA9IGdldEJ1aWxkZXJGYWN0b3J5KCd0c3VpJyk7XG5cbiAgZGVzY3JpYmUoJ1N1Y2NlZWQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHRyYW5zZmVyIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEodGVzdERhdGEuZ2FzRGF0YSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgICh0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPikuc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50IS5zaG91bGQuZGVlcEVxdWFsKFxuICAgICAgICB0ZXN0RGF0YS5jb2luc0dhc1BheW1lbnRcbiAgICAgICk7XG5cbiAgICAgIHR4LmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgICAgdHguaW5wdXRzWzBdLnNob3VsZC5kZWVwRXF1YWwoe1xuICAgICAgICBhZGRyZXNzOiB0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6ICh0ZXN0RGF0YS5BTU9VTlQgKiAyKS50b1N0cmluZygpLFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHR4Lm91dHB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYW1vdW50LFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHB1dHNbMV0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMV0uYWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IHRlc3REYXRhLnJlY2lwaWVudHNbMV0uYW1vdW50LFxuICAgICAgICBjb2luOiAndHN1aScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIHNob3VsZC5lcXVhbChyYXdUeCwgdGVzdERhdGEuVFJBTlNGRVIpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNwb25zb3JlZCB0cmFuc2ZlciB0eCB3aXRoIGlucHV0T2JqZWN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGlucHV0T2JqZWN0cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OCcsXG4gICAgICAgICAgdmVyc2lvbjogMTAwLFxuICAgICAgICAgIGRpZ2VzdDogJzJCOFhLUUo3bWZ4UVBVV3FKSkFHanpCQXppdmtXS3EyY0VhM1c4TEx6MXlCJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG9iamVjdElkOiAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMicsXG4gICAgICAgICAgdmVyc2lvbjogMjAwLFxuICAgICAgICAgIGRpZ2VzdDogJ0RvSndYdXo5b1U1WTV2NXZCUmlUZ2lzVlRRdVpRTG1IWldlcUp6ekQ1UVVFJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG5cbiAgICAgIC8vIENyZWF0ZSBnYXMgZGF0YSB3aXRoIGRpZmZlcmVudCBvd25lciAoc3BvbnNvcilcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLCAvLyBEaWZmZXJlbnQgZnJvbSBzZW5kZXJcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7IC8vIFNlbmRlclxuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTsgLy8gR2FzIHBhaWQgYnkgc3BvbnNvclxuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpOyAvLyBSZXF1aXJlZCBmb3Igc3BvbnNvcmVkIHR4XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuXG4gICAgICAvLyBWZXJpZnkgdHJhbnNhY3Rpb24gc3RydWN0dXJlIGZvciBzcG9uc29yZWQgdHJhbnNhY3Rpb25cbiAgICAgIGNvbnN0IHByb2dyYW1tYWJsZVR4ID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHg7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnMubGVuZ3RoLnNob3VsZC5iZS5ncmVhdGVyVGhhbigwKTtcblxuICAgICAgLy8gVmVyaWZ5IHNwb25zb3JlZCB0cmFuc2FjdGlvbiBjaGFyYWN0ZXJpc3RpY3NcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLnNlbmRlci5zaG91bGQuZXF1YWwodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5vd25lci5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyk7XG5cbiAgICAgIC8vIFNob3VsZCBoYXZlIHRyYW5zYWN0aW9ucyBmb3IgbWVyZ2luZy9zcGxpdHRpbmcgYW5kIHRyYW5zZmVycmluZyB3aGVuIHVzaW5nIGlucHV0T2JqZWN0c1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zLmxlbmd0aC5zaG91bGQuYmUuZ3JlYXRlclRoYW4oMCk7XG5cbiAgICAgIC8vIFZlcmlmeSB3ZSBoYXZlIHRyYW5zZmVyIG9wZXJhdGlvbnMgKHRoZSBleGFjdCBzdHJ1Y3R1cmUgdmFyaWVzIHdpdGggQVBJIHZlcnNpb25zKVxuICAgICAgc2hvdWxkLmV4aXN0KHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9ucyk7XG5cbiAgICAgIC8vIFZlcmlmeSBpbnB1dE9iamVjdHMgYXJlIG5vdCB1c2VkIGluIGdhcyBwYXltZW50ICh0aGV5J3JlIHNlcGFyYXRlKVxuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5wYXltZW50LnNob3VsZC5ub3QuY29udGFpbkRlZXAoaW5wdXRPYmplY3RzKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmV4aXN0KHJhd1R4KTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eXBlb2YgcmF3VHgsICdzdHJpbmcnKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcGxpdCBjb2luIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIGNvbnN0IGFtb3VudCA9IDEwMDAwMDAwMDA7XG4gICAgICBjb25zdCByZWNpcGllbnRzID0gbmV3IEFycmF5KDEwMCkuZmlsbCh7IGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLCBhbW91bnQ6IGFtb3VudC50b1N0cmluZygpIH0pO1xuICAgICAgdHhCdWlsZGVyLnNlbmQocmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YSh0ZXN0RGF0YS5nYXNEYXRhKTtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgKHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+KS5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQhLnNob3VsZC5kZWVwRXF1YWwoXG4gICAgICAgIHRlc3REYXRhLmNvaW5zR2FzUGF5bWVudFxuICAgICAgKTtcblxuICAgICAgdHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICB0eC5pbnB1dHNbMF0uc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICB2YWx1ZTogKGFtb3VudCAqIDEwMCkudG9TdHJpbmcoKSxcbiAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgfSk7XG4gICAgICB0eC5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMTAwKTtcbiAgICAgIHR4Lm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PlxuICAgICAgICBvdXRwdXQuc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgICAgdmFsdWU6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGEgc3BsaXQgY29pbiB0eCB3aXRoIG1vcmUgdGhhbiAyNTUgaW5wdXQgb2JqZWN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFtb3VudCA9IDEwMDAwMDAwMDA7XG4gICAgICBjb25zdCBudW1iZXJPZlJlY2lwaWVudHMgPSAxMDtcbiAgICAgIGNvbnN0IG51bWJlck9mUGF5bWVudE9iamVjdHMgPSAxMDAwO1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuXG4gICAgICBjb25zdCByZWNpcGllbnRzID0gbmV3IEFycmF5KG51bWJlck9mUmVjaXBpZW50cykuZmlsbCh7XG4gICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IGFtb3VudC50b1N0cmluZygpLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIHBheW1lbnQ6IHRlc3REYXRhLmdlbmVyYXRlT2JqZWN0cyhudW1iZXJPZlBheW1lbnRPYmplY3RzKSxcbiAgICAgIH07XG5cbiAgICAgIHR4QnVpbGRlci5zZW5kKHJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoZ2FzRGF0YSk7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuXG4gICAgICBhc3NlcnQodHggaW5zdGFuY2VvZiBTdWlUcmFuc2FjdGlvbik7XG4gICAgICB0eC50eXBlLnNob3VsZC5lcXVhbChUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICB0eC5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHR4LmlucHV0c1swXS5zaG91bGQuZGVlcEVxdWFsKHtcbiAgICAgICAgYWRkcmVzczogdGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsXG4gICAgICAgIHZhbHVlOiAoYW1vdW50ICogMTApLnRvU3RyaW5nKCksXG4gICAgICAgIGNvaW46ICd0c3VpJyxcbiAgICAgIH0pO1xuICAgICAgdHgub3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEwKTtcbiAgICAgIHR4Lm91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PlxuICAgICAgICBvdXRwdXQuc2hvdWxkLmRlZXBFcXVhbCh7XG4gICAgICAgICAgY29pbjogJ3RzdWknLFxuICAgICAgICAgIGFkZHJlc3M6IHRlc3REYXRhLnNlbmRlci5hZGRyZXNzLFxuICAgICAgICAgIHZhbHVlOiBhbW91bnQudG9TdHJpbmcoKSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICB0eC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbChnYXNEYXRhLm93bmVyKTtcbiAgICAgIHR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucHJpY2Uuc2hvdWxkLmVxdWFsKGdhc0RhdGEucHJpY2UpO1xuICAgICAgdHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5idWRnZXQuc2hvdWxkLmVxdWFsKGdhc0RhdGEuYnVkZ2V0KTtcbiAgICAgIHR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKE1BWF9HQVNfT0JKRUNUUyAtIDEpO1xuXG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuXG4gICAgICAvLyB0b3RhbCBvYmplY3RzIC0gb2JqZWN0cyBzZW50IGFzIGdhcyBwYXltZW50ICsgbm8uIG9mIHJlY2lwaWVudCBhbW91bnRzKHB1cmUpXG4gICAgICAvLyArIG5vLiBvZiB1bmlxdWUgcmVjaXBpZW50IGFkZHJlc3NlcyhkZS1kdXBlZCBvYmplY3RzKVxuICAgICAgcHJvZ3JhbW1hYmxlVHguaW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoXG4gICAgICAgIG51bWJlck9mUGF5bWVudE9iamVjdHMgLSAoTUFYX0dBU19PQkpFQ1RTIC0gMSkgKyBudW1iZXJPZlJlY2lwaWVudHMgKyAxXG4gICAgICApO1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzBdLmtpbmQuc2hvdWxkLmVxdWFsKCdNZXJnZUNvaW5zJyk7XG4gICAgICBwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0uc291cmNlcy5sZW5ndGguc2hvdWxkLmVxdWFsKE1BWF9DT01NQU5EX0FSR1MgLSAxKTtcbiAgICAgIHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1sxXS5raW5kLnNob3VsZC5lcXVhbCgnTWVyZ2VDb2lucycpO1xuICAgICAgcHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdLnNvdXJjZXMubGVuZ3RoLnNob3VsZC5lcXVhbChcbiAgICAgICAgbnVtYmVyT2ZQYXltZW50T2JqZWN0cyAtIChNQVhfQ09NTUFORF9BUkdTIC0gMSkgLSAoTUFYX0dBU19PQkpFQ1RTIC0gMSlcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICAgIHJlYnVpbHRUeC50b0pzb24oKS5nYXNEYXRhLnBheW1lbnQubGVuZ3RoLnNob3VsZC5lcXVhbChudW1iZXJPZlBheW1lbnRPYmplY3RzKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0ZhaWwnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBmYWlsIGZvciBpbnZhbGlkIHNlbmRlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgc2hvdWxkKCgpID0+IGJ1aWxkZXIuc2VuZGVyKCdyYW5kb21TdHJpbmcnKSkudGhyb3dFcnJvcignSW52YWxpZCBvciBtaXNzaW5nIHNlbmRlciwgZ290OiByYW5kb21TdHJpbmcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBwYXlUeCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgc2hvdWxkKCgpID0+IGJ1aWxkZXIuc2VuZChbdGVzdERhdGEuaW52YWxpZFJlY2lwaWVudHNbMF1dKSkudGhyb3dFcnJvcihcbiAgICAgICAgJ0ludmFsaWQgb3IgbWlzc2luZyBhZGRyZXNzLCBnb3Q6IHJhbmRvbVN0cmluZydcbiAgICAgICk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5zZW5kKFt0ZXN0RGF0YS5pbnZhbGlkUmVjaXBpZW50c1sxXV0pKS50aHJvd0Vycm9yKCdJbnZhbGlkIHJlY2lwaWVudCBhbW91bnQnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBnYXNEYXRhJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmludmFsaWRHYXNPd25lcikpLnRocm93RXJyb3IoXG4gICAgICAgIGBJbnZhbGlkIGdhcyBhZGRyZXNzICR7dGVzdERhdGEuaW52YWxpZEdhc093bmVyLm93bmVyfWBcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgZm9yIGludmFsaWQgZ2FzQnVkZ2V0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmludmFsaWRHYXNCdWRnZXQpKS50aHJvd0Vycm9yKCdJbnZhbGlkIGdhcyBidWRnZXQgLTEnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBnYXNQYXltZW50JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICBjb25zdCBpbnZhbGlkR2FzUGF5bWVudCA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YVdpdGhvdXRHYXNQYXltZW50LFxuICAgICAgICBwYXltZW50OiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgb2JqZWN0SWQ6ICcnLFxuICAgICAgICAgICAgdmVyc2lvbjogLTEsXG4gICAgICAgICAgICBkaWdlc3Q6ICcnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgICAgc2hvdWxkKCgpID0+IGJ1aWxkZXIuZ2FzRGF0YShpbnZhbGlkR2FzUGF5bWVudCkpLnRocm93RXJyb3IoJ0ludmFsaWQgcGF5bWVudCwgaW52YWxpZCBvciBtaXNzaW5nIHZlcnNpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBmb3IgaW52YWxpZCBpbnB1dE9iamVjdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBidWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIGNvbnN0IGludmFsaWRJbnB1dE9iamVjdHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBvYmplY3RJZDogJycsXG4gICAgICAgICAgdmVyc2lvbjogLTEsXG4gICAgICAgICAgZGlnZXN0OiAnJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBzaG91bGQoKCkgPT4gYnVpbGRlci5pbnB1dE9iamVjdHMoaW52YWxpZElucHV0T2JqZWN0cykpLnRocm93RXJyb3IoXG4gICAgICAgICdJbnZhbGlkIGlucHV0IG9iamVjdCwgaW52YWxpZCBvciBtaXNzaW5nIHZlcnNpb24nXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCB0cmFuc2ZlciB3aXRoIGRpZmZlcmVudCBnYXMgb3duZXIgYnV0IG5vIGlucHV0T2JqZWN0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNwb25zb3JlZEdhc0RhdGEgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGEsXG4gICAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLCAvLyBEaWZmZXJlbnQgZnJvbSBzZW5kZXJcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7IC8vIFNlbmRlclxuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTsgLy8gR2FzIHBhaWQgYnkgc3BvbnNvclxuICAgICAgLy8gTm90ZTogTk9UIHByb3ZpZGluZyBpbnB1dE9iamVjdHMgLSBzaG91bGQgc3RpbGwgd29yayAoZmVlIHNwb25zb3JzaGlwIHdpdGhvdXQgY29pbiBzcG9uc29yc2hpcClcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBzaG91bGQubm90LmV4aXN0KHN1aVR4LnN1aVRyYW5zYWN0aW9uLmlucHV0T2JqZWN0cyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZXh0cmFjdCBpbnB1dE9iamVjdHMgZnJvbSB0cmFuc2FjdGlvbiBkYXRhIHZpYSB0b0pzb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dE9iamVjdHMgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBvYmplY3RJZDogJzB4MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OCcsXG4gICAgICAgICAgdmVyc2lvbjogMTAwLFxuICAgICAgICAgIGRpZ2VzdDogJzJCOFhLUUo3bWZ4UVBVV3FKSkFHanpCQXppdmtXS3EyY0VhM1c4TEx6MXlCJyxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcywgLy8gRGlmZmVyZW50IGZyb20gc2VuZGVyXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5pbnB1dE9iamVjdHMoaW5wdXRPYmplY3RzKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgICAgLy8gVGVzdCB0aGF0IHRvSnNvbiBleHRyYWN0cyBpbnB1dE9iamVjdHMgZnJvbSB0cmFuc2FjdGlvbiBzdHJ1Y3R1cmVcbiAgICAgIGNvbnN0IHR4RGF0YSA9ICh0eCBhcyBhbnkpLnRvSnNvbigpO1xuICAgICAgc2hvdWxkLmV4aXN0KHR4RGF0YS5pbnB1dE9iamVjdHMpO1xuXG4gICAgICAvLyBUaGUgdG9Kc29uIHNob3VsZCBleHRyYWN0IHRoZSBpbnB1dE9iamVjdHMgZnJvbSB0aGUgdHJhbnNhY3Rpb24gc3RydWN0dXJlXG4gICAgICAvLyBUaGlzIHRlc3RzIG91ciBuZXcgZ2V0SW5wdXRPYmplY3RzRnJvbVR4IG1ldGhvZFxuICAgICAgc2hvdWxkLmV4aXN0KHR4RGF0YS5pbnB1dE9iamVjdHMpO1xuICAgICAgQXJyYXkuaXNBcnJheSh0eERhdGEuaW5wdXRPYmplY3RzKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdmdW5kc0luQWRkcmVzc0JhbGFuY2UnLCAoKSA9PiB7XG4gICAgY29uc3QgRlVORFNfSU5fQUREUkVTU19CQUxBTkNFID0gJzUwMDAwMDAwMDAnOyAvLyA1IFNVSVxuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBhIHNlbGYtcGF5IHRyYW5zZmVyIHVzaW5nIG9ubHkgYWRkcmVzcyBiYWxhbmNlIChlbXB0eSBwYXltZW50KScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQubGVuZ3RoLnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgLy8gU2VsZi1wYXkgcGF0aDogU3BsaXRDb2lucyhHYXNDb2luLCBbYW1vdW50XSkg4oCUIG5vIE1vdmVDYWxsIG5lZWRlZFxuICAgICAgY29uc3QgcHJvZ3JhbW1hYmxlVHggPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eDtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMF0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXA6IHJlYnVpbGQgZnJvbSByYXdcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzZWxmLXBheSB0cmFuc2ZlciB3aXRoIGNvaW4gb2JqZWN0cyArIGFkZHJlc3MgYmFsYW5jZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHRlc3REYXRhLmdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gU2VsZi1wYXkgcGF0aDogU3BsaXRDb2lucyhHYXNDb2luKSDigJQgcHJvdG9jb2wgbWVyZ2VzIGNvaW4gb2JqZWN0cyArIGFkZHJlc3MgYmFsYW5jZSBhdXRvbWF0aWNhbGx5XG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcG9uc29yZWQgdHJhbnNmZXIgd2l0aCBjb2luIG9iamVjdHMgKyBhZGRyZXNzIGJhbGFuY2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dE9iamVjdHMgPSB0ZXN0RGF0YS5nZW5lcmF0ZU9iamVjdHMoMik7XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmlucHV0T2JqZWN0cyhpbnB1dE9iamVjdHMpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19JTl9BRERSRVNTX0JBTEFOQ0UpO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MpO1xuXG4gICAgICAvLyBTcG9uc29yZWQgcGF0aDogTW92ZUNhbGwocmVkZWVtX2Z1bmRzKSArIE1lcmdlQ29pbnMgKyBTcGxpdENvaW5zXG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICAocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdIGFzIGFueSkua2luZC5zaG91bGQuZXF1YWwoJ01lcmdlQ29pbnMnKTtcbiAgICAgIChwcm9ncmFtbWFibGVUeC50cmFuc2FjdGlvbnNbMl0gYXMgYW55KS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcG9uc29yZWQgdHJhbnNmZXIgd2l0aCBhZGRyZXNzIGJhbGFuY2Ugb25seSAobm8gY29pbiBpbnB1dE9iamVjdHMpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3BvbnNvcmVkR2FzRGF0YSA9IHtcbiAgICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzcG9uc29yZWRHYXNEYXRhKTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIC8vIFBhdGggMWI6IHdpdGhkcmF3YWwg4oaSIHJlZGVlbV9mdW5kcyDihpIgU3BsaXRDb2lucyhhZGRyQ29pbikg4oaSIFRyYW5zZmVyT2JqZWN0c1xuICAgICAgLy8gU3BvbnNvcidzIGdhcyBjb2lucyByZW1haW4gaW4gZ2FzRGF0YS5wYXltZW50OyB0eC5nYXMgaXMgTk9UIHVzZWQgZm9yIHRoZSB0cmFuc2ZlciBhbW91bnQuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5vd25lci5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyk7XG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdNb3ZlQ2FsbCcpO1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICAocHJvZ3JhbW1hYmxlVHgudHJhbnNhY3Rpb25zWzFdIGFzIGFueSkua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwOiByZWJ1aWxkIGZyb20gcmF3XG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMWIgc2VuZC1hbGw6IHNwb25zb3JlZCBhZGRyLWJhbGFuY2Utb25seSwgbm8gY2hhbmdlIChNZXJnZUNvaW5zIGNvbnN1bWVzIGFkZHJDb2luKScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFJlcHJvZHVjZXMgdGhlIHJlYWwgb24tY2hhaW4gZmFpbHVyZTogVW51c2VkVmFsdWVXaXRob3V0RHJvcCB7IHJlc3VsdF9pZHg6IDAgfVxuICAgICAgLy8gT2NjdXJzIHdoZW4gcmVkZWVtX2Z1bmRzIHJldHVybnMgYWRkckNvaW4sIFNwbGl0Q29pbnMgZHJhaW5zIGl0IGNvbXBsZXRlbHksIGFuZCB0aGVcbiAgICAgIC8vIDAtYmFsYW5jZSBzb3VyY2UgY29pbiBpcyBuZXZlciBjb25zdW1lZC4gIEZpeDogTWVyZ2VDb2lucyhnYXMsIFthZGRyQ29pbl0pIGF0IHRoZSBlbmQuXG4gICAgICBjb25zdCBTRU5EX0FNT1VOVCA9ICcxMDAwMDAwJzsgLy8gMC4wMDEgU1VJIOKAlCBzYW1lIGFzIHRoZSBmYWlsaW5nIHR4XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogU0VORF9BTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKFNFTkRfQU1PVU5UKTsgLy8gc2VuZC1hbGw6IGJhbGFuY2UgPT0gcmVjaXBpZW50IGFtb3VudFxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGNtZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG5cbiAgICAgIC8vIEV4cGVjdGVkIGNvbW1hbmQgc2VxdWVuY2UgZm9yIFBhdGggMWIgc2VuZC1hbGw6XG4gICAgICAvLyAgIDA6IE1vdmVDYWxsIChyZWRlZW1fZnVuZHMpICAgICDigJQgd2l0aGRyYXcgYWRkckNvaW5cbiAgICAgIC8vICAgMTogU3BsaXRDb2lucyhhZGRyQ29pbikgICAgICAgIOKAlCBzcGxpdCByZWNpcGllbnQgYW1vdW50IG9mZiBhZGRyQ29pblxuICAgICAgLy8gICAyOiBUcmFuc2Zlck9iamVjdHMoW3NwbGl0XSkgICAg4oCUIHNlbmQgdG8gcmVjaXBpZW50XG4gICAgICAvLyAgIDM6IE1lcmdlQ29pbnMoZ2FzLCBbYWRkckNvaW5dKSDigJQgY29uc3VtZSB0aGUgbm93LXplcm8tYmFsYW5jZSBhZGRyQ29pblxuICAgICAgY21kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnTW92ZUNhbGwnKTtcbiAgICAgIGNtZHNbMF0udGFyZ2V0LnNob3VsZC5lcXVhbCgnMHgyOjpjb2luOjpyZWRlZW1fZnVuZHMnKTtcbiAgICAgIGNtZHNbMV0ua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcbiAgICAgIGNtZHNbMl0ua2luZC5zaG91bGQuZXF1YWwoJ1RyYW5zZmVyT2JqZWN0cycpO1xuICAgICAgY21kc1szXS5raW5kLnNob3VsZC5lcXVhbCgnTWVyZ2VDb2lucycsICdleHBlY3RlZCBNZXJnZUNvaW5zIHRvIGNvbnN1bWUgMC1iYWxhbmNlIGFkZHJDb2luIGFmdGVyIHNlbmQtYWxsJyk7XG5cbiAgICAgIC8vIFJlY2lwaWVudCBwYXJzaW5nIG11c3Qgbm90IGJlIGFmZmVjdGVkIGJ5IHRoZSB0cmFpbGluZyBNZXJnZUNvaW5zXG4gICAgICBjb25zdCByZWNpcGllbnRzID0gdXRpbHMuZ2V0UmVjaXBpZW50cyhzdWlUeC5zdWlUcmFuc2FjdGlvbik7XG4gICAgICByZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICByZWNpcGllbnRzWzBdLmFkZHJlc3Muc2hvdWxkLmVxdWFsKHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICByZWNpcGllbnRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoU0VORF9BTU9VTlQpO1xuXG4gICAgICAvLyBSb3VuZC10cmlwXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIFBhdGggMWIgd2l0aCBjaGFuZ2U6IHNwb25zb3JlZCBhZGRyLWJhbGFuY2Utb25seSwgZXhjZXNzIHJldHVybmVkIHRvIHNlbmRlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIGZ1bmRzSW5BZGRyZXNzQmFsYW5jZSBleGNlZWRzIHRoZSB0b3RhbCByZWNpcGllbnQgYW1vdW50IOKGkiBjaGFuZ2UgbXVzdCBiZSByZXR1cm5lZCB0b1xuICAgICAgLy8gdGhlIHNlbmRlciBhcyBhbiBleHRyYSBUcmFuc2Zlck9iamVjdHMoW2FkZHJDb2luXSwgc2VuZGVyKS4gIFRoZSB0cmFuc2FjdGlvbiBwYXJzZXIgbXVzdFxuICAgICAgLy8gc2tpcCB0aGlzIGNoYW5nZSB0cmFuc2ZlciBhbmQgb25seSByZXBvcnQgYWN0dWFsIHJlY2lwaWVudHMuXG4gICAgICBjb25zdCBTRU5EX0FNT1VOVCA9ICcxMDAnOyAvLyBlYWNoIG9mIHRoZSB0d28gdGVzdERhdGEucmVjaXBpZW50cyBnZXRzIDEwMFxuICAgICAgY29uc3QgRVhDRVNTID0gJzk5OTk5MDAnOyAvLyBmdW5kc0luQWRkcmVzc0JhbGFuY2UgPSAxMF8wMDBfMDAwLCB0b3RhbCBzZW5kID0gMjAwXG4gICAgICBjb25zdCBGVU5EU19CQUxBTkNFID0gKE51bWJlcihTRU5EX0FNT1VOVCkgKiB0ZXN0RGF0YS5yZWNpcGllbnRzLmxlbmd0aCArIE51bWJlcihFWENFU1MpKS50b1N0cmluZygpO1xuXG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgICAuLi50ZXN0RGF0YS5nYXNEYXRhLFxuICAgICAgICBvd25lcjogdGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZCh0ZXN0RGF0YS5yZWNpcGllbnRzKTsgLy8gMiByZWNpcGllbnRzIMOXIDEwMCBNSVNUID0gMjAwIE1JU1QgdG90YWxcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNwb25zb3JlZEdhc0RhdGEpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShGVU5EU19CQUxBTkNFKTsgLy8gMTBfMDAwXzAwMCA+IDIwMCDihpIgaGFzIGNoYW5nZVxuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGNtZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG5cbiAgICAgIC8vIEV4cGVjdGVkIHNlcXVlbmNlIGZvciBQYXRoIDFiIHdpdGggY2hhbmdlICgyIHJlY2lwaWVudHMpOlxuICAgICAgLy8gICAwOiBNb3ZlQ2FsbCAocmVkZWVtX2Z1bmRzKVxuICAgICAgLy8gICAxOiBTcGxpdENvaW5zICDigJQgIHJlY2lwaWVudCAwXG4gICAgICAvLyAgIDI6IFRyYW5zZmVyT2JqZWN0cyAg4oCUICByZWNpcGllbnQgMFxuICAgICAgLy8gICAzOiBTcGxpdENvaW5zICDigJQgIHJlY2lwaWVudCAxXG4gICAgICAvLyAgIDQ6IFRyYW5zZmVyT2JqZWN0cyAg4oCUICByZWNpcGllbnQgMVxuICAgICAgLy8gICA1OiBUcmFuc2Zlck9iamVjdHMoW2FkZHJDb2luXSwgc2VuZGVyKSAg4oCUICBjaGFuZ2UgYmFjayB0byBzZW5kZXJcbiAgICAgIGNtZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjbWRzWzBdLnRhcmdldC5zaG91bGQuZXF1YWwoJzB4Mjo6Y29pbjo6cmVkZWVtX2Z1bmRzJyk7XG4gICAgICBjb25zdCBsYXN0Q21kID0gY21kc1tjbWRzLmxlbmd0aCAtIDFdO1xuICAgICAgbGFzdENtZC5raW5kLnNob3VsZC5lcXVhbCgnVHJhbnNmZXJPYmplY3RzJywgJ2xhc3QgY29tbWFuZCBtdXN0IGJlIHRoZSBjaGFuZ2UgdHJhbnNmZXInKTtcblxuICAgICAgLy8gVGhlIGxhc3QgVHJhbnNmZXJPYmplY3RzIHJldHVybnMgY2hhbmdlIHRvIHRoZSAqc2VuZGVyKiwgbm90IGEgcmVjaXBpZW50XG4gICAgICBjb25zdCBjaGFuZ2VBZGRySW5wdXQgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHNbbGFzdENtZC5hZGRyZXNzLmluZGV4XSBhcyBhbnk7XG4gICAgICBjb25zdCBjaGFuZ2VBZGRyID0gdXRpbHMuZ2V0QWRkcmVzcyhjaGFuZ2VBZGRySW5wdXQpO1xuICAgICAgY2hhbmdlQWRkci5zaG91bGQuZXF1YWwodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MsICdjaGFuZ2UgbXVzdCBnbyBiYWNrIHRvIHNlbmRlcicpO1xuXG4gICAgICAvLyBQYXJzZXIgbXVzdCByZXR1cm4gb25seSB0aGUgYWN0dWFsIHJlY2lwaWVudHMsIG5vdCB0aGUgY2hhbmdlIHRyYW5zZmVyXG4gICAgICBjb25zdCByZWNpcGllbnRzID0gdXRpbHMuZ2V0UmVjaXBpZW50cyhzdWlUeC5zdWlUcmFuc2FjdGlvbik7XG4gICAgICByZWNpcGllbnRzLmxlbmd0aC5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50cy5sZW5ndGgpO1xuICAgICAgcmVjaXBpZW50c1swXS5hZGRyZXNzLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MpO1xuICAgICAgcmVjaXBpZW50c1swXS5hbW91bnQuc2hvdWxkLmVxdWFsKFNFTkRfQU1PVU5UKTtcbiAgICAgIHJlY2lwaWVudHNbMV0uYWRkcmVzcy5zaG91bGQuZXF1YWwodGVzdERhdGEucmVjaXBpZW50c1sxXS5hZGRyZXNzKTtcbiAgICAgIHJlY2lwaWVudHNbMV0uYW1vdW50LnNob3VsZC5lcXVhbChTRU5EX0FNT1VOVCk7XG5cbiAgICAgIC8vIFJvdW5kLXRyaXBcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYSBzcG9uc29yZWQgdHggZ2FzIHBhaWQgZnJvbSBzcG9uc29yIGFkZHJlc3MgYmFsYW5jZSAoZW1wdHkgcGF5bWVudCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dE9iamVjdHMgPSB0ZXN0RGF0YS5nZW5lcmF0ZU9iamVjdHMoMSk7XG4gICAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhTm9QYXltZW50ID0ge1xuICAgICAgICBwYXltZW50OiBbXSxcbiAgICAgICAgb3duZXI6IHRlc3REYXRhLmZlZVBheWVyLmFkZHJlc3MsXG4gICAgICAgIHByaWNlOiB0ZXN0RGF0YS5nYXNEYXRhLnByaWNlLFxuICAgICAgICBidWRnZXQ6IHRlc3REYXRhLmdhc0RhdGEuYnVkZ2V0LFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKHRlc3REYXRhLnJlY2lwaWVudHMpO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YU5vUGF5bWVudCk7XG4gICAgICB0eEJ1aWxkZXIuaW5wdXRPYmplY3RzKGlucHV0T2JqZWN0cyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBzaG91bGQuZXF1YWwodHgudHlwZSwgVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHR4IGFzIFN1aVRyYW5zYWN0aW9uPFRyYW5zZmVyUHJvZ3JhbW1hYmxlVHJhbnNhY3Rpb24+O1xuICAgICAgc3VpVHguc3VpVHJhbnNhY3Rpb24uZ2FzRGF0YS5vd25lci5zaG91bGQuZXF1YWwodGVzdERhdGEuZmVlUGF5ZXIuYWRkcmVzcyk7XG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLnBheW1lbnQubGVuZ3RoLnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgLy8gU3BvbnNvcmVkIHBhdGggd2l0aCBjb2luIG9iamVjdHMsIG5vIGFkZHJlc3MgYmFsYW5jZSB3aXRoZHJhd2FsXG4gICAgICBjb25zdCBwcm9ncmFtbWFibGVUeCA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4O1xuICAgICAgKHByb2dyYW1tYWJsZVR4LnRyYW5zYWN0aW9uc1swXSBhcyBhbnkpLmtpbmQuc2hvdWxkLmVxdWFsKCdTcGxpdENvaW5zJyk7XG5cbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNlbGYtcGF5IHRyYW5zZmVyIHdpdGggRXBvY2ggZXhwaXJhdGlvbiB2aWEgZnJvbUJ5dGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gUmVncmVzc2lvbiB0ZXN0IGZvciB0aGUgQmlnSW50IHJvdW5kLXRyaXAgYnVnOlxuICAgICAgLy8gQkNTLlU2NCBkZXNlcmlhbGl6ZXMgdTY0IGFzIEJpZ0ludCwgYnV0IHRoZSBwcmV2aW91cyBzdXBlcnN0cnVjdCBzY2hlbWEgdXNlZCBpbnRlZ2VyKClcbiAgICAgIC8vIHdoaWNoIHJlamVjdGVkIEJpZ0ludCwgY2F1c2luZyBmcm9tQnl0ZXMoKSB0byB0aHJvdyBhIFN0cnVjdEVycm9yIGF0IFwiZXhwaXJhdGlvblwiLlxuICAgICAgLy8gU3RyaW5nRW5jb2RlZEJpZ2ludCBub3cgYWNjZXB0cyBzdHJpbmcgfCBudW1iZXIgfCBiaWdpbnQsIGZpeGluZyB0aGUgcm91bmQtdHJpcC5cbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcbiAgICAgIHR4QnVpbGRlci5leHBpcmF0aW9uKHsgRXBvY2g6IDMyNCB9KTsgLy8gbnVtYmVyIGlucHV0XG5cbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIC8vIGZyb21CeXRlcyBtdXN0IG5vdCB0aHJvdyBTdHJ1Y3RFcnJvciDigJQgdGhpcyB3YXMgdGhlIGZhaWxpbmcgY2FzZSBiZWZvcmUgdGhlIGZpeFxuICAgICAgc2hvdWxkLmRvZXNOb3RUaHJvdygoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICAgIHNob3VsZC5leGlzdChyZWJ1aWxkZXIpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIEZ1bGwgcm91bmQtdHJpcDogcmVidWlsdCB0eCBtdXN0IHNlcmlhbGl6ZSBpZGVudGljYWxseVxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICAvLyBFcG9jaCB2YWx1ZSBtdXN0IHN1cnZpdmUgdGhlIHJvdW5kLXRyaXAgcmVnYXJkbGVzcyBvZiBCaWdJbnQvbnVtYmVyIHJlcHJlc2VudGF0aW9uXG4gICAgICBjb25zdCByZWJ1aWx0SnNvbiA9IHJlYnVpbHRUeC50b0pzb24oKTtcbiAgICAgIGNvbnN0IGVwb2NoVmFsID0gKHJlYnVpbHRKc29uLmV4cGlyYXRpb24gYXMgYW55KT8uRXBvY2g7XG4gICAgICBzaG91bGQuZXhpc3QoZXBvY2hWYWwpO1xuICAgICAgTnVtYmVyKGVwb2NoVmFsKS5zaG91bGQuZXF1YWwoMzI0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNlbGYtcGF5IHRyYW5zZmVyIHdpdGggVmFsaWREdXJpbmcgZXhwaXJhdGlvbiB2aWEgZnJvbUJ5dGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVmVyaWZpZXMgdGhlIGZ1bGwgNi1maWVsZCBWYWxpZER1cmluZ0V4cGlyYXRpb24gQkNTIHNjaGVtYTpcbiAgICAgIC8vICAgbWluRXBvY2gvbWF4RXBvY2ggYXMgT3B0aW9uPHU2ND4sIG1pblRpbWVzdGFtcC9tYXhUaW1lc3RhbXAgYXMgT3B0aW9uPHU2ND4gKE5vbmUpLFxuICAgICAgLy8gICBjaGFpbiBhcyAzMi1ieXRlIEJhc2U1OCBPYmplY3REaWdlc3QsIG5vbmNlIGFzIHUzMi5cbiAgICAgIC8vIFVzZXMgYSByZWFsIG1haW5uZXQgZ2VuZXNpcyBjaGVja3BvaW50IGRpZ2VzdCAoMzIgYnl0ZXMsIEJhc2U1OCkuXG4gICAgICBjb25zdCBHRU5FU0lTX0NIQUlOX0lEID0gJ0dBRnBDQ2NSQ3hUZEZmVUVNYlFia0xCYVp5MlJOaUdBZnZGQmhNTnBxMmtUJztcbiAgICAgIGNvbnN0IEZVTkRTX0lOX0FERFJFU1NfQkFMQU5DRSA9ICc1MDAwMDAwMDAwJztcbiAgICAgIGNvbnN0IGdhc0RhdGFOb1BheW1lbnQgPSB7XG4gICAgICAgIC4uLnRlc3REYXRhLmdhc0RhdGFXaXRob3V0R2FzUGF5bWVudCxcbiAgICAgICAgcGF5bWVudDogW10sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQodGVzdERhdGEucmVjaXBpZW50cyk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShnYXNEYXRhTm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoRlVORFNfSU5fQUREUkVTU19CQUxBTkNFKTtcbiAgICAgIHR4QnVpbGRlci5leHBpcmF0aW9uKHtcbiAgICAgICAgVmFsaWREdXJpbmc6IHtcbiAgICAgICAgICBtaW5FcG9jaDogeyBTb21lOiA1MDAgfSxcbiAgICAgICAgICBtYXhFcG9jaDogeyBTb21lOiA1MDEgfSxcbiAgICAgICAgICBtaW5UaW1lc3RhbXA6IHsgTm9uZTogbnVsbCB9LFxuICAgICAgICAgIG1heFRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgY2hhaW46IEdFTkVTSVNfQ0hBSU5fSUQsXG4gICAgICAgICAgbm9uY2U6IDB4ZGVhZGJlZWYsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHJhd1R4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh1dGlscy5pc1ZhbGlkUmF3VHJhbnNhY3Rpb24ocmF3VHgpLCB0cnVlKTtcblxuICAgICAgLy8gZnJvbUJ5dGVzIG11c3Qgbm90IHRocm93IOKAlCBWYWxpZER1cmluZyBmaWVsZHMgbXVzdCBzdXJ2aXZlIGRlc2VyaWFsaXphdGlvblxuICAgICAgY29uc3QgcmVidWlsZGVyID0gZmFjdG9yeS5mcm9tKHJhd1R4KTtcbiAgICAgIHJlYnVpbGRlci5hZGRTaWduYXR1cmUoeyBwdWI6IHRlc3REYXRhLnNlbmRlci5wdWJsaWNLZXkgfSwgQnVmZmVyLmZyb20odGVzdERhdGEuc2VuZGVyLnNpZ25hdHVyZUhleCkpO1xuICAgICAgY29uc3QgcmVidWlsdFR4ID0gYXdhaXQgcmVidWlsZGVyLmJ1aWxkKCk7XG5cbiAgICAgIC8vIEJDUyByb3VuZC10cmlwOiBzZXJpYWxpemVkIGJ5dGVzIG11c3QgYmUgaWRlbnRpY2FsXG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICAvLyBBbGwgVmFsaWREdXJpbmcgZmllbGRzIG11c3Qgc3Vydml2ZSB0aGUgcm91bmQtdHJpcFxuICAgICAgY29uc3QgZXhwaXJhdGlvbiA9IChyZWJ1aWx0VHgudG9Kc29uKCkuZXhwaXJhdGlvbiBhcyBhbnkpPy5WYWxpZER1cmluZztcbiAgICAgIHNob3VsZC5leGlzdChleHBpcmF0aW9uKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm1pbkVwb2NoPy5Tb21lID8/IGV4cGlyYXRpb24ubWluRXBvY2gpLnNob3VsZC5lcXVhbCg1MDApO1xuICAgICAgTnVtYmVyKGV4cGlyYXRpb24ubWF4RXBvY2g/LlNvbWUgPz8gZXhwaXJhdGlvbi5tYXhFcG9jaCkuc2hvdWxkLmVxdWFsKDUwMSk7XG4gICAgICBleHBpcmF0aW9uLmNoYWluLnNob3VsZC5lcXVhbChHRU5FU0lTX0NIQUlOX0lEKTtcbiAgICAgIE51bWJlcihleHBpcmF0aW9uLm5vbmNlKS5zaG91bGQuZXF1YWwoMHhkZWFkYmVlZik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCYWxhbmNlV2l0aGRyYXdhbCBCQ1MgZW5jb2RpbmcgKEZ1bmRzV2l0aGRyYXdhbCBmb3JtYXQpJywgKCkgPT4ge1xuICAgIGNvbnN0IEFNT1VOVCA9ICcxMDAwMDAwMDAnOyAvLyAwLjEgU1VJIGluIE1JU1RcbiAgICBjb25zdCBzcG9uc29yZWRHYXNEYXRhID0ge1xuICAgICAgLi4udGVzdERhdGEuZ2FzRGF0YSxcbiAgICAgIG93bmVyOiB0ZXN0RGF0YS5mZWVQYXllci5hZGRyZXNzLFxuICAgIH07XG5cbiAgICBhc3luYyBmdW5jdGlvbiBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCkge1xuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKTtcbiAgICAgIHR4QnVpbGRlci50eXBlKFN1aVRyYW5zYWN0aW9uVHlwZS5UcmFuc2Zlcik7XG4gICAgICB0eEJ1aWxkZXIuc2VuZGVyKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kKFt7IGFkZHJlc3M6IHRlc3REYXRhLnJlY2lwaWVudHNbMF0uYWRkcmVzcywgYW1vdW50OiBBTU9VTlQgfV0pO1xuICAgICAgdHhCdWlsZGVyLmdhc0RhdGEoc3BvbnNvcmVkR2FzRGF0YSk7XG4gICAgICB0eEJ1aWxkZXIuZnVuZHNJbkFkZHJlc3NCYWxhbmNlKEFNT1VOVCk7XG4gICAgICByZXR1cm4gdHhCdWlsZGVyLmJ1aWxkKCk7XG4gICAgfVxuXG4gICAgaXQoJ3Nob3VsZCBlbmNvZGUgQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQgd2l0aCBGdW5kc1dpdGhkcmF3YWwgc3RydWN0dXJlIChyZXNlcnZhdGlvbi90eXBlQXJnL3dpdGhkcmF3RnJvbSknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBpbnB1dHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHMgYXMgYW55W107XG5cbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCwgJ0JhbGFuY2VXaXRoZHJhd2FsIGlucHV0IG11c3QgYmUgcHJlc2VudCcpO1xuXG4gICAgICBjb25zdCBidyA9IGJ3SW5wdXQuQmFsYW5jZVdpdGhkcmF3YWwgPz8gYndJbnB1dC52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWw7XG5cbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbiwgJ3Jlc2VydmF0aW9uIGZpZWxkIG11c3QgZXhpc3QnKTtcbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQsICdyZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQgbXVzdCBleGlzdCcpO1xuICAgICAgYncucmVzZXJ2YXRpb24uTWF4QW1vdW50VTY0LnRvU3RyaW5nKCkuc2hvdWxkLmVxdWFsKEFNT1VOVCk7XG5cbiAgICAgIHNob3VsZC5leGlzdChidy50eXBlQXJnLCAndHlwZUFyZyBmaWVsZCBtdXN0IGV4aXN0Jyk7XG4gICAgICBzaG91bGQuZXhpc3QoYncudHlwZUFyZy5CYWxhbmNlLCAndHlwZUFyZy5CYWxhbmNlIG11c3QgZXhpc3QnKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LndpdGhkcmF3RnJvbSwgJ3dpdGhkcmF3RnJvbSBmaWVsZCBtdXN0IGV4aXN0Jyk7XG4gICAgICBzaG91bGQuZXhpc3QoXG4gICAgICAgIGJ3LndpdGhkcmF3RnJvbS5TZW5kZXIgIT09IHVuZGVmaW5lZCB8fCBidy53aXRoZHJhd0Zyb20uU3BvbnNvciAhPT0gdW5kZWZpbmVkLFxuICAgICAgICAnd2l0aGRyYXdGcm9tIG11c3QgYmUgU2VuZGVyIG9yIFNwb25zb3InXG4gICAgICApO1xuXG4gICAgICAvLyBPbGQgZm9ybWF0IGZpZWxkcyBtdXN0IE5PVCBleGlzdCBkaXJlY3RseSBvbiBid1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChidy5hbW91bnQsICdvbGQgXCJhbW91bnRcIiBmaWVsZCBtdXN0IG5vdCBleGlzdCBvbiBCYWxhbmNlV2l0aGRyYXdhbCcpO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChidy50eXBlXywgJ29sZCBcInR5cGVfXCIgZmllbGQgbXVzdCBub3QgZXhpc3Qgb24gQmFsYW5jZVdpdGhkcmF3YWwnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBCQ1MgYnl0ZXMgdGhhdCBkZWNvZGUgYmFjayB0byBGdW5kc1dpdGhkcmF3YWwgd2l0aCBjb3JyZWN0IGFtb3VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4ID0gYXdhaXQgYnVpbGRTcG9uc29yZWRUeFdpdGhBZGRyZXNzQmFsYW5jZSgpO1xuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSBTdWlUcmFuc2FjdGlvbi5kZXNlcmlhbGl6ZVN1aVRyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICAgIGNvbnN0IGlucHV0cyA9IGRlc2VyaWFsaXplZC50eC5pbnB1dHMgYXMgYW55W107XG5cbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCwgJ0JhbGFuY2VXaXRoZHJhd2FsIG11c3QgYmUgcHJlc2VudCBpbiBkZXNlcmlhbGl6ZWQgaW5wdXRzJyk7XG5cbiAgICAgIGNvbnN0IGJ3ID0gYndJbnB1dC5CYWxhbmNlV2l0aGRyYXdhbCA/PyBid0lucHV0LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbDtcblxuICAgICAgLy8gRnVuZHNXaXRoZHJhd2FsIHN0cnVjdHVyZSAobm90IG9sZCB7YW1vdW50LCB0eXBlX30pXG4gICAgICBzaG91bGQuZXhpc3QoYncucmVzZXJ2YXRpb24sICdyZXNlcnZhdGlvbiBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcbiAgICAgIHNob3VsZC5leGlzdChidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQsICdNYXhBbW91bnRVNjQgbXVzdCBzdXJ2aXZlIEJDUyByb3VuZC10cmlwJyk7XG4gICAgICBidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQU1PVU5UKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnR5cGVBcmcsICd0eXBlQXJnIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGJ3LnR5cGVBcmcuQmFsYW5jZSwgJ3R5cGVBcmcuQmFsYW5jZSBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcblxuICAgICAgc2hvdWxkLmV4aXN0KGJ3LndpdGhkcmF3RnJvbSwgJ3dpdGhkcmF3RnJvbSBtdXN0IHN1cnZpdmUgQkNTIHJvdW5kLXRyaXAnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2VyaWFsaXplIHRvSnNvbigpIHdpdGhvdXQgYSBCaWdJbnQgcmVwbGFjZXIgKG5vIFR5cGVFcnJvciknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIHNob3VsZC5kb2VzTm90VGhyb3coXG4gICAgICAgICgpID0+IEpTT04uc3RyaW5naWZ5KHR4LnRvSnNvbigpKSxcbiAgICAgICAgJ0pTT04uc3RyaW5naWZ5KHR4LnRvSnNvbigpKSBtdXN0IG5vdCB0aHJvdyDigJQgQmFsYW5jZVdpdGhkcmF3YWwgYW1vdW50IG11c3Qgbm90IGJlIHN0b3JlZCBhcyBCaWdJbnQnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBmdW5kc0luQWRkcmVzc0JhbGFuY2UgYW1vdW50IHRocm91Z2ggZnVsbCByb3VuZC10cmlwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSBhd2FpdCBidWlsZFNwb25zb3JlZFR4V2l0aEFkZHJlc3NCYWxhbmNlKCk7XG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuXG4gICAgICByZWJ1aWx0VHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zaG91bGQuZXF1YWwocmF3VHgpO1xuXG4gICAgICBjb25zdCBzdWlUeCA9IHJlYnVpbHRUeCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQuZXhpc3QoYndJbnB1dCk7XG4gICAgICBjb25zdCBidyA9IGJ3SW5wdXQuQmFsYW5jZVdpdGhkcmF3YWwgPz8gYndJbnB1dC52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWw7XG4gICAgICBidy5yZXNlcnZhdGlvbi5NYXhBbW91bnRVNjQudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoQU1PVU5UKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZW5jb2RlIGdhcy1mcm9tLWFkZHJlc3MtYmFsYW5jZSAoc2VsZi1wYXksIGVtcHR5IHBheW1lbnQpIHdpdGggbm8gRnVuZHNXaXRoZHJhd2FsIGlucHV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gV2hlbiBnYXNEYXRhLnBheW1lbnQ9W10gYW5kIHNlbmRlcj09PWdhc0RhdGEub3duZXIsIHRoZSBTdWkgcnVudGltZSBhdXRvbWF0aWNhbGx5XG4gICAgICAvLyB1c2VzIGFkZHJlc3MgYmFsYW5jZSB0byBmdW5kIGJvdGggZ2FzIGFuZCB0aGUgdHJhbnNmZXIgdmlhIEdhc0NvaW4uXG4gICAgICAvLyBObyBCYWxhbmNlV2l0aGRyYXdhbCBDYWxsQXJnIGlzIG5lZWRlZCDigJQgdGhlIHJ1bnRpbWUgaGFuZGxlcyBpdCBpbXBsaWNpdGx5LlxuICAgICAgY29uc3Qgc2VsZlBheU5vUGF5bWVudCA9IHsgLi4udGVzdERhdGEuZ2FzRGF0YVdpdGhvdXRHYXNQYXltZW50LCBwYXltZW50OiBbXSB9O1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoU3VpVHJhbnNhY3Rpb25UeXBlLlRyYW5zZmVyKTtcbiAgICAgIHR4QnVpbGRlci5zZW5kZXIodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgdHhCdWlsZGVyLnNlbmQoW3sgYWRkcmVzczogdGVzdERhdGEucmVjaXBpZW50c1swXS5hZGRyZXNzLCBhbW91bnQ6IEFNT1VOVCB9XSk7XG4gICAgICB0eEJ1aWxkZXIuZ2FzRGF0YShzZWxmUGF5Tm9QYXltZW50KTtcbiAgICAgIHR4QnVpbGRlci5mdW5kc0luQWRkcmVzc0JhbGFuY2UoQU1PVU5UKTtcblxuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHNob3VsZC5lcXVhbCh0eC50eXBlLCBUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG5cbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG5cbiAgICAgIC8vIEdhcyBvd25lciBtdXN0IGVxdWFsIHNlbmRlciAoc2VsZi1wYXkpXG4gICAgICBzdWlUeC5zdWlUcmFuc2FjdGlvbi5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICAvLyBQYXltZW50IG11c3QgYmUgZW1wdHkg4oCUIGdhcyBmdW5kZWQgZnJvbSBhZGRyZXNzIGJhbGFuY2UgYnkgdGhlIHJ1bnRpbWVcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBObyBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCDigJQgcnVudGltZSBoYW5kbGVzIGFkZHJlc3MgYmFsYW5jZSBhdXRvbWF0aWNhbGx5XG4gICAgICBjb25zdCBpbnB1dHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC5pbnB1dHMgYXMgYW55W107XG4gICAgICBjb25zdCBid0lucHV0ID0gaW5wdXRzLmZpbmQoXG4gICAgICAgIChpbnApID0+IGlucD8uQmFsYW5jZVdpdGhkcmF3YWwgIT09IHVuZGVmaW5lZCB8fCBpbnA/LnZhbHVlPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkXG4gICAgICApO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChid0lucHV0LCAnc2VsZi1wYXkgbXVzdCBOT1QgaGF2ZSBhIEJhbGFuY2VXaXRoZHJhd2FsIGlucHV0IOKAlCBydW50aW1lIGhhbmRsZXMgaXQnKTtcblxuICAgICAgLy8gRmlyc3QgY29tbWFuZCBtdXN0IGJlIFNwbGl0Q29pbnMoR2FzQ29pbikg4oCUIG5vIHJlZGVlbV9mdW5kcyBuZWVkZWRcbiAgICAgIGNvbnN0IGNvbW1hbmRzID0gc3VpVHguc3VpVHJhbnNhY3Rpb24udHgudHJhbnNhY3Rpb25zIGFzIGFueVtdO1xuICAgICAgY29tbWFuZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ1NwbGl0Q29pbnMnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZWQgPSBTdWlUcmFuc2FjdGlvbi5kZXNlcmlhbGl6ZVN1aVRyYW5zYWN0aW9uKHJhd1R4KTtcbiAgICAgIGRlc2VyaWFsaXplZC5zZW5kZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIGRlc2VyaWFsaXplZC5nYXNEYXRhLm93bmVyLnNob3VsZC5lcXVhbCh0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICBkZXNlcmlhbGl6ZWQuZ2FzRGF0YS5wYXltZW50Lmxlbmd0aC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgIC8vIE5vIEZ1bmRzV2l0aGRyYXdhbCBpbiBkZWNvZGVkIGlucHV0cyDigJQgb25seSBQdXJlIGFyZ3NcbiAgICAgIGNvbnN0IGRlY29kZWRJbnB1dHMgPSBkZXNlcmlhbGl6ZWQudHguaW5wdXRzIGFzIGFueVtdO1xuICAgICAgZGVjb2RlZElucHV0c1xuICAgICAgICAuZXZlcnkoKGlucDogYW55KSA9PiBpbnA/LkJhbGFuY2VXaXRoZHJhd2FsID09PSB1bmRlZmluZWQgJiYgaW5wPy52YWx1ZT8uQmFsYW5jZVdpdGhkcmF3YWwgPT09IHVuZGVmaW5lZClcbiAgICAgICAgLnNob3VsZC5iZS50cnVlKCdkZWNvZGVkIGlucHV0cyBtdXN0IGNvbnRhaW4gbm8gRnVuZHNXaXRoZHJhd2FsIGZvciBzZWxmLXBheSBwYXRoJyk7XG5cbiAgICAgIGNvbnN0IHJlYnVpbGRlciA9IGZhY3RvcnkuZnJvbShyYXdUeCk7XG4gICAgICByZWJ1aWxkZXIuYWRkU2lnbmF0dXJlKHsgcHViOiB0ZXN0RGF0YS5zZW5kZXIucHVibGljS2V5IH0sIEJ1ZmZlci5mcm9tKHRlc3REYXRhLnNlbmRlci5zaWduYXR1cmVIZXgpKTtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHJlYnVpbGRlci5idWlsZCgpO1xuICAgICAgcmVidWlsdFR4LnRvQnJvYWRjYXN0Rm9ybWF0KCkuc2hvdWxkLmVxdWFsKHJhd1R4KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZW5jb2RlIGdhcy1mcm9tLWFkZHJlc3MtYmFsYW5jZSB3aXRoIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gKHNlbGYtcGF5LCBlbXB0eSBwYXltZW50KScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFdoZW4gZ2FzRGF0YS5wYXltZW50PVtdIHRoZSBTdWkgbm9kZSByZXF1aXJlcyBhIFZhbGlkRHVyaW5nIGV4cGlyYXRpb24gdG8gcHJldmVudFxuICAgICAgLy8gcmVwbGF5IGF0dGFja3MuIEdhcyBhbmQgdHJhbnNmZXIgYXJlIGJvdGggZnVuZGVkIGZyb20gYWRkcmVzcyBiYWxhbmNlIHZpYSBHYXNDb2luLlxuICAgICAgY29uc3QgR0VORVNJU19DSEFJTl9JRCA9ICdHQUZwQ0NjUkN4VGRGZlVFTWJRYmtMQmFaeTJSTmlHQWZ2RkJoTU5wcTJrVCc7XG4gICAgICBjb25zdCBzZWxmUGF5Tm9QYXltZW50ID0geyAuLi50ZXN0RGF0YS5nYXNEYXRhV2l0aG91dEdhc1BheW1lbnQsIHBheW1lbnQ6IFtdIH07XG5cbiAgICAgIGNvbnN0IHR4QnVpbGRlciA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCk7XG4gICAgICB0eEJ1aWxkZXIudHlwZShTdWlUcmFuc2FjdGlvblR5cGUuVHJhbnNmZXIpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcih0ZXN0RGF0YS5zZW5kZXIuYWRkcmVzcyk7XG4gICAgICB0eEJ1aWxkZXIuc2VuZChbeyBhZGRyZXNzOiB0ZXN0RGF0YS5yZWNpcGllbnRzWzBdLmFkZHJlc3MsIGFtb3VudDogQU1PVU5UIH1dKTtcbiAgICAgIHR4QnVpbGRlci5nYXNEYXRhKHNlbGZQYXlOb1BheW1lbnQpO1xuICAgICAgdHhCdWlsZGVyLmZ1bmRzSW5BZGRyZXNzQmFsYW5jZShBTU9VTlQpO1xuICAgICAgdHhCdWlsZGVyLmV4cGlyYXRpb24oe1xuICAgICAgICBWYWxpZER1cmluZzoge1xuICAgICAgICAgIG1pbkVwb2NoOiB7IFNvbWU6IDUwMCB9LFxuICAgICAgICAgIG1heEVwb2NoOiB7IFNvbWU6IDUwMSB9LFxuICAgICAgICAgIG1pblRpbWVzdGFtcDogeyBOb25lOiBudWxsIH0sXG4gICAgICAgICAgbWF4VGltZXN0YW1wOiB7IE5vbmU6IG51bGwgfSxcbiAgICAgICAgICBjaGFpbjogR0VORVNJU19DSEFJTl9JRCxcbiAgICAgICAgICBub25jZTogMHhkZWFkYmVlZixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHR4LnR5cGUsIFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcblxuICAgICAgY29uc3Qgc3VpVHggPSB0eCBhcyBTdWlUcmFuc2FjdGlvbjxUcmFuc2ZlclByb2dyYW1tYWJsZVRyYW5zYWN0aW9uPjtcblxuICAgICAgLy8gU2VsZi1wYXk6IG93bmVyID09PSBzZW5kZXIsIHBheW1lbnQgZW1wdHlcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEub3duZXIuc2hvdWxkLmVxdWFsKHRlc3REYXRhLnNlbmRlci5hZGRyZXNzKTtcbiAgICAgIHN1aVR4LnN1aVRyYW5zYWN0aW9uLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAvLyBObyBCYWxhbmNlV2l0aGRyYXdhbCBpbnB1dCDigJQgcnVudGltZSBoYW5kbGVzIEdhc0NvaW4gZnJvbSBhZGRyZXNzIGJhbGFuY2VcbiAgICAgIGNvbnN0IGlucHV0cyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGNvbnN0IGJ3SW5wdXQgPSBpbnB1dHMuZmluZChcbiAgICAgICAgKGlucCkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCAhPT0gdW5kZWZpbmVkIHx8IGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsICE9PSB1bmRlZmluZWRcbiAgICAgICk7XG4gICAgICBzaG91bGQubm90LmV4aXN0KGJ3SW5wdXQsICdzZWxmLXBheSBtdXN0IE5PVCBoYXZlIGEgQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQnKTtcblxuICAgICAgLy8gRmlyc3QgY29tbWFuZDogU3BsaXRDb2lucyhHYXNDb2luKSDigJQgbm8gcmVkZWVtX2Z1bmRzIGZvciBzZWxmLXBheVxuICAgICAgY29uc3QgY29tbWFuZHMgPSBzdWlUeC5zdWlUcmFuc2FjdGlvbi50eC50cmFuc2FjdGlvbnMgYXMgYW55W107XG4gICAgICBjb21tYW5kc1swXS5raW5kLnNob3VsZC5lcXVhbCgnU3BsaXRDb2lucycpO1xuXG4gICAgICBjb25zdCByYXdUeCA9IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBzaG91bGQuZXF1YWwodXRpbHMuaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1R4KSwgdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZCA9IFN1aVRyYW5zYWN0aW9uLmRlc2VyaWFsaXplU3VpVHJhbnNhY3Rpb24ocmF3VHgpO1xuICAgICAgZGVzZXJpYWxpemVkLnNlbmRlci5zaG91bGQuZXF1YWwodGVzdERhdGEuc2VuZGVyLmFkZHJlc3MpO1xuICAgICAgZGVzZXJpYWxpemVkLmdhc0RhdGEucGF5bWVudC5sZW5ndGguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICBjb25zdCBleHBpcmF0aW9uID0gKGRlc2VyaWFsaXplZC5leHBpcmF0aW9uIGFzIGFueSk/LlZhbGlkRHVyaW5nO1xuICAgICAgc2hvdWxkLmV4aXN0KGV4cGlyYXRpb24sICdWYWxpZER1cmluZyBleHBpcmF0aW9uIG11c3Qgc3Vydml2ZSBCQ1Mgcm91bmQtdHJpcCcpO1xuICAgICAgTnVtYmVyKGV4cGlyYXRpb24ubWluRXBvY2g/LlNvbWUgPz8gZXhwaXJhdGlvbi5taW5FcG9jaCkuc2hvdWxkLmVxdWFsKDUwMCk7XG4gICAgICBOdW1iZXIoZXhwaXJhdGlvbi5tYXhFcG9jaD8uU29tZSA/PyBleHBpcmF0aW9uLm1heEVwb2NoKS5zaG91bGQuZXF1YWwoNTAxKTtcbiAgICAgIGV4cGlyYXRpb24uY2hhaW4uc2hvdWxkLmVxdWFsKEdFTkVTSVNfQ0hBSU5fSUQpO1xuICAgICAgTnVtYmVyKGV4cGlyYXRpb24ubm9uY2UpLnNob3VsZC5lcXVhbCgweGRlYWRiZWVmKTtcblxuICAgICAgLy8gSW5wdXRzIG11c3QgY29udGFpbiBubyBGdW5kc1dpdGhkcmF3YWwg4oCUIG9ubHkgUHVyZSBhcmdzXG4gICAgICBjb25zdCBkZWNvZGVkSW5wdXRzID0gZGVzZXJpYWxpemVkLnR4LmlucHV0cyBhcyBhbnlbXTtcbiAgICAgIGRlY29kZWRJbnB1dHNcbiAgICAgICAgLmV2ZXJ5KChpbnA6IGFueSkgPT4gaW5wPy5CYWxhbmNlV2l0aGRyYXdhbCA9PT0gdW5kZWZpbmVkICYmIGlucD8udmFsdWU/LkJhbGFuY2VXaXRoZHJhd2FsID09PSB1bmRlZmluZWQpXG4gICAgICAgIC5zaG91bGQuYmUudHJ1ZSgnZGVjb2RlZCBpbnB1dHMgbXVzdCBjb250YWluIG5vIEZ1bmRzV2l0aGRyYXdhbCBmb3Igc2VsZi1wYXkgcGF0aCcpO1xuXG4gICAgICBjb25zdCByZWJ1aWxkZXIgPSBmYWN0b3J5LmZyb20ocmF3VHgpO1xuICAgICAgcmVidWlsZGVyLmFkZFNpZ25hdHVyZSh7IHB1YjogdGVzdERhdGEuc2VuZGVyLnB1YmxpY0tleSB9LCBCdWZmZXIuZnJvbSh0ZXN0RGF0YS5zZW5kZXIuc2lnbmF0dXJlSGV4KSk7XG4gICAgICBjb25zdCByZWJ1aWx0VHggPSBhd2FpdCByZWJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIHJlYnVpbHRUeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnNob3VsZC5lcXVhbChyYXdUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGFuZCBjb3JyZWN0bHkgZGVjb2RlIGEgTW92ZUNhbGwgdG8gMHgyOjpjb2luOjpyZWRlZW1fZnVuZHMgd2l0aCBCYWxhbmNlV2l0aGRyYXdhbCBhcmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eCA9IGF3YWl0IGJ1aWxkU3BvbnNvcmVkVHhXaXRoQWRkcmVzc0JhbGFuY2UoKTtcbiAgICAgIGNvbnN0IHN1aVR4ID0gdHggYXMgU3VpVHJhbnNhY3Rpb248VHJhbnNmZXJQcm9ncmFtbWFibGVUcmFuc2FjdGlvbj47XG4gICAgICBjb25zdCBjb21tYW5kcyA9IHN1aVR4LnN1aVRyYW5zYWN0aW9uLnR4LnRyYW5zYWN0aW9ucyBhcyBhbnlbXTtcblxuICAgICAgY29tbWFuZHNbMF0ua2luZC5zaG91bGQuZXF1YWwoJ01vdmVDYWxsJyk7XG4gICAgICBjb21tYW5kc1swXS50YXJnZXQuc2hvdWxkLmVxdWFsKCcweDI6OmNvaW46OnJlZGVlbV9mdW5kcycpO1xuICAgICAgY29tbWFuZHNbMF0udHlwZUFyZ3VtZW50c1swXS5zaG91bGQuZXF1YWwoJzB4Mjo6c3VpOjpTVUknKTtcblxuICAgICAgLy8gVGhlIGFyZ3VtZW50IHRvIHJlZGVlbV9mdW5kcyBtdXN0IHJlZmVyZW5jZSB0aGUgQmFsYW5jZVdpdGhkcmF3YWwgaW5wdXQgKGluZGV4IDApXG4gICAgICBjb25zdCBhcmcgPSBjb21tYW5kc1swXS5hcmd1bWVudHNbMF07XG4gICAgICBhcmcua2luZC5zaG91bGQuZXF1YWwoJ0lucHV0Jyk7XG4gICAgICBhcmcuaW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgICAgYXJnLnR5cGUuc2hvdWxkLmVxdWFsKCdvYmplY3QnKTtcblxuICAgICAgY29uc3QgcmF3VHggPSB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgc2hvdWxkLmVxdWFsKHV0aWxzLmlzVmFsaWRSYXdUcmFuc2FjdGlvbihyYXdUeCksIHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19