@bitgo-beta/sdk-coin-tempo 1.0.1-beta.31 → 1.0.1-beta.310
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.
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/lib/constants.d.ts +21 -1
- package/dist/src/lib/constants.d.ts.map +1 -1
- package/dist/src/lib/constants.js +25 -5
- package/dist/src/lib/index.d.ts +4 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +5 -1
- package/dist/src/lib/keyPair.d.ts +5 -25
- package/dist/src/lib/keyPair.d.ts.map +1 -1
- package/dist/src/lib/keyPair.js +9 -97
- package/dist/src/lib/tip20Abi.d.ts +98 -0
- package/dist/src/lib/tip20Abi.d.ts.map +1 -0
- package/dist/src/lib/tip20Abi.js +62 -0
- package/dist/src/lib/transaction.d.ts +144 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +216 -0
- package/dist/src/lib/transactionBuilder.d.ts +139 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +408 -0
- package/dist/src/lib/types.d.ts +27 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/dist/src/lib/types.js +3 -0
- package/dist/src/lib/utils.d.ts +70 -7
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +148 -16
- package/dist/src/register.d.ts.map +1 -1
- package/dist/src/register.js +5 -1
- package/dist/src/tempo.d.ts +95 -41
- package/dist/src/tempo.d.ts.map +1 -1
- package/dist/src/tempo.js +447 -76
- package/dist/src/tip20Token.d.ts +83 -0
- package/dist/src/tip20Token.d.ts.map +1 -0
- package/dist/src/tip20Token.js +202 -0
- package/dist/test/integration/tip20.d.ts +7 -0
- package/dist/test/integration/tip20.d.ts.map +1 -0
- package/dist/test/integration/tip20.js +178 -0
- package/dist/test/resources/tempo.d.ts +61 -0
- package/dist/test/resources/tempo.d.ts.map +1 -0
- package/dist/test/resources/tempo.js +79 -0
- package/dist/test/unit/index.js +172 -3
- package/dist/test/unit/tempo.d.ts +2 -0
- package/dist/test/unit/tempo.d.ts.map +1 -0
- package/dist/test/unit/tempo.js +207 -0
- package/dist/test/unit/transactionBuilder.d.ts +2 -0
- package/dist/test/unit/transactionBuilder.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder.js +858 -0
- package/dist/test/unit/utils.js +6 -5
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -7
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const assert_1 = __importDefault(require("assert"));
|
|
7
|
+
const mocha_1 = require("mocha");
|
|
8
|
+
const ethers_1 = require("ethers");
|
|
9
|
+
const transactionBuilder_1 = require("../../src/lib/transactionBuilder");
|
|
10
|
+
const transaction_1 = require("../../src/lib/transaction");
|
|
11
|
+
const utils_1 = require("../../src/lib/utils");
|
|
12
|
+
const constants_1 = require("../../src/lib/constants");
|
|
13
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
14
|
+
const ttempo_1 = require("../../src/ttempo");
|
|
15
|
+
const sdk_api_1 = require("@bitgo-beta/sdk-api");
|
|
16
|
+
const sdk_test_1 = require("@bitgo-beta/sdk-test");
|
|
17
|
+
const tempo_1 = require("../resources/tempo");
|
|
18
|
+
const mockCoinConfig = statics_1.coins.get('ttempo');
|
|
19
|
+
(0, mocha_1.describe)('TIP-20 Utilities', () => {
|
|
20
|
+
(0, mocha_1.describe)('amountToTip20Units', () => {
|
|
21
|
+
(0, mocha_1.it)('should convert decimal amount to 6-decimal units', () => {
|
|
22
|
+
assert_1.default.strictEqual((0, utils_1.amountToTip20Units)('1.5'), 1500000n);
|
|
23
|
+
assert_1.default.strictEqual((0, utils_1.amountToTip20Units)('100'), 100000000n);
|
|
24
|
+
assert_1.default.strictEqual((0, utils_1.amountToTip20Units)('0.000001'), 1n);
|
|
25
|
+
});
|
|
26
|
+
(0, mocha_1.it)('should throw error for invalid amount', () => {
|
|
27
|
+
assert_1.default.throws(() => (0, utils_1.amountToTip20Units)('invalid'), /Invalid amount format/);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
(0, mocha_1.describe)('tip20UnitsToAmount', () => {
|
|
31
|
+
(0, mocha_1.it)('should convert 6-decimal units to human-readable amount', () => {
|
|
32
|
+
assert_1.default.strictEqual((0, utils_1.tip20UnitsToAmount)(1500000n), '1.5');
|
|
33
|
+
assert_1.default.strictEqual((0, utils_1.tip20UnitsToAmount)(100000000n), '100.0');
|
|
34
|
+
assert_1.default.strictEqual((0, utils_1.tip20UnitsToAmount)(1n), '0.000001');
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
(0, mocha_1.describe)('stringToBytes32', () => {
|
|
38
|
+
(0, mocha_1.it)('should convert string to bytes32', () => {
|
|
39
|
+
const result = (0, utils_1.stringToBytes32)('12345');
|
|
40
|
+
assert_1.default.strictEqual(result.length, 66);
|
|
41
|
+
assert_1.default.ok(result.startsWith('0x'));
|
|
42
|
+
});
|
|
43
|
+
(0, mocha_1.it)('should throw error for string longer than 32 bytes', () => {
|
|
44
|
+
assert_1.default.throws(() => (0, utils_1.stringToBytes32)('a'.repeat(33)), /Memo too long/);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
(0, mocha_1.describe)('encodeTip20TransferWithMemo', () => {
|
|
48
|
+
(0, mocha_1.it)('should encode transferWithMemo call', () => {
|
|
49
|
+
const to = ethers_1.ethers.utils.getAddress('0x742d35cc6634c0532925a3b844bc9e7595f0beb1');
|
|
50
|
+
const encoded = (0, utils_1.encodeTip20TransferWithMemo)(to, 1500000n, '12345');
|
|
51
|
+
assert_1.default.ok(encoded.startsWith('0x'));
|
|
52
|
+
assert_1.default.ok(encoded.length > 10);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
(0, mocha_1.describe)('isValidTip20Amount', () => {
|
|
56
|
+
(0, mocha_1.it)('should validate amounts correctly', () => {
|
|
57
|
+
assert_1.default.strictEqual((0, utils_1.isValidTip20Amount)('1.5'), true);
|
|
58
|
+
assert_1.default.strictEqual((0, utils_1.isValidTip20Amount)('invalid'), false);
|
|
59
|
+
assert_1.default.strictEqual((0, utils_1.isValidTip20Amount)('-5'), false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
(0, mocha_1.describe)('TIP-20 Transaction Builder', () => {
|
|
64
|
+
const mockToken = ethers_1.ethers.utils.getAddress('0x1234567890123456789012345678901234567890');
|
|
65
|
+
const mockRecipient = ethers_1.ethers.utils.getAddress('0x742d35cc6634c0532925a3b844bc9e7595f0beb1');
|
|
66
|
+
const mockFeeToken = ethers_1.ethers.utils.getAddress('0xabcdefabcdefabcdefabcdefabcdefabcdefabcd');
|
|
67
|
+
(0, mocha_1.describe)('addOperation', () => {
|
|
68
|
+
(0, mocha_1.it)('should add operation with and without memo', () => {
|
|
69
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
70
|
+
builder.addOperation({ token: mockToken, to: mockRecipient, amount: '100' });
|
|
71
|
+
builder.addOperation({ token: mockToken, to: mockRecipient, amount: '50', memo: '1' });
|
|
72
|
+
const operations = builder.getOperations();
|
|
73
|
+
assert_1.default.strictEqual(operations.length, 2);
|
|
74
|
+
assert_1.default.strictEqual(operations[0].memo, undefined);
|
|
75
|
+
assert_1.default.strictEqual(operations[1].memo, '1');
|
|
76
|
+
});
|
|
77
|
+
(0, mocha_1.it)('should throw error for invalid addresses', () => {
|
|
78
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
79
|
+
assert_1.default.throws(() => builder.addOperation({ token: '0xinvalid', to: mockRecipient, amount: '100' }), /Invalid token address/);
|
|
80
|
+
assert_1.default.throws(() => builder.addOperation({ token: mockToken, to: '0xinvalid', amount: '100' }), /Invalid recipient address/);
|
|
81
|
+
});
|
|
82
|
+
(0, mocha_1.it)('should throw error for invalid amount', () => {
|
|
83
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
84
|
+
assert_1.default.throws(() => builder.addOperation({ token: mockToken, to: mockRecipient, amount: 'invalid-amount' }), /Invalid amount/);
|
|
85
|
+
});
|
|
86
|
+
(0, mocha_1.it)('should throw error for invalid (non-numeric) memo', () => {
|
|
87
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
88
|
+
assert_1.default.throws(() => builder.addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: 'INV-001' }), /Invalid memo/);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
(0, mocha_1.describe)('feeToken', () => {
|
|
92
|
+
(0, mocha_1.it)('should set and get fee token', () => {
|
|
93
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
94
|
+
builder.feeToken(mockFeeToken);
|
|
95
|
+
assert_1.default.strictEqual(builder.getFeeToken(), mockFeeToken);
|
|
96
|
+
});
|
|
97
|
+
(0, mocha_1.it)('should throw error for invalid fee token address', () => {
|
|
98
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
99
|
+
assert_1.default.throws(() => builder.feeToken('invalid-address'), /Invalid fee token address/);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
(0, mocha_1.describe)('Transaction parameters', () => {
|
|
103
|
+
(0, mocha_1.it)('should set nonce, gas, maxFeePerGas, and maxPriorityFeePerGas', () => {
|
|
104
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
105
|
+
builder.nonce(42).gas(500000n).maxFeePerGas(1000000000n).maxPriorityFeePerGas(500000000n);
|
|
106
|
+
assert_1.default.strictEqual(builder._nonce, 42);
|
|
107
|
+
assert_1.default.strictEqual(builder._gas, 500000n);
|
|
108
|
+
assert_1.default.strictEqual(builder._maxFeePerGas, 1000000000n);
|
|
109
|
+
assert_1.default.strictEqual(builder._maxPriorityFeePerGas, 500000000n);
|
|
110
|
+
});
|
|
111
|
+
(0, mocha_1.it)('should throw error for invalid nonce and gas', () => {
|
|
112
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
113
|
+
assert_1.default.throws(() => builder.nonce(-1), /Invalid nonce/);
|
|
114
|
+
assert_1.default.throws(() => builder.gas(0n), /Invalid gas limit/);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
(0, mocha_1.describe)('Method chaining', () => {
|
|
118
|
+
(0, mocha_1.it)('should support fluent interface', () => {
|
|
119
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
120
|
+
const result = builder
|
|
121
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: '5' })
|
|
122
|
+
.feeToken(mockFeeToken)
|
|
123
|
+
.nonce(10)
|
|
124
|
+
.gas(400000n)
|
|
125
|
+
.maxFeePerGas(2000000000n)
|
|
126
|
+
.maxPriorityFeePerGas(1000000000n);
|
|
127
|
+
assert_1.default.strictEqual(result, builder);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
(0, mocha_1.describe)('TIP-20 Constants', () => {
|
|
132
|
+
(0, mocha_1.it)('should have correct decimal places', () => {
|
|
133
|
+
assert_1.default.strictEqual(constants_1.TIP20_DECIMALS, 6);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
(0, mocha_1.describe)('TIP-20 Transaction Build', () => {
|
|
137
|
+
const mockToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.alphaUSD.address);
|
|
138
|
+
const mockRecipient = ethers_1.ethers.utils.getAddress(tempo_1.TEST_RECIPIENT_ADDRESS);
|
|
139
|
+
const mockFeeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
|
|
140
|
+
(0, mocha_1.describe)('Build Transaction', () => {
|
|
141
|
+
(0, mocha_1.it)('should build single-operation transaction', async () => {
|
|
142
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
143
|
+
builder
|
|
144
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: '1' })
|
|
145
|
+
.feeToken(mockFeeToken)
|
|
146
|
+
.nonce(0)
|
|
147
|
+
.gas(100000n)
|
|
148
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
149
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
150
|
+
const tx = (await builder.build());
|
|
151
|
+
assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
|
|
152
|
+
assert_1.default.strictEqual(tx.getOperationCount(), 1);
|
|
153
|
+
assert_1.default.strictEqual(tx.getFeeToken(), mockFeeToken);
|
|
154
|
+
});
|
|
155
|
+
(0, mocha_1.it)('should build batch transaction with multiple operations', async () => {
|
|
156
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
157
|
+
builder
|
|
158
|
+
.addOperation({ token: tempo_1.TESTNET_TOKENS.alphaUSD.address, to: mockRecipient, amount: '10', memo: '1' })
|
|
159
|
+
.addOperation({ token: tempo_1.TESTNET_TOKENS.betaUSD.address, to: mockRecipient, amount: '20', memo: '2' })
|
|
160
|
+
.addOperation({ token: tempo_1.TESTNET_TOKENS.thetaUSD.address, to: mockRecipient, amount: '30', memo: '3' })
|
|
161
|
+
.feeToken(mockFeeToken)
|
|
162
|
+
.nonce(42)
|
|
163
|
+
.gas(300000n)
|
|
164
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
165
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
166
|
+
const tx = (await builder.build());
|
|
167
|
+
assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
|
|
168
|
+
assert_1.default.strictEqual(tx.getOperationCount(), 3);
|
|
169
|
+
assert_1.default.strictEqual(tx.isBatch(), true);
|
|
170
|
+
});
|
|
171
|
+
(0, mocha_1.it)('should build transaction without fee token', async () => {
|
|
172
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
173
|
+
builder
|
|
174
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '50' })
|
|
175
|
+
.nonce(1)
|
|
176
|
+
.gas(100000n)
|
|
177
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
178
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
179
|
+
const tx = (await builder.build());
|
|
180
|
+
assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
|
|
181
|
+
assert_1.default.strictEqual(tx.getFeeToken(), undefined);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
(0, mocha_1.describe)('Build Validation Errors', () => {
|
|
185
|
+
(0, mocha_1.it)('should throw error when no operations added', async () => {
|
|
186
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
187
|
+
builder.nonce(0).gas(100000n).maxFeePerGas(1000000000n).maxPriorityFeePerGas(500000000n);
|
|
188
|
+
await assert_1.default.rejects(async () => await builder.build(), /At least one operation or raw call is required/);
|
|
189
|
+
});
|
|
190
|
+
(0, mocha_1.it)('should throw error when nonce not set', async () => {
|
|
191
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
192
|
+
builder
|
|
193
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
194
|
+
.gas(100000n)
|
|
195
|
+
.maxFeePerGas(1000000000n)
|
|
196
|
+
.maxPriorityFeePerGas(500000000n);
|
|
197
|
+
await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingNonce);
|
|
198
|
+
});
|
|
199
|
+
(0, mocha_1.it)('should throw error when gas not set', async () => {
|
|
200
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
201
|
+
builder
|
|
202
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
203
|
+
.nonce(0)
|
|
204
|
+
.maxFeePerGas(1000000000n)
|
|
205
|
+
.maxPriorityFeePerGas(500000000n);
|
|
206
|
+
await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingGas);
|
|
207
|
+
});
|
|
208
|
+
(0, mocha_1.it)('should throw error when maxFeePerGas not set', async () => {
|
|
209
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
210
|
+
builder
|
|
211
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
212
|
+
.nonce(0)
|
|
213
|
+
.gas(100000n)
|
|
214
|
+
.maxPriorityFeePerGas(500000000n);
|
|
215
|
+
await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingMaxFeePerGas);
|
|
216
|
+
});
|
|
217
|
+
(0, mocha_1.it)('should throw error when maxPriorityFeePerGas not set', async () => {
|
|
218
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
219
|
+
builder
|
|
220
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
221
|
+
.nonce(0)
|
|
222
|
+
.gas(100000n)
|
|
223
|
+
.maxFeePerGas(1000000000n);
|
|
224
|
+
await assert_1.default.rejects(async () => await builder.build(), tempo_1.ERROR_MESSAGES.missingMaxPriorityFeePerGas);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
(0, mocha_1.describe)('Round-Trip: Build -> Serialize -> Operations Check', () => {
|
|
228
|
+
(0, mocha_1.it)('should preserve operation data through build', async () => {
|
|
229
|
+
const operations = [{ token: mockToken, to: mockRecipient, amount: '123', memo: '1' }];
|
|
230
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
231
|
+
builder
|
|
232
|
+
.addOperation(operations[0])
|
|
233
|
+
.feeToken(mockFeeToken)
|
|
234
|
+
.nonce(10)
|
|
235
|
+
.gas(150000n)
|
|
236
|
+
.maxFeePerGas(2000000000n)
|
|
237
|
+
.maxPriorityFeePerGas(1000000000n);
|
|
238
|
+
const tx = (await builder.build());
|
|
239
|
+
const txOps = tx.getOperations();
|
|
240
|
+
assert_1.default.strictEqual(txOps.length, 1);
|
|
241
|
+
assert_1.default.strictEqual(txOps[0].token, operations[0].token);
|
|
242
|
+
assert_1.default.strictEqual(txOps[0].to, operations[0].to);
|
|
243
|
+
assert_1.default.strictEqual(txOps[0].amount, operations[0].amount);
|
|
244
|
+
assert_1.default.strictEqual(txOps[0].memo, operations[0].memo);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
(0, mocha_1.describe)('Build -> Serialize -> Sign Flow', () => {
|
|
248
|
+
(0, mocha_1.it)('should produce serializable unsigned transaction', async () => {
|
|
249
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
250
|
+
builder
|
|
251
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '50', memo: '2' })
|
|
252
|
+
.feeToken(mockFeeToken)
|
|
253
|
+
.nonce(5)
|
|
254
|
+
.gas(100000n)
|
|
255
|
+
.maxFeePerGas(2000000000n)
|
|
256
|
+
.maxPriorityFeePerGas(1000000000n);
|
|
257
|
+
const tx = (await builder.build());
|
|
258
|
+
const unsignedHex = await tx.serialize();
|
|
259
|
+
assert_1.default.ok(unsignedHex.startsWith(constants_1.AA_TRANSACTION_TYPE));
|
|
260
|
+
assert_1.default.ok(/^0x[0-9a-f]+$/i.test(unsignedHex));
|
|
261
|
+
});
|
|
262
|
+
(0, mocha_1.it)('should support full sign and broadcast flow', async () => {
|
|
263
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
264
|
+
builder
|
|
265
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '75', memo: '3' })
|
|
266
|
+
.feeToken(mockFeeToken)
|
|
267
|
+
.nonce(123)
|
|
268
|
+
.gas(120000n)
|
|
269
|
+
.maxFeePerGas(2500000000n)
|
|
270
|
+
.maxPriorityFeePerGas(1200000000n);
|
|
271
|
+
const tx = (await builder.build());
|
|
272
|
+
const unsignedHex = await tx.serialize();
|
|
273
|
+
tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
|
|
274
|
+
const broadcastHex = await tx.toBroadcastFormat();
|
|
275
|
+
assert_1.default.ok(broadcastHex.startsWith(constants_1.AA_TRANSACTION_TYPE));
|
|
276
|
+
assert_1.default.ok(broadcastHex.length > unsignedHex.length, 'Signed should be longer');
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
(0, mocha_1.describe)('Transaction JSON Representation', () => {
|
|
280
|
+
(0, mocha_1.it)('should produce consistent JSON from built transaction', async () => {
|
|
281
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
282
|
+
builder
|
|
283
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100', memo: '4' })
|
|
284
|
+
.feeToken(mockFeeToken)
|
|
285
|
+
.nonce(50)
|
|
286
|
+
.gas(200000n)
|
|
287
|
+
.maxFeePerGas(3000000000n)
|
|
288
|
+
.maxPriorityFeePerGas(1500000000n);
|
|
289
|
+
const tx = (await builder.build());
|
|
290
|
+
const json = tx.toJson();
|
|
291
|
+
assert_1.default.strictEqual(json.type, constants_1.AA_TRANSACTION_TYPE);
|
|
292
|
+
assert_1.default.strictEqual(json.nonce, 50);
|
|
293
|
+
assert_1.default.strictEqual(json.gas, '200000');
|
|
294
|
+
assert_1.default.strictEqual(json.maxFeePerGas, '3000000000');
|
|
295
|
+
assert_1.default.strictEqual(json.maxPriorityFeePerGas, '1500000000');
|
|
296
|
+
assert_1.default.strictEqual(json.callCount, 1);
|
|
297
|
+
assert_1.default.strictEqual(json.feeToken, mockFeeToken);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
(0, mocha_1.describe)('Transaction id getter', () => {
|
|
301
|
+
(0, mocha_1.it)('unsigned and signed transactions should have different ids', async () => {
|
|
302
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
303
|
+
builder
|
|
304
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '10' })
|
|
305
|
+
.nonce(1)
|
|
306
|
+
.gas(100000n)
|
|
307
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
308
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
309
|
+
const tx = (await builder.build());
|
|
310
|
+
const unsignedId = tx.id;
|
|
311
|
+
tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
|
|
312
|
+
const signedId = tx.id;
|
|
313
|
+
assert_1.default.notStrictEqual(unsignedId, signedId, 'Signed and unsigned tx should have different ids');
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
(0, mocha_1.describe)('outputs / inputs population', () => {
|
|
317
|
+
(0, mocha_1.it)('should expose outputs with base-unit value and token address as coin', async () => {
|
|
318
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
319
|
+
builder
|
|
320
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '1.5', memo: '7' })
|
|
321
|
+
.nonce(0)
|
|
322
|
+
.gas(100000n)
|
|
323
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
324
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
325
|
+
const tx = (await builder.build());
|
|
326
|
+
assert_1.default.strictEqual(tx.outputs.length, 1);
|
|
327
|
+
assert_1.default.strictEqual(tx.outputs[0].address, mockRecipient);
|
|
328
|
+
// 1.5 tokens * 10^6 = 1_500_000 base units
|
|
329
|
+
assert_1.default.strictEqual(tx.outputs[0].value, '1500000');
|
|
330
|
+
// coin is the token contract address, not the chain name
|
|
331
|
+
assert_1.default.strictEqual(tx.outputs[0].coin?.toLowerCase(), mockToken.toLowerCase());
|
|
332
|
+
});
|
|
333
|
+
(0, mocha_1.it)('should expose a single input with the total in base units', async () => {
|
|
334
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
335
|
+
builder
|
|
336
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '1.5' })
|
|
337
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '3.5' })
|
|
338
|
+
.nonce(0)
|
|
339
|
+
.gas(100000n)
|
|
340
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
341
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
342
|
+
const tx = (await builder.build());
|
|
343
|
+
assert_1.default.strictEqual(tx.inputs.length, 1);
|
|
344
|
+
assert_1.default.strictEqual(tx.inputs[0].address, '');
|
|
345
|
+
// (1.5 + 3.5) tokens * 10^6 = 5_000_000 base units
|
|
346
|
+
assert_1.default.strictEqual(tx.inputs[0].value, '5000000');
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
(0, mocha_1.describe)('Round-Trip: Build -> Serialize -> From (deserialization)', () => {
|
|
350
|
+
(0, mocha_1.it)('should round-trip a single-operation transaction without a signature', async () => {
|
|
351
|
+
const operation = { token: mockToken, to: mockRecipient, amount: '25.5', memo: '12345' };
|
|
352
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
353
|
+
builder
|
|
354
|
+
.addOperation(operation)
|
|
355
|
+
.feeToken(mockFeeToken)
|
|
356
|
+
.nonce(7)
|
|
357
|
+
.gas(150000n)
|
|
358
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
359
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
360
|
+
const originalTx = (await builder.build());
|
|
361
|
+
const serialized = await originalTx.serialize();
|
|
362
|
+
// Deserialize via from()
|
|
363
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
364
|
+
builder2.from(serialized);
|
|
365
|
+
const restoredTx = (await builder2.build());
|
|
366
|
+
const ops = restoredTx.getOperations();
|
|
367
|
+
assert_1.default.strictEqual(ops.length, 1);
|
|
368
|
+
assert_1.default.strictEqual(ops[0].token.toLowerCase(), operation.token.toLowerCase());
|
|
369
|
+
assert_1.default.strictEqual(ops[0].to.toLowerCase(), operation.to.toLowerCase());
|
|
370
|
+
assert_1.default.strictEqual(ops[0].amount, operation.amount);
|
|
371
|
+
assert_1.default.strictEqual(ops[0].memo, operation.memo);
|
|
372
|
+
assert_1.default.strictEqual(restoredTx.getFeeToken()?.toLowerCase(), mockFeeToken.toLowerCase());
|
|
373
|
+
});
|
|
374
|
+
(0, mocha_1.it)('should round-trip a batch transaction', async () => {
|
|
375
|
+
// Use amounts that match tip20UnitsToAmount output: ethers formatUnits always includes decimal
|
|
376
|
+
const operations = [
|
|
377
|
+
{ token: tempo_1.TESTNET_TOKENS.alphaUSD.address, to: mockRecipient, amount: '10.0', memo: '1' },
|
|
378
|
+
{ token: tempo_1.TESTNET_TOKENS.betaUSD.address, to: mockRecipient, amount: '20.0', memo: '2' },
|
|
379
|
+
];
|
|
380
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
381
|
+
builder
|
|
382
|
+
.addOperation(operations[0])
|
|
383
|
+
.addOperation(operations[1])
|
|
384
|
+
.nonce(42)
|
|
385
|
+
.gas(250000n)
|
|
386
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
387
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
388
|
+
const originalTx = (await builder.build());
|
|
389
|
+
const serialized = await originalTx.serialize();
|
|
390
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
391
|
+
builder2.from(serialized);
|
|
392
|
+
const restoredTx = (await builder2.build());
|
|
393
|
+
assert_1.default.strictEqual(restoredTx.getOperationCount(), 2);
|
|
394
|
+
assert_1.default.ok(restoredTx.isBatch());
|
|
395
|
+
const json = restoredTx.toJson();
|
|
396
|
+
assert_1.default.strictEqual(json.nonce, 42);
|
|
397
|
+
assert_1.default.strictEqual(json.gas, '250000');
|
|
398
|
+
assert_1.default.strictEqual(json.maxFeePerGas, tempo_1.TX_PARAMS.defaultMaxFeePerGas.toString());
|
|
399
|
+
assert_1.default.strictEqual(json.maxPriorityFeePerGas, tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas.toString());
|
|
400
|
+
const ops = restoredTx.getOperations();
|
|
401
|
+
for (let i = 0; i < operations.length; i++) {
|
|
402
|
+
assert_1.default.strictEqual(ops[i].token.toLowerCase(), operations[i].token.toLowerCase());
|
|
403
|
+
assert_1.default.strictEqual(ops[i].to.toLowerCase(), mockRecipient.toLowerCase());
|
|
404
|
+
assert_1.default.strictEqual(ops[i].amount, operations[i].amount);
|
|
405
|
+
assert_1.default.strictEqual(ops[i].memo, operations[i].memo);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
(0, mocha_1.it)('should round-trip a signed transaction and preserve the signature', async () => {
|
|
409
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
410
|
+
builder
|
|
411
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '5' })
|
|
412
|
+
.nonce(99)
|
|
413
|
+
.gas(100000n)
|
|
414
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
415
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
416
|
+
const tx = (await builder.build());
|
|
417
|
+
tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
|
|
418
|
+
const signedHex = await tx.toBroadcastFormat();
|
|
419
|
+
// Deserialize the signed transaction
|
|
420
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
421
|
+
builder2.from(signedHex);
|
|
422
|
+
const restoredTx = (await builder2.build());
|
|
423
|
+
const sig = restoredTx.getSignature();
|
|
424
|
+
assert_1.default.ok(sig !== undefined, 'Signature should be preserved');
|
|
425
|
+
assert_1.default.strictEqual(sig.yParity, tempo_1.SIGNATURE_TEST_DATA.validSignature.yParity);
|
|
426
|
+
});
|
|
427
|
+
(0, mocha_1.it)('should produce the same tx id after a serialization round-trip', async () => {
|
|
428
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
429
|
+
builder
|
|
430
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100.0', memo: '99' })
|
|
431
|
+
.nonce(3)
|
|
432
|
+
.gas(100000n)
|
|
433
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
434
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
435
|
+
const originalTx = (await builder.build());
|
|
436
|
+
const serialized = await originalTx.serialize();
|
|
437
|
+
const originalId = originalTx.id;
|
|
438
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
439
|
+
builder2.from(serialized);
|
|
440
|
+
const restoredTx = (await builder2.build());
|
|
441
|
+
assert_1.default.strictEqual(restoredTx.id, originalId);
|
|
442
|
+
const originalJson = originalTx.toJson();
|
|
443
|
+
const restoredJson = restoredTx.toJson();
|
|
444
|
+
assert_1.default.strictEqual(restoredJson.nonce, originalJson.nonce);
|
|
445
|
+
assert_1.default.strictEqual(restoredJson.gas, originalJson.gas);
|
|
446
|
+
assert_1.default.strictEqual(restoredJson.maxFeePerGas, originalJson.maxFeePerGas);
|
|
447
|
+
assert_1.default.strictEqual(restoredJson.maxPriorityFeePerGas, originalJson.maxPriorityFeePerGas);
|
|
448
|
+
assert_1.default.strictEqual(restoredJson.feeToken, originalJson.feeToken);
|
|
449
|
+
assert_1.default.strictEqual(restoredJson.callCount, originalJson.callCount);
|
|
450
|
+
const originalOps = originalTx.getOperations();
|
|
451
|
+
const restoredOps = restoredTx.getOperations();
|
|
452
|
+
assert_1.default.strictEqual(restoredOps.length, originalOps.length);
|
|
453
|
+
assert_1.default.strictEqual(restoredOps[0].token.toLowerCase(), originalOps[0].token.toLowerCase());
|
|
454
|
+
assert_1.default.strictEqual(restoredOps[0].to.toLowerCase(), originalOps[0].to.toLowerCase());
|
|
455
|
+
assert_1.default.strictEqual(restoredOps[0].amount, originalOps[0].amount);
|
|
456
|
+
assert_1.default.strictEqual(restoredOps[0].memo, originalOps[0].memo);
|
|
457
|
+
const restoredSerialized = await restoredTx.serialize();
|
|
458
|
+
assert_1.default.strictEqual(restoredSerialized, serialized);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
(0, mocha_1.describe)('Tempo coin - parseTransaction / verifyTransaction', () => {
|
|
463
|
+
let bitgo;
|
|
464
|
+
let coin;
|
|
465
|
+
const mockToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.alphaUSD.address);
|
|
466
|
+
const mockRecipient = ethers_1.ethers.utils.getAddress(tempo_1.TEST_RECIPIENT_ADDRESS);
|
|
467
|
+
(0, mocha_1.before)(function () {
|
|
468
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
469
|
+
bitgo.safeRegister('ttempo', (bg) => {
|
|
470
|
+
const mockStaticsCoin = {
|
|
471
|
+
name: 'ttempo',
|
|
472
|
+
fullName: 'Testnet Tempo',
|
|
473
|
+
network: { type: 'testnet' },
|
|
474
|
+
features: [],
|
|
475
|
+
};
|
|
476
|
+
return ttempo_1.Ttempo.createInstance(bg, mockStaticsCoin);
|
|
477
|
+
});
|
|
478
|
+
bitgo.initializeTestVars();
|
|
479
|
+
coin = bitgo.coin('ttempo');
|
|
480
|
+
});
|
|
481
|
+
async function buildSerializedTx(operations, nonce = 0) {
|
|
482
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
|
|
483
|
+
for (const op of operations) {
|
|
484
|
+
builder.addOperation(op);
|
|
485
|
+
}
|
|
486
|
+
builder
|
|
487
|
+
.nonce(nonce)
|
|
488
|
+
.gas(100000n)
|
|
489
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
490
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
491
|
+
const tx = (await builder.build());
|
|
492
|
+
return tx.serialize();
|
|
493
|
+
}
|
|
494
|
+
(0, mocha_1.describe)('parseTransaction', () => {
|
|
495
|
+
(0, mocha_1.it)('should parse a single-operation transaction into outputs', async () => {
|
|
496
|
+
const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '50', memo: '1' }]);
|
|
497
|
+
const parsed = await coin.parseTransaction({ txHex });
|
|
498
|
+
assert_1.default.ok(Array.isArray(parsed.outputs), 'outputs should be an array');
|
|
499
|
+
assert_1.default.strictEqual(parsed.outputs.length, 1);
|
|
500
|
+
assert_1.default.strictEqual(parsed.outputs[0].address.toLowerCase(), mockRecipient.toLowerCase());
|
|
501
|
+
// 50 tokens * 10^6 = 50_000_000 base units
|
|
502
|
+
assert_1.default.strictEqual(parsed.outputs[0].amount, '50000000');
|
|
503
|
+
});
|
|
504
|
+
(0, mocha_1.it)('should return empty object when no txHex is provided', async () => {
|
|
505
|
+
const parsed = await coin.parseTransaction({});
|
|
506
|
+
assert_1.default.deepStrictEqual(parsed, {});
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
(0, mocha_1.describe)('verifyTransaction', () => {
|
|
510
|
+
(0, mocha_1.it)('should return true when no recipients are specified', async () => {
|
|
511
|
+
const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '10' }]);
|
|
512
|
+
const result = await coin.verifyTransaction({
|
|
513
|
+
txPrebuild: { txHex },
|
|
514
|
+
txParams: {},
|
|
515
|
+
});
|
|
516
|
+
assert_1.default.strictEqual(result, true);
|
|
517
|
+
});
|
|
518
|
+
(0, mocha_1.it)('should return true when recipients match operations', async () => {
|
|
519
|
+
const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '100' }]);
|
|
520
|
+
const result = await coin.verifyTransaction({
|
|
521
|
+
txPrebuild: { txHex },
|
|
522
|
+
txParams: {
|
|
523
|
+
recipients: [{ address: mockRecipient, amount: '100000000' }], // 100 * 10^6 base units
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
assert_1.default.strictEqual(result, true);
|
|
527
|
+
});
|
|
528
|
+
(0, mocha_1.it)('should throw when recipient address does not match', async () => {
|
|
529
|
+
const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '100' }]);
|
|
530
|
+
const wrongAddress = ethers_1.ethers.utils.getAddress('0x1111111111111111111111111111111111111111');
|
|
531
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
532
|
+
txPrebuild: { txHex },
|
|
533
|
+
txParams: { recipients: [{ address: wrongAddress, amount: '100000000' }] },
|
|
534
|
+
}), /recipient mismatch/);
|
|
535
|
+
});
|
|
536
|
+
(0, mocha_1.it)('should throw when recipient amount does not match', async () => {
|
|
537
|
+
const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '100' }]);
|
|
538
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
539
|
+
txPrebuild: { txHex },
|
|
540
|
+
txParams: { recipients: [{ address: mockRecipient, amount: '999' }] },
|
|
541
|
+
}), /amount mismatch/);
|
|
542
|
+
});
|
|
543
|
+
(0, mocha_1.it)('should throw when operation count differs from recipient count', async () => {
|
|
544
|
+
const txHex = await buildSerializedTx([{ token: mockToken, to: mockRecipient, amount: '10' }]);
|
|
545
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
546
|
+
txPrebuild: { txHex },
|
|
547
|
+
txParams: {
|
|
548
|
+
recipients: [
|
|
549
|
+
{ address: mockRecipient, amount: '10000000' },
|
|
550
|
+
{ address: mockRecipient, amount: '10000000' },
|
|
551
|
+
],
|
|
552
|
+
},
|
|
553
|
+
}), /operation\(s\)/);
|
|
554
|
+
});
|
|
555
|
+
(0, mocha_1.it)('should return true when no txHex is provided', async () => {
|
|
556
|
+
const result = await coin.verifyTransaction({ txPrebuild: {}, txParams: {} });
|
|
557
|
+
assert_1.default.strictEqual(result, true);
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
(0, mocha_1.describe)('verifyTransaction with feeToken', () => {
|
|
561
|
+
(0, mocha_1.it)('should verify transaction with matching fee token', async () => {
|
|
562
|
+
const feeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
|
|
563
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
|
|
564
|
+
builder
|
|
565
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
566
|
+
.feeToken(feeToken)
|
|
567
|
+
.nonce(0)
|
|
568
|
+
.gas(100000n)
|
|
569
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
570
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
571
|
+
const tx = (await builder.build());
|
|
572
|
+
const txHex = await tx.serialize();
|
|
573
|
+
const result = await coin.verifyTransaction({
|
|
574
|
+
txPrebuild: { txHex },
|
|
575
|
+
txParams: { feeToken: feeToken },
|
|
576
|
+
});
|
|
577
|
+
assert_1.default.strictEqual(result, true);
|
|
578
|
+
});
|
|
579
|
+
(0, mocha_1.it)('should throw when fee token does not match', async () => {
|
|
580
|
+
const feeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
|
|
581
|
+
const wrongFeeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.alphaUSD.address);
|
|
582
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
|
|
583
|
+
builder
|
|
584
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
585
|
+
.feeToken(feeToken)
|
|
586
|
+
.nonce(0)
|
|
587
|
+
.gas(100000n)
|
|
588
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
589
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
590
|
+
const tx = (await builder.build());
|
|
591
|
+
const txHex = await tx.serialize();
|
|
592
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
593
|
+
txPrebuild: { txHex },
|
|
594
|
+
txParams: { feeToken: wrongFeeToken },
|
|
595
|
+
}), /Fee token mismatch/);
|
|
596
|
+
});
|
|
597
|
+
(0, mocha_1.it)('should throw when fee token is expected but transaction has none', async () => {
|
|
598
|
+
const expectedFeeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
|
|
599
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
|
|
600
|
+
builder
|
|
601
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
602
|
+
.nonce(0)
|
|
603
|
+
.gas(100000n)
|
|
604
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
605
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
606
|
+
const tx = (await builder.build());
|
|
607
|
+
const txHex = await tx.serialize();
|
|
608
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
609
|
+
txPrebuild: { txHex },
|
|
610
|
+
txParams: { feeToken: expectedFeeToken },
|
|
611
|
+
}), /Fee token mismatch/);
|
|
612
|
+
});
|
|
613
|
+
(0, mocha_1.it)('should pass verification when no fee token is specified in params', async () => {
|
|
614
|
+
const feeToken = ethers_1.ethers.utils.getAddress(tempo_1.TESTNET_TOKENS.betaUSD.address);
|
|
615
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
|
|
616
|
+
builder
|
|
617
|
+
.addOperation({ token: mockToken, to: mockRecipient, amount: '100' })
|
|
618
|
+
.feeToken(feeToken)
|
|
619
|
+
.nonce(0)
|
|
620
|
+
.gas(100000n)
|
|
621
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
622
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
623
|
+
const tx = (await builder.build());
|
|
624
|
+
const txHex = await tx.serialize();
|
|
625
|
+
// No feeToken in txParams - should not verify, just pass
|
|
626
|
+
const result = await coin.verifyTransaction({
|
|
627
|
+
txPrebuild: { txHex },
|
|
628
|
+
txParams: {},
|
|
629
|
+
});
|
|
630
|
+
assert_1.default.strictEqual(result, true);
|
|
631
|
+
});
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
(0, mocha_1.describe)('Raw Contract Call Builder', () => {
|
|
635
|
+
const mockContract = ethers_1.ethers.utils.getAddress('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef');
|
|
636
|
+
const mockCalldata = '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e0000000000000000000000000000000000000000000000000000000000989680';
|
|
637
|
+
(0, mocha_1.describe)('addRawCall', () => {
|
|
638
|
+
(0, mocha_1.it)('should add a raw call and return it via getRawCalls()', () => {
|
|
639
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
640
|
+
builder.addRawCall({ to: mockContract, data: mockCalldata });
|
|
641
|
+
const rawCalls = builder.getRawCalls();
|
|
642
|
+
assert_1.default.strictEqual(rawCalls.length, 1);
|
|
643
|
+
assert_1.default.strictEqual(rawCalls[0].to, mockContract);
|
|
644
|
+
assert_1.default.strictEqual(rawCalls[0].data, mockCalldata);
|
|
645
|
+
});
|
|
646
|
+
(0, mocha_1.it)('should support chaining addRawCall', () => {
|
|
647
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
648
|
+
const result = builder.addRawCall({ to: mockContract, data: mockCalldata });
|
|
649
|
+
assert_1.default.strictEqual(result, builder);
|
|
650
|
+
});
|
|
651
|
+
(0, mocha_1.it)('should throw for invalid contract address', () => {
|
|
652
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
653
|
+
assert_1.default.throws(() => builder.addRawCall({ to: '0xinvalid', data: mockCalldata }), /Invalid contract address/);
|
|
654
|
+
});
|
|
655
|
+
(0, mocha_1.it)('should throw for empty calldata', () => {
|
|
656
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
657
|
+
assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: '0x' }), /Invalid calldata/);
|
|
658
|
+
});
|
|
659
|
+
(0, mocha_1.it)('should throw for non-hex calldata', () => {
|
|
660
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
661
|
+
assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: 'not-hex-data' }), /Invalid calldata/);
|
|
662
|
+
});
|
|
663
|
+
(0, mocha_1.it)('should throw for calldata missing 0x prefix', () => {
|
|
664
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
665
|
+
assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: 'a9059cbb' }), /Invalid calldata/);
|
|
666
|
+
});
|
|
667
|
+
(0, mocha_1.it)('should throw for odd-length hex calldata', () => {
|
|
668
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
669
|
+
assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: '0xabc' }), /Invalid calldata/);
|
|
670
|
+
});
|
|
671
|
+
(0, mocha_1.it)('should throw for invalid value string', () => {
|
|
672
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
673
|
+
assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: mockCalldata, value: '1e18' }), /Invalid value/);
|
|
674
|
+
});
|
|
675
|
+
(0, mocha_1.it)('should throw for negative value', () => {
|
|
676
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
677
|
+
assert_1.default.throws(() => builder.addRawCall({ to: mockContract, data: mockCalldata, value: '-1' }), /Invalid value/);
|
|
678
|
+
});
|
|
679
|
+
(0, mocha_1.it)('should allow raw-call-only transaction (no operations)', async () => {
|
|
680
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
681
|
+
builder
|
|
682
|
+
.addRawCall({ to: mockContract, data: mockCalldata })
|
|
683
|
+
.nonce(0)
|
|
684
|
+
.gas(100000n)
|
|
685
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
686
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
687
|
+
const tx = (await builder.build());
|
|
688
|
+
assert_1.default.ok(tx instanceof transaction_1.Tip20Transaction);
|
|
689
|
+
assert_1.default.strictEqual(tx.getOperations().length, 0);
|
|
690
|
+
assert_1.default.strictEqual(tx.getRawCalls().length, 1);
|
|
691
|
+
assert_1.default.strictEqual(tx.getOperationCount(), 1);
|
|
692
|
+
});
|
|
693
|
+
});
|
|
694
|
+
(0, mocha_1.describe)('Round-Trip: Build -> Serialize -> From (raw call deserialization)', () => {
|
|
695
|
+
(0, mocha_1.it)('should preserve raw call calldata through a round-trip', async () => {
|
|
696
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
697
|
+
builder
|
|
698
|
+
.addRawCall({ to: mockContract, data: mockCalldata })
|
|
699
|
+
.nonce(5)
|
|
700
|
+
.gas(150000n)
|
|
701
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
702
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
703
|
+
const originalTx = (await builder.build());
|
|
704
|
+
const serialized = await originalTx.serialize();
|
|
705
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
706
|
+
builder2.from(serialized);
|
|
707
|
+
const restoredTx = (await builder2.build());
|
|
708
|
+
assert_1.default.strictEqual(restoredTx.getOperations().length, 0);
|
|
709
|
+
const rawCalls = restoredTx.getRawCalls();
|
|
710
|
+
assert_1.default.strictEqual(rawCalls.length, 1);
|
|
711
|
+
assert_1.default.strictEqual(rawCalls[0].to.toLowerCase(), mockContract.toLowerCase());
|
|
712
|
+
assert_1.default.strictEqual(rawCalls[0].data.toLowerCase(), mockCalldata.toLowerCase());
|
|
713
|
+
});
|
|
714
|
+
(0, mocha_1.it)('should preserve calldata through a signed round-trip', async () => {
|
|
715
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
716
|
+
builder
|
|
717
|
+
.addRawCall({ to: mockContract, data: mockCalldata })
|
|
718
|
+
.nonce(7)
|
|
719
|
+
.gas(120000n)
|
|
720
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
721
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
722
|
+
const tx = (await builder.build());
|
|
723
|
+
tx.setSignature(tempo_1.SIGNATURE_TEST_DATA.validSignature);
|
|
724
|
+
const signedHex = await tx.toBroadcastFormat();
|
|
725
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
726
|
+
builder2.from(signedHex);
|
|
727
|
+
const restoredTx = (await builder2.build());
|
|
728
|
+
const rawCalls = restoredTx.getRawCalls();
|
|
729
|
+
assert_1.default.strictEqual(rawCalls.length, 1);
|
|
730
|
+
assert_1.default.strictEqual(rawCalls[0].data.toLowerCase(), mockCalldata.toLowerCase());
|
|
731
|
+
const sig = restoredTx.getSignature();
|
|
732
|
+
assert_1.default.ok(sig !== undefined);
|
|
733
|
+
assert_1.default.strictEqual(sig.yParity, tempo_1.SIGNATURE_TEST_DATA.validSignature.yParity);
|
|
734
|
+
});
|
|
735
|
+
(0, mocha_1.it)('should preserve raw call tx id through a round-trip', async () => {
|
|
736
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
737
|
+
builder
|
|
738
|
+
.addRawCall({ to: mockContract, data: mockCalldata })
|
|
739
|
+
.nonce(3)
|
|
740
|
+
.gas(100000n)
|
|
741
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
742
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
743
|
+
const originalTx = (await builder.build());
|
|
744
|
+
const serialized = await originalTx.serialize();
|
|
745
|
+
const originalId = originalTx.id;
|
|
746
|
+
const builder2 = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
747
|
+
builder2.from(serialized);
|
|
748
|
+
const restoredTx = (await builder2.build());
|
|
749
|
+
assert_1.default.strictEqual(restoredTx.id, originalId);
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
(0, mocha_1.describe)('Raw call toJson and outputs', () => {
|
|
753
|
+
(0, mocha_1.it)('should expose raw call contract address as output', async () => {
|
|
754
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
755
|
+
builder
|
|
756
|
+
.addRawCall({ to: mockContract, data: mockCalldata, value: '0' })
|
|
757
|
+
.nonce(2)
|
|
758
|
+
.gas(200000n)
|
|
759
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
760
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
761
|
+
const tx = (await builder.build());
|
|
762
|
+
assert_1.default.strictEqual(tx.outputs.length, 1);
|
|
763
|
+
assert_1.default.strictEqual(tx.outputs[0].address.toLowerCase(), mockContract.toLowerCase());
|
|
764
|
+
});
|
|
765
|
+
(0, mocha_1.it)('should include rawCalls in toJson() output', async () => {
|
|
766
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(mockCoinConfig);
|
|
767
|
+
builder
|
|
768
|
+
.addRawCall({ to: mockContract, data: mockCalldata })
|
|
769
|
+
.nonce(0)
|
|
770
|
+
.gas(100000n)
|
|
771
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
772
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
773
|
+
const tx = (await builder.build());
|
|
774
|
+
const json = tx.toJson();
|
|
775
|
+
assert_1.default.ok(Array.isArray(json.rawCalls));
|
|
776
|
+
assert_1.default.strictEqual(json.rawCalls.length, 1);
|
|
777
|
+
assert_1.default.strictEqual(json.rawCalls[0].to, mockContract);
|
|
778
|
+
assert_1.default.strictEqual(json.rawCalls[0].data, mockCalldata);
|
|
779
|
+
});
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
(0, mocha_1.describe)('Tempo coin - verifyTransaction with raw calls', () => {
|
|
783
|
+
let bitgo;
|
|
784
|
+
let coin;
|
|
785
|
+
const mockContract = ethers_1.ethers.utils.getAddress('0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef');
|
|
786
|
+
const mockCalldata = '0xa9059cbb000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e0000000000000000000000000000000000000000000000000000000000989680';
|
|
787
|
+
(0, mocha_1.before)(function () {
|
|
788
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'mock' });
|
|
789
|
+
bitgo.safeRegister('ttempo', (bg) => {
|
|
790
|
+
const mockStaticsCoin = {
|
|
791
|
+
name: 'ttempo',
|
|
792
|
+
fullName: 'Testnet Tempo',
|
|
793
|
+
network: { type: 'testnet' },
|
|
794
|
+
features: [],
|
|
795
|
+
};
|
|
796
|
+
return ttempo_1.Ttempo.createInstance(bg, mockStaticsCoin);
|
|
797
|
+
});
|
|
798
|
+
bitgo.initializeTestVars();
|
|
799
|
+
coin = bitgo.coin('ttempo');
|
|
800
|
+
});
|
|
801
|
+
async function buildRawCallTx(contract, calldata, nonce = 0) {
|
|
802
|
+
const builder = new transactionBuilder_1.Tip20TransactionBuilder(statics_1.coins.get('ttempo'));
|
|
803
|
+
builder
|
|
804
|
+
.addRawCall({ to: contract, data: calldata })
|
|
805
|
+
.nonce(nonce)
|
|
806
|
+
.gas(150000n)
|
|
807
|
+
.maxFeePerGas(tempo_1.TX_PARAMS.defaultMaxFeePerGas)
|
|
808
|
+
.maxPriorityFeePerGas(tempo_1.TX_PARAMS.defaultMaxPriorityFeePerGas);
|
|
809
|
+
const tx = (await builder.build());
|
|
810
|
+
return tx.serialize();
|
|
811
|
+
}
|
|
812
|
+
(0, mocha_1.it)('should verify a raw call transaction when recipient data matches', async () => {
|
|
813
|
+
const txHex = await buildRawCallTx(mockContract, mockCalldata);
|
|
814
|
+
const result = await coin.verifyTransaction({
|
|
815
|
+
txPrebuild: { txHex },
|
|
816
|
+
txParams: {
|
|
817
|
+
recipients: [{ address: mockContract, amount: '0', data: mockCalldata }],
|
|
818
|
+
},
|
|
819
|
+
});
|
|
820
|
+
assert_1.default.strictEqual(result, true);
|
|
821
|
+
});
|
|
822
|
+
(0, mocha_1.it)('should throw when raw call address does not match recipient', async () => {
|
|
823
|
+
const txHex = await buildRawCallTx(mockContract, mockCalldata);
|
|
824
|
+
const wrongAddress = ethers_1.ethers.utils.getAddress('0x1111111111111111111111111111111111111111');
|
|
825
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
826
|
+
txPrebuild: { txHex },
|
|
827
|
+
txParams: { recipients: [{ address: wrongAddress, amount: '0', data: mockCalldata }] },
|
|
828
|
+
}), /address mismatch/);
|
|
829
|
+
});
|
|
830
|
+
(0, mocha_1.it)('should throw when raw call calldata does not match', async () => {
|
|
831
|
+
const txHex = await buildRawCallTx(mockContract, mockCalldata);
|
|
832
|
+
const wrongCalldata = '0xdeadbeef01020304';
|
|
833
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
834
|
+
txPrebuild: { txHex },
|
|
835
|
+
txParams: { recipients: [{ address: mockContract, amount: '0', data: wrongCalldata }] },
|
|
836
|
+
}), /calldata mismatch/);
|
|
837
|
+
});
|
|
838
|
+
(0, mocha_1.it)('should throw when recipient count does not match call count', async () => {
|
|
839
|
+
const txHex = await buildRawCallTx(mockContract, mockCalldata);
|
|
840
|
+
await assert_1.default.rejects(() => coin.verifyTransaction({
|
|
841
|
+
txPrebuild: { txHex },
|
|
842
|
+
txParams: {
|
|
843
|
+
recipients: [
|
|
844
|
+
{ address: mockContract, amount: '0', data: mockCalldata },
|
|
845
|
+
{ address: mockContract, amount: '0', data: mockCalldata },
|
|
846
|
+
],
|
|
847
|
+
},
|
|
848
|
+
}), /call\(s\)/);
|
|
849
|
+
});
|
|
850
|
+
(0, mocha_1.it)('should parse a raw call transaction and expose the contract as an output', async () => {
|
|
851
|
+
const txHex = await buildRawCallTx(mockContract, mockCalldata);
|
|
852
|
+
const parsed = await coin.parseTransaction({ txHex });
|
|
853
|
+
assert_1.default.ok(Array.isArray(parsed.outputs));
|
|
854
|
+
assert_1.default.strictEqual(parsed.outputs.length, 1);
|
|
855
|
+
assert_1.default.strictEqual(parsed.outputs[0].address.toLowerCase(), mockContract.toLowerCase());
|
|
856
|
+
});
|
|
857
|
+
});
|
|
858
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L3RyYW5zYWN0aW9uQnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE0QjtBQUM1QixpQ0FBNkM7QUFDN0MsbUNBQWdDO0FBQ2hDLHlFQUEyRTtBQUMzRSwyREFBNkQ7QUFDN0QsK0NBTTZCO0FBQzdCLHVEQUE4RTtBQUM5RSxpREFBNEM7QUFDNUMsNkNBQTBDO0FBQzFDLGlEQUErQztBQUMvQyxtREFBK0Q7QUFFL0QsOENBTTRCO0FBRTVCLE1BQU0sY0FBYyxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFM0MsSUFBQSxnQkFBUSxFQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtJQUNoQyxJQUFBLGdCQUFRLEVBQUMsb0JBQW9CLEVBQUUsR0FBRyxFQUFFO1FBQ2xDLElBQUEsVUFBRSxFQUFDLGtEQUFrRCxFQUFFLEdBQUcsRUFBRTtZQUMxRCxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFBLDBCQUFrQixFQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3hELGdCQUFNLENBQUMsV0FBVyxDQUFDLElBQUEsMEJBQWtCLEVBQUMsS0FBSyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDMUQsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsSUFBQSwwQkFBa0IsRUFBQyxVQUFVLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN6RCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsVUFBRSxFQUFDLHVDQUF1QyxFQUFFLEdBQUcsRUFBRTtZQUMvQyxnQkFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFBLDBCQUFrQixFQUFDLFNBQVMsQ0FBQyxFQUFFLHVCQUF1QixDQUFDLENBQUM7UUFDOUUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FB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QUcsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFO2lCQUMzRDthQUNGO1NBQ0YsQ0FBQyxFQUNKLFdBQVcsQ0FDWixDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQywwRUFBMEUsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN4RixNQUFNLEtBQUssR0FBRyxNQUFNLGNBQWMsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELGdCQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDekMsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0MsZ0JBQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDMUYsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGRlc2NyaWJlLCBpdCwgYmVmb3JlIH0gZnJvbSAnbW9jaGEnO1xuaW1wb3J0IHsgZXRoZXJzIH0gZnJvbSAnZXRoZXJzJztcbmltcG9ydCB7IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyIH0gZnJvbSAnLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXInO1xuaW1wb3J0IHsgVGlwMjBUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uL3NyYy9saWIvdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHtcbiAgYW1vdW50VG9UaXAyMFVuaXRzLFxuICB0aXAyMFVuaXRzVG9BbW91bnQsXG4gIHN0cmluZ1RvQnl0ZXMzMixcbiAgZW5jb2RlVGlwMjBUcmFuc2ZlcldpdGhNZW1vLFxuICBpc1ZhbGlkVGlwMjBBbW91bnQsXG59IGZyb20gJy4uLy4uL3NyYy9saWIvdXRpbHMnO1xuaW1wb3J0IHsgVElQMjBfREVDSU1BTFMsIEFBX1RSQU5TQUNUSU9OX1RZUEUgfSBmcm9tICcuLi8uLi9zcmMvbGliL2NvbnN0YW50cyc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgVHRlbXBvIH0gZnJvbSAnLi4vLi4vc3JjL3R0ZW1wbyc7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHb0Jhc2UgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQge1xuICBURVNUTkVUX1RPS0VOUyxcbiAgVFhfUEFSQU1TLFxuICBFUlJPUl9NRVNTQUdFUyxcbiAgU0lHTkFUVVJFX1RFU1RfREFUQSxcbiAgVEVTVF9SRUNJUElFTlRfQUREUkVTUyxcbn0gZnJvbSAnLi4vcmVzb3VyY2VzL3RlbXBvJztcblxuY29uc3QgbW9ja0NvaW5Db25maWcgPSBjb2lucy5nZXQoJ3R0ZW1wbycpO1xuXG5kZXNjcmliZSgnVElQLTIwIFV0aWxpdGllcycsICgpID0+IHtcbiAgZGVzY3JpYmUoJ2Ftb3VudFRvVGlwMjBVbml0cycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGNvbnZlcnQgZGVjaW1hbCBhbW91bnQgdG8gNi1kZWNpbWFsIHVuaXRzJywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGFtb3VudFRvVGlwMjBVbml0cygnMS41JyksIDE1MDAwMDBuKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhbW91bnRUb1RpcDIwVW5pdHMoJzEwMCcpLCAxMDAwMDAwMDBuKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhbW91bnRUb1RpcDIwVW5pdHMoJzAuMDAwMDAxJyksIDFuKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgYW1vdW50JywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBhbW91bnRUb1RpcDIwVW5pdHMoJ2ludmFsaWQnKSwgL0ludmFsaWQgYW1vdW50IGZvcm1hdC8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndGlwMjBVbml0c1RvQW1vdW50JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY29udmVydCA2LWRlY2ltYWwgdW5pdHMgdG8gaHVtYW4tcmVhZGFibGUgYW1vdW50JywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRpcDIwVW5pdHNUb0Ftb3VudCgxNTAwMDAwbiksICcxLjUnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0aXAyMFVuaXRzVG9BbW91bnQoMTAwMDAwMDAwbiksICcxMDAuMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRpcDIwVW5pdHNUb0Ftb3VudCgxbiksICcwLjAwMDAwMScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3RyaW5nVG9CeXRlczMyJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgY29udmVydCBzdHJpbmcgdG8gYnl0ZXMzMicsICgpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHN0cmluZ1RvQnl0ZXMzMignMTIzNDUnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQubGVuZ3RoLCA2Nik7XG4gICAgICBhc3NlcnQub2socmVzdWx0LnN0YXJ0c1dpdGgoJzB4JykpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3Igc3RyaW5nIGxvbmdlciB0aGFuIDMyIGJ5dGVzJywgKCkgPT4ge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBzdHJpbmdUb0J5dGVzMzIoJ2EnLnJlcGVhdCgzMykpLCAvTWVtbyB0b28gbG9uZy8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZW5jb2RlVGlwMjBUcmFuc2ZlcldpdGhNZW1vJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZW5jb2RlIHRyYW5zZmVyV2l0aE1lbW8gY2FsbCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRvID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoJzB4NzQyZDM1Y2M2NjM0YzA1MzI5MjVhM2I4NDRiYzllNzU5NWYwYmViMScpO1xuICAgICAgY29uc3QgZW5jb2RlZCA9IGVuY29kZVRpcDIwVHJhbnNmZXJXaXRoTWVtbyh0bywgMTUwMDAwMG4sICcxMjM0NScpO1xuICAgICAgYXNzZXJ0Lm9rKGVuY29kZWQuc3RhcnRzV2l0aCgnMHgnKSk7XG4gICAgICBhc3NlcnQub2soZW5jb2RlZC5sZW5ndGggPiAxMCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdpc1ZhbGlkVGlwMjBBbW91bnQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB2YWxpZGF0ZSBhbW91bnRzIGNvcnJlY3RseScsICgpID0+IHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkVGlwMjBBbW91bnQoJzEuNScpLCB0cnVlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1ZhbGlkVGlwMjBBbW91bnQoJ2ludmFsaWQnKSwgZmFsc2UpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVmFsaWRUaXAyMEFtb3VudCgnLTUnKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnVElQLTIwIFRyYW5zYWN0aW9uIEJ1aWxkZXInLCAoKSA9PiB7XG4gIGNvbnN0IG1vY2tUb2tlbiA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKCcweDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAnKTtcbiAgY29uc3QgbW9ja1JlY2lwaWVudCA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKCcweDc0MmQzNWNjNjYzNGMwNTMyOTI1YTNiODQ0YmM5ZTc1OTVmMGJlYjEnKTtcbiAgY29uc3QgbW9ja0ZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoJzB4YWJjZGVmYWJjZGVmYWJjZGVmYWJjZGVmYWJjZGVmYWJjZGVmYWJjZCcpO1xuXG4gIGRlc2NyaWJlKCdhZGRPcGVyYXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBhZGQgb3BlcmF0aW9uIHdpdGggYW5kIHdpdGhvdXQgbWVtbycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlci5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KTtcbiAgICAgIGJ1aWxkZXIuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzUwJywgbWVtbzogJzEnIH0pO1xuXG4gICAgICBjb25zdCBvcGVyYXRpb25zID0gYnVpbGRlci5nZXRPcGVyYXRpb25zKCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BlcmF0aW9ucy5sZW5ndGgsIDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9wZXJhdGlvbnNbMF0ubWVtbywgdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcGVyYXRpb25zWzFdLm1lbW8sICcxJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnZhbGlkIGFkZHJlc3NlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gYnVpbGRlci5hZGRPcGVyYXRpb24oeyB0b2tlbjogJzB4aW52YWxpZCcgYXMgYW55LCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KSxcbiAgICAgICAgL0ludmFsaWQgdG9rZW4gYWRkcmVzcy9cbiAgICAgICk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiBidWlsZGVyLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiAnMHhpbnZhbGlkJyBhcyBhbnksIGFtb3VudDogJzEwMCcgfSksXG4gICAgICAgIC9JbnZhbGlkIHJlY2lwaWVudCBhZGRyZXNzL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgYW1vdW50JywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PiBidWlsZGVyLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICdpbnZhbGlkLWFtb3VudCcgfSksXG4gICAgICAgIC9JbnZhbGlkIGFtb3VudC9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBpbnZhbGlkIChub24tbnVtZXJpYykgbWVtbycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gYnVpbGRlci5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJywgbWVtbzogJ0lOVi0wMDEnIH0pLFxuICAgICAgICAvSW52YWxpZCBtZW1vL1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2ZlZVRva2VuJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgc2V0IGFuZCBnZXQgZmVlIHRva2VuJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyLmZlZVRva2VuKG1vY2tGZWVUb2tlbik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnVpbGRlci5nZXRGZWVUb2tlbigpLCBtb2NrRmVlVG9rZW4pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBmZWUgdG9rZW4gYWRkcmVzcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLmZlZVRva2VuKCdpbnZhbGlkLWFkZHJlc3MnKSwgL0ludmFsaWQgZmVlIHRva2VuIGFkZHJlc3MvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIHBhcmFtZXRlcnMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBzZXQgbm9uY2UsIGdhcywgbWF4RmVlUGVyR2FzLCBhbmQgbWF4UHJpb3JpdHlGZWVQZXJHYXMnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXIubm9uY2UoNDIpLmdhcyg1MDAwMDBuKS5tYXhGZWVQZXJHYXMoMTAwMDAwMDAwMG4pLm1heFByaW9yaXR5RmVlUGVyR2FzKDUwMDAwMDAwMG4pO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoKGJ1aWxkZXIgYXMgYW55KS5fbm9uY2UsIDQyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCgoYnVpbGRlciBhcyBhbnkpLl9nYXMsIDUwMDAwMG4pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKChidWlsZGVyIGFzIGFueSkuX21heEZlZVBlckdhcywgMTAwMDAwMDAwMG4pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKChidWlsZGVyIGFzIGFueSkuX21heFByaW9yaXR5RmVlUGVyR2FzLCA1MDAwMDAwMDBuKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgbm9uY2UgYW5kIGdhcycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLm5vbmNlKC0xKSwgL0ludmFsaWQgbm9uY2UvKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gYnVpbGRlci5nYXMoMG4pLCAvSW52YWxpZCBnYXMgbGltaXQvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ01ldGhvZCBjaGFpbmluZycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHN1cHBvcnQgZmx1ZW50IGludGVyZmFjZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcsIG1lbW86ICc1JyB9KVxuICAgICAgICAuZmVlVG9rZW4obW9ja0ZlZVRva2VuKVxuICAgICAgICAubm9uY2UoMTApXG4gICAgICAgIC5nYXMoNDAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcygyMDAwMDAwMDAwbilcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKDEwMDAwMDAwMDBuKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgYnVpbGRlcik7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdUSVAtMjAgQ29uc3RhbnRzJywgKCkgPT4ge1xuICBpdCgnc2hvdWxkIGhhdmUgY29ycmVjdCBkZWNpbWFsIHBsYWNlcycsICgpID0+IHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoVElQMjBfREVDSU1BTFMsIDYpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnVElQLTIwIFRyYW5zYWN0aW9uIEJ1aWxkJywgKCkgPT4ge1xuICBjb25zdCBtb2NrVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5hbHBoYVVTRC5hZGRyZXNzKTtcbiAgY29uc3QgbW9ja1JlY2lwaWVudCA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKFRFU1RfUkVDSVBJRU5UX0FERFJFU1MpO1xuICBjb25zdCBtb2NrRmVlVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5iZXRhVVNELmFkZHJlc3MpO1xuXG4gIGRlc2NyaWJlKCdCdWlsZCBUcmFuc2FjdGlvbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHNpbmdsZS1vcGVyYXRpb24gdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnLCBtZW1vOiAnMScgfSlcbiAgICAgICAgLmZlZVRva2VuKG1vY2tGZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG5cbiAgICAgIGFzc2VydC5vayh0eCBpbnN0YW5jZW9mIFRpcDIwVHJhbnNhY3Rpb24pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldE9wZXJhdGlvbkNvdW50KCksIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldEZlZVRva2VuKCksIG1vY2tGZWVUb2tlbik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGJ1aWxkIGJhdGNoIHRyYW5zYWN0aW9uIHdpdGggbXVsdGlwbGUgb3BlcmF0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmFscGhhVVNELmFkZHJlc3MsIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMCcsIG1lbW86ICcxJyB9KVxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmJldGFVU0QuYWRkcmVzcywgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzIwJywgbWVtbzogJzInIH0pXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogVEVTVE5FVF9UT0tFTlMudGhldGFVU0QuYWRkcmVzcywgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzMwJywgbWVtbzogJzMnIH0pXG4gICAgICAgIC5mZWVUb2tlbihtb2NrRmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSg0MilcbiAgICAgICAgLmdhcygzMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcblxuICAgICAgYXNzZXJ0Lm9rKHR4IGluc3RhbmNlb2YgVGlwMjBUcmFuc2FjdGlvbik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguZ2V0T3BlcmF0aW9uQ291bnQoKSwgMyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguaXNCYXRjaCgpLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgdHJhbnNhY3Rpb24gd2l0aG91dCBmZWUgdG9rZW4nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICc1MCcgfSlcbiAgICAgICAgLm5vbmNlKDEpXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG5cbiAgICAgIGFzc2VydC5vayh0eCBpbnN0YW5jZW9mIFRpcDIwVHJhbnNhY3Rpb24pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldEZlZVRva2VuKCksIHVuZGVmaW5lZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCdWlsZCBWYWxpZGF0aW9uIEVycm9ycycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbm8gb3BlcmF0aW9ucyBhZGRlZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlci5ub25jZSgwKS5nYXMoMTAwMDAwbikubWF4RmVlUGVyR2FzKDEwMDAwMDAwMDBuKS5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgL0F0IGxlYXN0IG9uZSBvcGVyYXRpb24gb3IgcmF3IGNhbGwgaXMgcmVxdWlyZWQvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBub25jZSBub3Qgc2V0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoMTAwMDAwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgRVJST1JfTUVTU0FHRVMubWlzc2luZ05vbmNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBnYXMgbm90IHNldCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfSlcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoMTAwMDAwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgRVJST1JfTUVTU0FHRVMubWlzc2luZ0dhcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbWF4RmVlUGVyR2FzIG5vdCBzZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH0pXG4gICAgICAgIC5ub25jZSgwKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyg1MDAwMDAwMDBuKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSwgRVJST1JfTUVTU0FHRVMubWlzc2luZ01heEZlZVBlckdhcyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbWF4UHJpb3JpdHlGZWVQZXJHYXMgbm90IHNldCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfSlcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcygxMDAwMDAwMDAwbik7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBhd2FpdCBidWlsZGVyLmJ1aWxkKCksIEVSUk9SX01FU1NBR0VTLm1pc3NpbmdNYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSb3VuZC1UcmlwOiBCdWlsZCAtPiBTZXJpYWxpemUgLT4gT3BlcmF0aW9ucyBDaGVjaycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIG9wZXJhdGlvbiBkYXRhIHRocm91Z2ggYnVpbGQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBvcGVyYXRpb25zID0gW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEyMycsIG1lbW86ICcxJyB9XTtcblxuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24ob3BlcmF0aW9uc1swXSlcbiAgICAgICAgLmZlZVRva2VuKG1vY2tGZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDEwKVxuICAgICAgICAuZ2FzKDE1MDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoMjAwMDAwMDAwMG4pXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcygxMDAwMDAwMDAwbik7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHR4T3BzID0gdHguZ2V0T3BlcmF0aW9ucygpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHhPcHMubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eE9wc1swXS50b2tlbiwgb3BlcmF0aW9uc1swXS50b2tlbik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHhPcHNbMF0udG8sIG9wZXJhdGlvbnNbMF0udG8pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4T3BzWzBdLmFtb3VudCwgb3BlcmF0aW9uc1swXS5hbW91bnQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4T3BzWzBdLm1lbW8sIG9wZXJhdGlvbnNbMF0ubWVtbyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCdWlsZCAtPiBTZXJpYWxpemUgLT4gU2lnbiBGbG93JywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBzZXJpYWxpemFibGUgdW5zaWduZWQgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICc1MCcsIG1lbW86ICcyJyB9KVxuICAgICAgICAuZmVlVG9rZW4obW9ja0ZlZVRva2VuKVxuICAgICAgICAubm9uY2UoNSlcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKDIwMDAwMDAwMDBuKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoMTAwMDAwMDAwMG4pO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB1bnNpZ25lZEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBhc3NlcnQub2sodW5zaWduZWRIZXguc3RhcnRzV2l0aChBQV9UUkFOU0FDVElPTl9UWVBFKSk7XG4gICAgICBhc3NlcnQub2soL14weFswLTlhLWZdKyQvaS50ZXN0KHVuc2lnbmVkSGV4KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1cHBvcnQgZnVsbCBzaWduIGFuZCBicm9hZGNhc3QgZmxvdycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzc1JywgbWVtbzogJzMnIH0pXG4gICAgICAgIC5mZWVUb2tlbihtb2NrRmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSgxMjMpXG4gICAgICAgIC5nYXMoMTIwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcygyNTAwMDAwMDAwbilcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKDEyMDAwMDAwMDBuKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgYnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgdW5zaWduZWRIZXggPSBhd2FpdCB0eC5zZXJpYWxpemUoKTtcblxuICAgICAgdHguc2V0U2lnbmF0dXJlKFNJR05BVFVSRV9URVNUX0RBVEEudmFsaWRTaWduYXR1cmUpO1xuXG4gICAgICBjb25zdCBicm9hZGNhc3RIZXggPSBhd2FpdCB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuICAgICAgYXNzZXJ0Lm9rKGJyb2FkY2FzdEhleC5zdGFydHNXaXRoKEFBX1RSQU5TQUNUSU9OX1RZUEUpKTtcbiAgICAgIGFzc2VydC5vayhicm9hZGNhc3RIZXgubGVuZ3RoID4gdW5zaWduZWRIZXgubGVuZ3RoLCAnU2lnbmVkIHNob3VsZCBiZSBsb25nZXInKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIEpTT04gUmVwcmVzZW50YXRpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGNvbnNpc3RlbnQgSlNPTiBmcm9tIGJ1aWx0IHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJywgbWVtbzogJzQnIH0pXG4gICAgICAgIC5mZWVUb2tlbihtb2NrRmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSg1MClcbiAgICAgICAgLmdhcygyMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKDMwMDAwMDAwMDBuKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoMTUwMDAwMDAwMG4pO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBqc29uID0gdHgudG9Kc29uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLnR5cGUsIEFBX1RSQU5TQUNUSU9OX1RZUEUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ubm9uY2UsIDUwKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLmdhcywgJzIwMDAwMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ubWF4RmVlUGVyR2FzLCAnMzAwMDAwMDAwMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ubWF4UHJpb3JpdHlGZWVQZXJHYXMsICcxNTAwMDAwMDAwJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5jYWxsQ291bnQsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24uZmVlVG9rZW4sIG1vY2tGZWVUb2tlbik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBpZCBnZXR0ZXInLCAoKSA9PiB7XG4gICAgaXQoJ3Vuc2lnbmVkIGFuZCBzaWduZWQgdHJhbnNhY3Rpb25zIHNob3VsZCBoYXZlIGRpZmZlcmVudCBpZHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMCcgfSlcbiAgICAgICAgLm5vbmNlKDEpXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB1bnNpZ25lZElkID0gdHguaWQ7XG5cbiAgICAgIHR4LnNldFNpZ25hdHVyZShTSUdOQVRVUkVfVEVTVF9EQVRBLnZhbGlkU2lnbmF0dXJlKTtcbiAgICAgIGNvbnN0IHNpZ25lZElkID0gdHguaWQ7XG5cbiAgICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbCh1bnNpZ25lZElkLCBzaWduZWRJZCwgJ1NpZ25lZCBhbmQgdW5zaWduZWQgdHggc2hvdWxkIGhhdmUgZGlmZmVyZW50IGlkcycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnb3V0cHV0cyAvIGlucHV0cyBwb3B1bGF0aW9uJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgZXhwb3NlIG91dHB1dHMgd2l0aCBiYXNlLXVuaXQgdmFsdWUgYW5kIHRva2VuIGFkZHJlc3MgYXMgY29pbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEuNScsIG1lbW86ICc3JyB9KVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5vdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHgub3V0cHV0c1swXS5hZGRyZXNzLCBtb2NrUmVjaXBpZW50KTtcbiAgICAgIC8vIDEuNSB0b2tlbnMgKiAxMF42ID0gMV81MDBfMDAwIGJhc2UgdW5pdHNcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5vdXRwdXRzWzBdLnZhbHVlLCAnMTUwMDAwMCcpO1xuICAgICAgLy8gY29pbiBpcyB0aGUgdG9rZW4gY29udHJhY3QgYWRkcmVzcywgbm90IHRoZSBjaGFpbiBuYW1lXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHgub3V0cHV0c1swXS5jb2luPy50b0xvd2VyQ2FzZSgpLCBtb2NrVG9rZW4udG9Mb3dlckNhc2UoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cG9zZSBhIHNpbmdsZSBpbnB1dCB3aXRoIHRoZSB0b3RhbCBpbiBiYXNlIHVuaXRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMS41JyB9KVxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzMuNScgfSlcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguaW5wdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHguaW5wdXRzWzBdLmFkZHJlc3MsICcnKTtcbiAgICAgIC8vICgxLjUgKyAzLjUpIHRva2VucyAqIDEwXjYgPSA1XzAwMF8wMDAgYmFzZSB1bml0c1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmlucHV0c1swXS52YWx1ZSwgJzUwMDAwMDAnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JvdW5kLVRyaXA6IEJ1aWxkIC0+IFNlcmlhbGl6ZSAtPiBGcm9tIChkZXNlcmlhbGl6YXRpb24pJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNpbmdsZS1vcGVyYXRpb24gdHJhbnNhY3Rpb24gd2l0aG91dCBhIHNpZ25hdHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IG9wZXJhdGlvbiA9IHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzI1LjUnLCBtZW1vOiAnMTIzNDUnIH07XG5cbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKG9wZXJhdGlvbilcbiAgICAgICAgLmZlZVRva2VuKG1vY2tGZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDcpXG4gICAgICAgIC5nYXMoMTUwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBhd2FpdCBvcmlnaW5hbFR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICAvLyBEZXNlcmlhbGl6ZSB2aWEgZnJvbSgpXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBjb25zdCBvcHMgPSByZXN0b3JlZFR4LmdldE9wZXJhdGlvbnMoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHMubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHNbMF0udG9rZW4udG9Mb3dlckNhc2UoKSwgb3BlcmF0aW9uLnRva2VuLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9wc1swXS50by50b0xvd2VyQ2FzZSgpLCBvcGVyYXRpb24udG8udG9Mb3dlckNhc2UoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BzWzBdLmFtb3VudCwgb3BlcmF0aW9uLmFtb3VudCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BzWzBdLm1lbW8sIG9wZXJhdGlvbi5tZW1vKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZFR4LmdldEZlZVRva2VuKCk/LnRvTG93ZXJDYXNlKCksIG1vY2tGZWVUb2tlbi50b0xvd2VyQ2FzZSgpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIGJhdGNoIHRyYW5zYWN0aW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gVXNlIGFtb3VudHMgdGhhdCBtYXRjaCB0aXAyMFVuaXRzVG9BbW91bnQgb3V0cHV0OiBldGhlcnMgZm9ybWF0VW5pdHMgYWx3YXlzIGluY2x1ZGVzIGRlY2ltYWxcbiAgICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBbXG4gICAgICAgIHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmFscGhhVVNELmFkZHJlc3MsIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMC4wJywgbWVtbzogJzEnIH0sXG4gICAgICAgIHsgdG9rZW46IFRFU1RORVRfVE9LRU5TLmJldGFVU0QuYWRkcmVzcywgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzIwLjAnLCBtZW1vOiAnMicgfSxcbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKG9wZXJhdGlvbnNbMF0pXG4gICAgICAgIC5hZGRPcGVyYXRpb24ob3BlcmF0aW9uc1sxXSlcbiAgICAgICAgLm5vbmNlKDQyKVxuICAgICAgICAuZ2FzKDI1MDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxUeCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gYXdhaXQgb3JpZ2luYWxUeC5zZXJpYWxpemUoKTtcblxuICAgICAgY29uc3QgYnVpbGRlcjIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlcjIuZnJvbShzZXJpYWxpemVkKTtcbiAgICAgIGNvbnN0IHJlc3RvcmVkVHggPSAoYXdhaXQgYnVpbGRlcjIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkVHguZ2V0T3BlcmF0aW9uQ291bnQoKSwgMik7XG4gICAgICBhc3NlcnQub2socmVzdG9yZWRUeC5pc0JhdGNoKCkpO1xuXG4gICAgICBjb25zdCBqc29uID0gcmVzdG9yZWRUeC50b0pzb24oKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLm5vbmNlLCA0Mik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5nYXMsICcyNTAwMDAnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uLm1heEZlZVBlckdhcywgVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMudG9TdHJpbmcoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5tYXhQcmlvcml0eUZlZVBlckdhcywgVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcy50b1N0cmluZygpKTtcblxuICAgICAgY29uc3Qgb3BzID0gcmVzdG9yZWRUeC5nZXRPcGVyYXRpb25zKCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9wZXJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9wc1tpXS50b2tlbi50b0xvd2VyQ2FzZSgpLCBvcGVyYXRpb25zW2ldLnRva2VuLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3BzW2ldLnRvLnRvTG93ZXJDYXNlKCksIG1vY2tSZWNpcGllbnQudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHNbaV0uYW1vdW50LCBvcGVyYXRpb25zW2ldLmFtb3VudCk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvcHNbaV0ubWVtbywgb3BlcmF0aW9uc1tpXS5tZW1vKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcm91bmQtdHJpcCBhIHNpZ25lZCB0cmFuc2FjdGlvbiBhbmQgcHJlc2VydmUgdGhlIHNpZ25hdHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzUnIH0pXG4gICAgICAgIC5ub25jZSg5OSlcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIHR4LnNldFNpZ25hdHVyZShTSUdOQVRVUkVfVEVTVF9EQVRBLnZhbGlkU2lnbmF0dXJlKTtcbiAgICAgIGNvbnN0IHNpZ25lZEhleCA9IGF3YWl0IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIC8vIERlc2VyaWFsaXplIHRoZSBzaWduZWQgdHJhbnNhY3Rpb25cbiAgICAgIGNvbnN0IGJ1aWxkZXIyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXIyLmZyb20oc2lnbmVkSGV4KTtcbiAgICAgIGNvbnN0IHJlc3RvcmVkVHggPSAoYXdhaXQgYnVpbGRlcjIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcblxuICAgICAgY29uc3Qgc2lnID0gcmVzdG9yZWRUeC5nZXRTaWduYXR1cmUoKTtcbiAgICAgIGFzc2VydC5vayhzaWcgIT09IHVuZGVmaW5lZCwgJ1NpZ25hdHVyZSBzaG91bGQgYmUgcHJlc2VydmVkJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnIS55UGFyaXR5LCBTSUdOQVRVUkVfVEVTVF9EQVRBLnZhbGlkU2lnbmF0dXJlLnlQYXJpdHkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIHRoZSBzYW1lIHR4IGlkIGFmdGVyIGEgc2VyaWFsaXphdGlvbiByb3VuZC10cmlwJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwLjAnLCBtZW1vOiAnOTknIH0pXG4gICAgICAgIC5ub25jZSgzKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxUeCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gYXdhaXQgb3JpZ2luYWxUeC5zZXJpYWxpemUoKTtcbiAgICAgIGNvbnN0IG9yaWdpbmFsSWQgPSBvcmlnaW5hbFR4LmlkO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRUeC5pZCwgb3JpZ2luYWxJZCk7XG5cbiAgICAgIGNvbnN0IG9yaWdpbmFsSnNvbiA9IG9yaWdpbmFsVHgudG9Kc29uKCk7XG4gICAgICBjb25zdCByZXN0b3JlZEpzb24gPSByZXN0b3JlZFR4LnRvSnNvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkSnNvbi5ub25jZSwgb3JpZ2luYWxKc29uLm5vbmNlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZEpzb24uZ2FzLCBvcmlnaW5hbEpzb24uZ2FzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZEpzb24ubWF4RmVlUGVyR2FzLCBvcmlnaW5hbEpzb24ubWF4RmVlUGVyR2FzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZEpzb24ubWF4UHJpb3JpdHlGZWVQZXJHYXMsIG9yaWdpbmFsSnNvbi5tYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRKc29uLmZlZVRva2VuLCBvcmlnaW5hbEpzb24uZmVlVG9rZW4pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkSnNvbi5jYWxsQ291bnQsIG9yaWdpbmFsSnNvbi5jYWxsQ291bnQpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbE9wcyA9IG9yaWdpbmFsVHguZ2V0T3BlcmF0aW9ucygpO1xuICAgICAgY29uc3QgcmVzdG9yZWRPcHMgPSByZXN0b3JlZFR4LmdldE9wZXJhdGlvbnMoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN0b3JlZE9wcy5sZW5ndGgsIG9yaWdpbmFsT3BzLmxlbmd0aCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRPcHNbMF0udG9rZW4udG9Mb3dlckNhc2UoKSwgb3JpZ2luYWxPcHNbMF0udG9rZW4udG9Mb3dlckNhc2UoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRPcHNbMF0udG8udG9Mb3dlckNhc2UoKSwgb3JpZ2luYWxPcHNbMF0udG8udG9Mb3dlckNhc2UoKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRPcHNbMF0uYW1vdW50LCBvcmlnaW5hbE9wc1swXS5hbW91bnQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkT3BzWzBdLm1lbW8sIG9yaWdpbmFsT3BzWzBdLm1lbW8pO1xuXG4gICAgICBjb25zdCByZXN0b3JlZFNlcmlhbGl6ZWQgPSBhd2FpdCByZXN0b3JlZFR4LnNlcmlhbGl6ZSgpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3RvcmVkU2VyaWFsaXplZCwgc2VyaWFsaXplZCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdUZW1wbyBjb2luIC0gcGFyc2VUcmFuc2FjdGlvbiAvIHZlcmlmeVRyYW5zYWN0aW9uJywgKCkgPT4ge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IGFueTtcblxuICBjb25zdCBtb2NrVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5hbHBoYVVTRC5hZGRyZXNzKTtcbiAgY29uc3QgbW9ja1JlY2lwaWVudCA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKFRFU1RfUkVDSVBJRU5UX0FERFJFU1MpO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0dGVtcG8nLCAoYmc6IEJpdEdvQmFzZSkgPT4ge1xuICAgICAgY29uc3QgbW9ja1N0YXRpY3NDb2luID0ge1xuICAgICAgICBuYW1lOiAndHRlbXBvJyxcbiAgICAgICAgZnVsbE5hbWU6ICdUZXN0bmV0IFRlbXBvJyxcbiAgICAgICAgbmV0d29yazogeyB0eXBlOiAndGVzdG5ldCcgfSxcbiAgICAgICAgZmVhdHVyZXM6IFtdLFxuICAgICAgfSBhcyBhbnk7XG4gICAgICByZXR1cm4gVHRlbXBvLmNyZWF0ZUluc3RhbmNlKGJnLCBtb2NrU3RhdGljc0NvaW4pO1xuICAgIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGNvaW4gPSBiaXRnby5jb2luKCd0dGVtcG8nKTtcbiAgfSk7XG5cbiAgYXN5bmMgZnVuY3Rpb24gYnVpbGRTZXJpYWxpemVkVHgoXG4gICAgb3BlcmF0aW9uczogeyB0b2tlbjogc3RyaW5nOyB0bzogc3RyaW5nOyBhbW91bnQ6IHN0cmluZzsgbWVtbz86IHN0cmluZyB9W10sXG4gICAgbm9uY2UgPSAwXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihjb2lucy5nZXQoJ3R0ZW1wbycpKTtcbiAgICBmb3IgKGNvbnN0IG9wIG9mIG9wZXJhdGlvbnMpIHtcbiAgICAgIGJ1aWxkZXIuYWRkT3BlcmF0aW9uKG9wKTtcbiAgICB9XG4gICAgYnVpbGRlclxuICAgICAgLm5vbmNlKG5vbmNlKVxuICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcbiAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgcmV0dXJuIHR4LnNlcmlhbGl6ZSgpO1xuICB9XG5cbiAgZGVzY3JpYmUoJ3BhcnNlVHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhIHNpbmdsZS1vcGVyYXRpb24gdHJhbnNhY3Rpb24gaW50byBvdXRwdXRzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZFNlcmlhbGl6ZWRUeChbeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnNTAnLCBtZW1vOiAnMScgfV0pO1xuICAgICAgY29uc3QgcGFyc2VkID0gYXdhaXQgY29pbi5wYXJzZVRyYW5zYWN0aW9uKHsgdHhIZXggfSk7XG4gICAgICBhc3NlcnQub2soQXJyYXkuaXNBcnJheShwYXJzZWQub3V0cHV0cyksICdvdXRwdXRzIHNob3VsZCBiZSBhbiBhcnJheScpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLm91dHB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLCBtb2NrUmVjaXBpZW50LnRvTG93ZXJDYXNlKCkpO1xuICAgICAgLy8gNTAgdG9rZW5zICogMTBeNiA9IDUwXzAwMF8wMDAgYmFzZSB1bml0c1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzWzBdLmFtb3VudCwgJzUwMDAwMDAwJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBvYmplY3Qgd2hlbiBubyB0eEhleCBpcyBwcm92aWRlZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IGNvaW4ucGFyc2VUcmFuc2FjdGlvbih7fSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZCwge30pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24nLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIG5vIHJlY2lwaWVudHMgYXJlIHNwZWNpZmllZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRTZXJpYWxpemVkVHgoW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwJyB9XSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gdHJ1ZSB3aGVuIHJlY2lwaWVudHMgbWF0Y2ggb3BlcmF0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRTZXJpYWxpemVkVHgoW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfV0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29pbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAwMDAwMDAnIH1dLCAvLyAxMDAgKiAxMF42IGJhc2UgdW5pdHNcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gcmVjaXBpZW50IGFkZHJlc3MgZG9lcyBub3QgbWF0Y2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkU2VyaWFsaXplZFR4KFt7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH1dKTtcbiAgICAgIGNvbnN0IHdyb25nQWRkcmVzcyA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKCcweDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEnKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogd3JvbmdBZGRyZXNzLCBhbW91bnQ6ICcxMDAwMDAwMDAnIH1dIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIC9yZWNpcGllbnQgbWlzbWF0Y2gvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHJlY2lwaWVudCBhbW91bnQgZG9lcyBub3QgbWF0Y2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkU2VyaWFsaXplZFR4KFt7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH1dKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnOTk5JyB9XSB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICAvYW1vdW50IG1pc21hdGNoL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBvcGVyYXRpb24gY291bnQgZGlmZmVycyBmcm9tIHJlY2lwaWVudCBjb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRTZXJpYWxpemVkVHgoW3sgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwJyB9XSk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICAgICAgICB7IGFkZHJlc3M6IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMDAwMDAwJyB9LFxuICAgICAgICAgICAgICAgIHsgYWRkcmVzczogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwMDAwMDAnIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICAvb3BlcmF0aW9uXFwoc1xcKS9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIHdoZW4gbm8gdHhIZXggaXMgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZDoge30sIHR4UGFyYW1zOiB7fSB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24gd2l0aCBmZWVUb2tlbicsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHZlcmlmeSB0cmFuc2FjdGlvbiB3aXRoIG1hdGNoaW5nIGZlZSB0b2tlbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoVEVTVE5FVF9UT0tFTlMuYmV0YVVTRC5hZGRyZXNzKTtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KCd0dGVtcG8nKSk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KVxuICAgICAgICAuZmVlVG9rZW4oZmVlVG9rZW4pXG4gICAgICAgIC5ub25jZSgwKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgdHguc2VyaWFsaXplKCk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0sXG4gICAgICAgIHR4UGFyYW1zOiB7IGZlZVRva2VuOiBmZWVUb2tlbiB9LFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCB0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBmZWUgdG9rZW4gZG9lcyBub3QgbWF0Y2gnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBmZWVUb2tlbiA9IGV0aGVycy51dGlscy5nZXRBZGRyZXNzKFRFU1RORVRfVE9LRU5TLmJldGFVU0QuYWRkcmVzcyk7XG4gICAgICBjb25zdCB3cm9uZ0ZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoVEVTVE5FVF9UT0tFTlMuYWxwaGFVU0QuYWRkcmVzcyk7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKGNvaW5zLmdldCgndHRlbXBvJykpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkT3BlcmF0aW9uKHsgdG9rZW46IG1vY2tUb2tlbiwgdG86IG1vY2tSZWNpcGllbnQsIGFtb3VudDogJzEwMCcgfSlcbiAgICAgICAgLmZlZVRva2VuKGZlZVRva2VuKVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7IGZlZVRva2VuOiB3cm9uZ0ZlZVRva2VuIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIC9GZWUgdG9rZW4gbWlzbWF0Y2gvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGZlZSB0b2tlbiBpcyBleHBlY3RlZCBidXQgdHJhbnNhY3Rpb24gaGFzIG5vbmUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBleHBlY3RlZEZlZVRva2VuID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoVEVTVE5FVF9UT0tFTlMuYmV0YVVTRC5hZGRyZXNzKTtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KCd0dGVtcG8nKSk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRPcGVyYXRpb24oeyB0b2tlbjogbW9ja1Rva2VuLCB0bzogbW9ja1JlY2lwaWVudCwgYW1vdW50OiAnMTAwJyB9KVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IHR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICAgIHR4UGFyYW1zOiB7IGZlZVRva2VuOiBleHBlY3RlZEZlZVRva2VuIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIC9GZWUgdG9rZW4gbWlzbWF0Y2gvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXNzIHZlcmlmaWNhdGlvbiB3aGVuIG5vIGZlZSB0b2tlbiBpcyBzcGVjaWZpZWQgaW4gcGFyYW1zJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZmVlVG9rZW4gPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcyhURVNUTkVUX1RPS0VOUy5iZXRhVVNELmFkZHJlc3MpO1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihjb2lucy5nZXQoJ3R0ZW1wbycpKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZE9wZXJhdGlvbih7IHRva2VuOiBtb2NrVG9rZW4sIHRvOiBtb2NrUmVjaXBpZW50LCBhbW91bnQ6ICcxMDAnIH0pXG4gICAgICAgIC5mZWVUb2tlbihmZWVUb2tlbilcbiAgICAgICAgLm5vbmNlKDApXG4gICAgICAgIC5nYXMoMTAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuICAgICAgY29uc3QgdHggPSAoYXdhaXQgYnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCB0eC5zZXJpYWxpemUoKTtcblxuICAgICAgLy8gTm8gZmVlVG9rZW4gaW4gdHhQYXJhbXMgLSBzaG91bGQgbm90IHZlcmlmeSwganVzdCBwYXNzXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9LFxuICAgICAgICB0eFBhcmFtczoge30sXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHRydWUpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnUmF3IENvbnRyYWN0IENhbGwgQnVpbGRlcicsICgpID0+IHtcbiAgY29uc3QgbW9ja0NvbnRyYWN0ID0gZXRoZXJzLnV0aWxzLmdldEFkZHJlc3MoJzB4ZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZicpO1xuICBjb25zdCBtb2NrQ2FsbGRhdGEgPVxuICAgICcweGE5MDU5Y2JiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNzQyZDM1Y2M2NjM0YzA1MzI5MjVhM2I4NDRiYzQ1NGU0NDM4ZjQ0ZTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA5ODk2ODAnO1xuXG4gIGRlc2NyaWJlKCdhZGRSYXdDYWxsJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgYWRkIGEgcmF3IGNhbGwgYW5kIHJldHVybiBpdCB2aWEgZ2V0UmF3Q2FsbHMoKScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pO1xuXG4gICAgICBjb25zdCByYXdDYWxscyA9IGJ1aWxkZXIuZ2V0UmF3Q2FsbHMoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyYXdDYWxscy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzWzBdLnRvLCBtb2NrQ29udHJhY3QpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzWzBdLmRhdGEsIG1vY2tDYWxsZGF0YSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHN1cHBvcnQgY2hhaW5pbmcgYWRkUmF3Q2FsbCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgYnVpbGRlcik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIGNvbnRyYWN0IGFkZHJlc3MnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86ICcweGludmFsaWQnLCBkYXRhOiBtb2NrQ2FsbGRhdGEgfSksIC9JbnZhbGlkIGNvbnRyYWN0IGFkZHJlc3MvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIGVtcHR5IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGJ1aWxkZXIuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6ICcweCcgfSksIC9JbnZhbGlkIGNhbGxkYXRhLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBub24taGV4IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGJ1aWxkZXIuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6ICdub3QtaGV4LWRhdGEnIH0pLCAvSW52YWxpZCBjYWxsZGF0YS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgY2FsbGRhdGEgbWlzc2luZyAweCBwcmVmaXgnLCAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gYnVpbGRlci5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogJ2E5MDU5Y2JiJyB9KSwgL0ludmFsaWQgY2FsbGRhdGEvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZm9yIG9kZC1sZW5ndGggaGV4IGNhbGxkYXRhJywgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGJ1aWxkZXIuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6ICcweGFiYycgfSksIC9JbnZhbGlkIGNhbGxkYXRhLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBpbnZhbGlkIHZhbHVlIHN0cmluZycsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEsIHZhbHVlOiAnMWUxOCcgfSksIC9JbnZhbGlkIHZhbHVlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBuZWdhdGl2ZSB2YWx1ZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBidWlsZGVyLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEsIHZhbHVlOiAnLTEnIH0pLCAvSW52YWxpZCB2YWx1ZS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyByYXctY2FsbC1vbmx5IHRyYW5zYWN0aW9uIChubyBvcGVyYXRpb25zKScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIobW9ja0NvaW5Db25maWcpO1xuICAgICAgYnVpbGRlclxuICAgICAgICAuYWRkUmF3Q2FsbCh7IHRvOiBtb2NrQ29udHJhY3QsIGRhdGE6IG1vY2tDYWxsZGF0YSB9KVxuICAgICAgICAubm9uY2UoMClcbiAgICAgICAgLmdhcygxMDAwMDBuKVxuICAgICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgICAubWF4UHJpb3JpdHlGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhQcmlvcml0eUZlZVBlckdhcyk7XG5cbiAgICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGFzc2VydC5vayh0eCBpbnN0YW5jZW9mIFRpcDIwVHJhbnNhY3Rpb24pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldE9wZXJhdGlvbnMoKS5sZW5ndGgsIDApO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4LmdldFJhd0NhbGxzKCkubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eC5nZXRPcGVyYXRpb25Db3VudCgpLCAxKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1JvdW5kLVRyaXA6IEJ1aWxkIC0+IFNlcmlhbGl6ZSAtPiBGcm9tIChyYXcgY2FsbCBkZXNlcmlhbGl6YXRpb24pJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcHJlc2VydmUgcmF3IGNhbGwgY2FsbGRhdGEgdGhyb3VnaCBhIHJvdW5kLXRyaXAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEgfSlcbiAgICAgICAgLm5vbmNlKDUpXG4gICAgICAgIC5nYXMoMTUwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSBhd2FpdCBvcmlnaW5hbFR4LnNlcmlhbGl6ZSgpO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRUeC5nZXRPcGVyYXRpb25zKCkubGVuZ3RoLCAwKTtcbiAgICAgIGNvbnN0IHJhd0NhbGxzID0gcmVzdG9yZWRUeC5nZXRSYXdDYWxscygpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmF3Q2FsbHNbMF0udG8udG9Mb3dlckNhc2UoKSwgbW9ja0NvbnRyYWN0LnRvTG93ZXJDYXNlKCkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzWzBdLmRhdGEudG9Mb3dlckNhc2UoKSwgbW9ja0NhbGxkYXRhLnRvTG93ZXJDYXNlKCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcmVzZXJ2ZSBjYWxsZGF0YSB0aHJvdWdoIGEgc2lnbmVkIHJvdW5kLXRyaXAnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEgfSlcbiAgICAgICAgLm5vbmNlKDcpXG4gICAgICAgIC5nYXMoMTIwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICB0eC5zZXRTaWduYXR1cmUoU0lHTkFUVVJFX1RFU1RfREFUQS52YWxpZFNpZ25hdHVyZSk7XG4gICAgICBjb25zdCBzaWduZWRIZXggPSBhd2FpdCB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNpZ25lZEhleCk7XG4gICAgICBjb25zdCByZXN0b3JlZFR4ID0gKGF3YWl0IGJ1aWxkZXIyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG5cbiAgICAgIGNvbnN0IHJhd0NhbGxzID0gcmVzdG9yZWRUeC5nZXRSYXdDYWxscygpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJhd0NhbGxzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmF3Q2FsbHNbMF0uZGF0YS50b0xvd2VyQ2FzZSgpLCBtb2NrQ2FsbGRhdGEudG9Mb3dlckNhc2UoKSk7XG4gICAgICBjb25zdCBzaWcgPSByZXN0b3JlZFR4LmdldFNpZ25hdHVyZSgpO1xuICAgICAgYXNzZXJ0Lm9rKHNpZyAhPT0gdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWchLnlQYXJpdHksIFNJR05BVFVSRV9URVNUX0RBVEEudmFsaWRTaWduYXR1cmUueVBhcml0eSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByZXNlcnZlIHJhdyBjYWxsIHR4IGlkIHRocm91Z2ggYSByb3VuZC10cmlwJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pXG4gICAgICAgIC5ub25jZSgzKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3Qgb3JpZ2luYWxUeCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBjb25zdCBzZXJpYWxpemVkID0gYXdhaXQgb3JpZ2luYWxUeC5zZXJpYWxpemUoKTtcbiAgICAgIGNvbnN0IG9yaWdpbmFsSWQgPSBvcmlnaW5hbFR4LmlkO1xuXG4gICAgICBjb25zdCBidWlsZGVyMiA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyMi5mcm9tKHNlcmlhbGl6ZWQpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUeCA9IChhd2FpdCBidWlsZGVyMi5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdG9yZWRUeC5pZCwgb3JpZ2luYWxJZCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSYXcgY2FsbCB0b0pzb24gYW5kIG91dHB1dHMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBleHBvc2UgcmF3IGNhbGwgY29udHJhY3QgYWRkcmVzcyBhcyBvdXRwdXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBidWlsZGVyID0gbmV3IFRpcDIwVHJhbnNhY3Rpb25CdWlsZGVyKG1vY2tDb2luQ29uZmlnKTtcbiAgICAgIGJ1aWxkZXJcbiAgICAgICAgLmFkZFJhd0NhbGwoeyB0bzogbW9ja0NvbnRyYWN0LCBkYXRhOiBtb2NrQ2FsbGRhdGEsIHZhbHVlOiAnMCcgfSlcbiAgICAgICAgLm5vbmNlKDIpXG4gICAgICAgIC5nYXMoMjAwMDAwbilcbiAgICAgICAgLm1heEZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heEZlZVBlckdhcylcbiAgICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuXG4gICAgICBjb25zdCB0eCA9IChhd2FpdCBidWlsZGVyLmJ1aWxkKCkpIGFzIFRpcDIwVHJhbnNhY3Rpb247XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHgub3V0cHV0cy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4Lm91dHB1dHNbMF0uYWRkcmVzcy50b0xvd2VyQ2FzZSgpLCBtb2NrQ29udHJhY3QudG9Mb3dlckNhc2UoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgcmF3Q2FsbHMgaW4gdG9Kc29uKCkgb3V0cHV0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYnVpbGRlciA9IG5ldyBUaXAyMFRyYW5zYWN0aW9uQnVpbGRlcihtb2NrQ29pbkNvbmZpZyk7XG4gICAgICBidWlsZGVyXG4gICAgICAgIC5hZGRSYXdDYWxsKHsgdG86IG1vY2tDb250cmFjdCwgZGF0YTogbW9ja0NhbGxkYXRhIH0pXG4gICAgICAgIC5ub25jZSgwKVxuICAgICAgICAuZ2FzKDEwMDAwMG4pXG4gICAgICAgIC5tYXhGZWVQZXJHYXMoVFhfUEFSQU1TLmRlZmF1bHRNYXhGZWVQZXJHYXMpXG4gICAgICAgIC5tYXhQcmlvcml0eUZlZVBlckdhcyhUWF9QQVJBTVMuZGVmYXVsdE1heFByaW9yaXR5RmVlUGVyR2FzKTtcblxuICAgICAgY29uc3QgdHggPSAoYXdhaXQgYnVpbGRlci5idWlsZCgpKSBhcyBUaXAyMFRyYW5zYWN0aW9uO1xuICAgICAgY29uc3QganNvbiA9IHR4LnRvSnNvbigpO1xuXG4gICAgICBhc3NlcnQub2soQXJyYXkuaXNBcnJheShqc29uLnJhd0NhbGxzKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5yYXdDYWxscy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb24ucmF3Q2FsbHNbMF0udG8sIG1vY2tDb250cmFjdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoanNvbi5yYXdDYWxsc1swXS5kYXRhLCBtb2NrQ2FsbGRhdGEpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnVGVtcG8gY29pbiAtIHZlcmlmeVRyYW5zYWN0aW9uIHdpdGggcmF3IGNhbGxzJywgKCkgPT4ge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGNvaW46IGFueTtcblxuICBjb25zdCBtb2NrQ29udHJhY3QgPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcygnMHhkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmJyk7XG4gIGNvbnN0IG1vY2tDYWxsZGF0YSA9XG4gICAgJzB4YTkwNTljYmIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA3NDJkMzVjYzY2MzRjMDUzMjkyNWEzYjg0NGJjNDU0ZTQ0MzhmNDRlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDk4OTY4MCc7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICdtb2NrJyB9KTtcbiAgICBiaXRnby5zYWZlUmVnaXN0ZXIoJ3R0ZW1wbycsIChiZzogQml0R29CYXNlKSA9PiB7XG4gICAgICBjb25zdCBtb2NrU3RhdGljc0NvaW4gPSB7XG4gICAgICAgIG5hbWU6ICd0dGVtcG8nLFxuICAgICAgICBmdWxsTmFtZTogJ1Rlc3RuZXQgVGVtcG8nLFxuICAgICAgICBuZXR3b3JrOiB7IHR5cGU6ICd0ZXN0bmV0JyB9LFxuICAgICAgICBmZWF0dXJlczogW10sXG4gICAgICB9IGFzIGFueTtcbiAgICAgIHJldHVybiBUdGVtcG8uY3JlYXRlSW5zdGFuY2UoYmcsIG1vY2tTdGF0aWNzQ29pbik7XG4gICAgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ3R0ZW1wbycpO1xuICB9KTtcblxuICBhc3luYyBmdW5jdGlvbiBidWlsZFJhd0NhbGxUeChjb250cmFjdDogc3RyaW5nLCBjYWxsZGF0YTogc3RyaW5nLCBub25jZSA9IDApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVGlwMjBUcmFuc2FjdGlvbkJ1aWxkZXIoY29pbnMuZ2V0KCd0dGVtcG8nKSk7XG4gICAgYnVpbGRlclxuICAgICAgLmFkZFJhd0NhbGwoeyB0bzogY29udHJhY3QsIGRhdGE6IGNhbGxkYXRhIH0pXG4gICAgICAubm9uY2Uobm9uY2UpXG4gICAgICAuZ2FzKDE1MDAwMG4pXG4gICAgICAubWF4RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4RmVlUGVyR2FzKVxuICAgICAgLm1heFByaW9yaXR5RmVlUGVyR2FzKFRYX1BBUkFNUy5kZWZhdWx0TWF4UHJpb3JpdHlGZWVQZXJHYXMpO1xuICAgIGNvbnN0IHR4ID0gKGF3YWl0IGJ1aWxkZXIuYnVpbGQoKSkgYXMgVGlwMjBUcmFuc2FjdGlvbjtcbiAgICByZXR1cm4gdHguc2VyaWFsaXplKCk7XG4gIH1cblxuICBpdCgnc2hvdWxkIHZlcmlmeSBhIHJhdyBjYWxsIHRyYW5zYWN0aW9uIHdoZW4gcmVjaXBpZW50IGRhdGEgbWF0Y2hlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkUmF3Q2FsbFR4KG1vY2tDb250cmFjdCwgbW9ja0NhbGxkYXRhKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgIHJlY2lwaWVudHM6IFt7IGFkZHJlc3M6IG1vY2tDb250cmFjdCwgYW1vdW50OiAnMCcsIGRhdGE6IG1vY2tDYWxsZGF0YSB9XSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdCwgdHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByYXcgY2FsbCBhZGRyZXNzIGRvZXMgbm90IG1hdGNoIHJlY2lwaWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkUmF3Q2FsbFR4KG1vY2tDb250cmFjdCwgbW9ja0NhbGxkYXRhKTtcbiAgICBjb25zdCB3cm9uZ0FkZHJlc3MgPSBldGhlcnMudXRpbHMuZ2V0QWRkcmVzcygnMHgxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExJyk7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0sXG4gICAgICAgICAgdHhQYXJhbXM6IHsgcmVjaXBpZW50czogW3sgYWRkcmVzczogd3JvbmdBZGRyZXNzLCBhbW91bnQ6ICcwJywgZGF0YTogbW9ja0NhbGxkYXRhIH1dIH0sXG4gICAgICAgIH0pLFxuICAgICAgL2FkZHJlc3MgbWlzbWF0Y2gvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIHJhdyBjYWxsIGNhbGxkYXRhIGRvZXMgbm90IG1hdGNoJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRSYXdDYWxsVHgobW9ja0NvbnRyYWN0LCBtb2NrQ2FsbGRhdGEpO1xuICAgIGNvbnN0IHdyb25nQ2FsbGRhdGEgPSAnMHhkZWFkYmVlZjAxMDIwMzA0JztcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbeyBhZGRyZXNzOiBtb2NrQ29udHJhY3QsIGFtb3VudDogJzAnLCBkYXRhOiB3cm9uZ0NhbGxkYXRhIH1dIH0sXG4gICAgICAgIH0pLFxuICAgICAgL2NhbGxkYXRhIG1pc21hdGNoL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByZWNpcGllbnQgY291bnQgZG9lcyBub3QgbWF0Y2ggY2FsbCBjb3VudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkUmF3Q2FsbFR4KG1vY2tDb250cmFjdCwgbW9ja0NhbGxkYXRhKTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSxcbiAgICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7IGFkZHJlc3M6IG1vY2tDb250cmFjdCwgYW1vdW50OiAnMCcsIGRhdGE6IG1vY2tDYWxsZGF0YSB9LFxuICAgICAgICAgICAgICB7IGFkZHJlc3M6IG1vY2tDb250cmFjdCwgYW1vdW50OiAnMCcsIGRhdGE6IG1vY2tDYWxsZGF0YSB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgIC9jYWxsXFwoc1xcKS9cbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHBhcnNlIGEgcmF3IGNhbGwgdHJhbnNhY3Rpb24gYW5kIGV4cG9zZSB0aGUgY29udHJhY3QgYXMgYW4gb3V0cHV0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGRSYXdDYWxsVHgobW9ja0NvbnRyYWN0LCBtb2NrQ2FsbGRhdGEpO1xuICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IGNvaW4ucGFyc2VUcmFuc2FjdGlvbih7IHR4SGV4IH0pO1xuICAgIGFzc2VydC5vayhBcnJheS5pc0FycmF5KHBhcnNlZC5vdXRwdXRzKSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5vdXRwdXRzWzBdLmFkZHJlc3MudG9Mb3dlckNhc2UoKSwgbW9ja0NvbnRyYWN0LnRvTG93ZXJDYXNlKCkpO1xuICB9KTtcbn0pO1xuIl19
|