@bitgo/sdk-coin-eth 25.10.1 → 25.11.1
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/erc20Token.js +3 -3
- package/dist/src/erc721Token.js +3 -3
- package/dist/src/erc7984Token.d.ts +16 -2
- package/dist/src/erc7984Token.d.ts.map +1 -1
- package/dist/src/erc7984Token.js +120 -1
- package/dist/src/eth.js +3 -3
- package/dist/test/unit/erc7984Token.d.ts +2 -0
- package/dist/test/unit/erc7984Token.d.ts.map +1 -0
- package/dist/test/unit/erc7984Token.js +403 -0
- package/dist/test/unit/eth.js +49 -1
- package/dist/test/unit/transaction.js +22 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,403 @@
|
|
|
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
|
+
/**
|
|
7
|
+
* Unit tests for Erc7984Token.
|
|
8
|
+
*
|
|
9
|
+
* Covers:
|
|
10
|
+
* - getTokenEnablementConfig
|
|
11
|
+
* - verifyTransaction (TSS and multisig paths)
|
|
12
|
+
* - decodeTokenAddressesFromDelegationCalldata (round-trip and forwarder-wrapped)
|
|
13
|
+
*/
|
|
14
|
+
const should_1 = __importDefault(require("should"));
|
|
15
|
+
const sdk_api_1 = require("@bitgo/sdk-api");
|
|
16
|
+
const sdk_test_1 = require("@bitgo/sdk-test");
|
|
17
|
+
const sdk_core_1 = require("@bitgo/sdk-core");
|
|
18
|
+
const abstract_eth_1 = require("@bitgo/abstract-eth");
|
|
19
|
+
const getBuilder_1 = require("./getBuilder");
|
|
20
|
+
const register_1 = require("../../src/register");
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Constants
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Hoodi ACL contract address (Networks.test.hoodi.zamaAclContractAddress)
|
|
25
|
+
const ZAMA_ACL_ADDRESS = '0x6d3faf6f86e1ff9f3b0831dda920aba1cbd5bd68';
|
|
26
|
+
const DELEGATE_ADDRESS = '0x1111111111111111111111111111111111111111';
|
|
27
|
+
// hteth:ctest1 token contract address (from statics/erc7984Tokens.ts)
|
|
28
|
+
const CTEST1_TOKEN_ADDRESS = '0x7b1d59bbcd291daa59cb6c8c5bc04de1afc4aba1';
|
|
29
|
+
// hteth:cusdt token contract address (from statics/erc7984Tokens.ts)
|
|
30
|
+
const CUSDT_TOKEN_ADDRESS = '0x2debbe0487ef921df4457f9e36ed05be2df1ac75';
|
|
31
|
+
const WRONG_TOKEN_ADDRESS = '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
|
|
32
|
+
const WRONG_ACL_ADDRESS = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
|
33
|
+
const FORWARDER_ADDRESS = '0x1234567890123456789012345678901234567890';
|
|
34
|
+
const EXPIRY = Math.floor(Date.now() / 1000) + 365 * 86400;
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Helpers
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/**
|
|
39
|
+
* Builds a root-wallet delegation tx hex (to = ACL, data = multicall).
|
|
40
|
+
*/
|
|
41
|
+
async function buildDelegationTxHex(aclAddress, tokenAddresses, value = '0') {
|
|
42
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
43
|
+
txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
|
|
44
|
+
txBuilder.counter(1);
|
|
45
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
46
|
+
txBuilder.contract(aclAddress);
|
|
47
|
+
const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, tokenAddresses, EXPIRY);
|
|
48
|
+
txBuilder.data(calldata);
|
|
49
|
+
if (value !== '0') {
|
|
50
|
+
txBuilder.value(value);
|
|
51
|
+
}
|
|
52
|
+
const tx = await txBuilder.build();
|
|
53
|
+
return tx.toBroadcastFormat();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Builds a forwarder delegation tx hex (to = forwarder, data = callFromParent(ACL, 0, multicall)).
|
|
57
|
+
* This mirrors what DecryptionDelegationBuilder.build() returns when forwarderAddress is set.
|
|
58
|
+
*/
|
|
59
|
+
async function buildForwarderDelegationTxHex(forwarderAddress, aclAddress, tokenAddresses) {
|
|
60
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
61
|
+
txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
|
|
62
|
+
txBuilder.counter(1);
|
|
63
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
64
|
+
txBuilder.contract(forwarderAddress);
|
|
65
|
+
const innerCalldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, tokenAddresses, EXPIRY);
|
|
66
|
+
const outerCalldata = (0, abstract_eth_1.wrapInCallFromParent)(aclAddress, innerCalldata);
|
|
67
|
+
txBuilder.data(outerCalldata);
|
|
68
|
+
const tx = await txBuilder.build();
|
|
69
|
+
return tx.toBroadcastFormat();
|
|
70
|
+
}
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Tests
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
describe('Erc7984Token', function () {
|
|
75
|
+
let bitgo;
|
|
76
|
+
let coin;
|
|
77
|
+
before(function () {
|
|
78
|
+
bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
|
|
79
|
+
bitgo.initializeTestVars();
|
|
80
|
+
(0, register_1.register)(bitgo);
|
|
81
|
+
coin = bitgo.coin('hteth:ctest1');
|
|
82
|
+
});
|
|
83
|
+
// -------------------------------------------------------------------------
|
|
84
|
+
describe('getTokenEnablementConfig', function () {
|
|
85
|
+
it('should return requiresTokenEnablement: true', function () {
|
|
86
|
+
const config = coin.getTokenEnablementConfig();
|
|
87
|
+
config.requiresTokenEnablement.should.equal(true);
|
|
88
|
+
});
|
|
89
|
+
it('should return supportsMultipleTokenEnablements: true', function () {
|
|
90
|
+
const config = coin.getTokenEnablementConfig();
|
|
91
|
+
config.supportsMultipleTokenEnablements.should.equal(true);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
// -------------------------------------------------------------------------
|
|
95
|
+
describe('verifyTransaction – non-enable-token', function () {
|
|
96
|
+
it('should fall through to parent when type is not enabletoken', async function () {
|
|
97
|
+
// The parent verifyTransaction requires recipients, wallet, etc. When we
|
|
98
|
+
// pass a params object with no type, it falls into the parent path and
|
|
99
|
+
// throws with the parent's "missing params" error — confirming the
|
|
100
|
+
// override only intercepts the enabletoken type.
|
|
101
|
+
await coin
|
|
102
|
+
.verifyTransaction({
|
|
103
|
+
txParams: { recipients: [] },
|
|
104
|
+
txPrebuild: {},
|
|
105
|
+
wallet: {},
|
|
106
|
+
})
|
|
107
|
+
.should.be.rejectedWith(/missing params/);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
// -------------------------------------------------------------------------
|
|
111
|
+
describe('verifyTransaction – TSS path', function () {
|
|
112
|
+
it('should verify a valid single-token delegation tx', async function () {
|
|
113
|
+
const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
|
|
114
|
+
const result = await coin.verifyTransaction({
|
|
115
|
+
txParams: {
|
|
116
|
+
type: 'enabletoken',
|
|
117
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
118
|
+
},
|
|
119
|
+
txPrebuild: { txHex },
|
|
120
|
+
wallet: {},
|
|
121
|
+
walletType: 'tss',
|
|
122
|
+
});
|
|
123
|
+
result.should.equal(true);
|
|
124
|
+
});
|
|
125
|
+
it('should verify a valid multi-token delegation tx', async function () {
|
|
126
|
+
const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS, CUSDT_TOKEN_ADDRESS]);
|
|
127
|
+
const result = await coin.verifyTransaction({
|
|
128
|
+
txParams: {
|
|
129
|
+
type: 'enabletoken',
|
|
130
|
+
enableTokens: [{ name: 'hteth:ctest1' }, { name: 'hteth:cusdt' }],
|
|
131
|
+
},
|
|
132
|
+
txPrebuild: { txHex },
|
|
133
|
+
wallet: {},
|
|
134
|
+
walletType: 'tss',
|
|
135
|
+
});
|
|
136
|
+
result.should.equal(true);
|
|
137
|
+
});
|
|
138
|
+
it('should throw when ACL address does not match', async function () {
|
|
139
|
+
const txHex = await buildDelegationTxHex(WRONG_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
|
|
140
|
+
await coin
|
|
141
|
+
.verifyTransaction({
|
|
142
|
+
txParams: {
|
|
143
|
+
type: 'enabletoken',
|
|
144
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
145
|
+
},
|
|
146
|
+
txPrebuild: { txHex },
|
|
147
|
+
wallet: {},
|
|
148
|
+
walletType: 'tss',
|
|
149
|
+
})
|
|
150
|
+
.should.be.rejectedWith(/does not match ACL contract/);
|
|
151
|
+
});
|
|
152
|
+
it('should throw when calldata contains wrong token address', async function () {
|
|
153
|
+
const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [WRONG_TOKEN_ADDRESS]);
|
|
154
|
+
await coin
|
|
155
|
+
.verifyTransaction({
|
|
156
|
+
txParams: {
|
|
157
|
+
type: 'enabletoken',
|
|
158
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
159
|
+
},
|
|
160
|
+
txPrebuild: { txHex },
|
|
161
|
+
wallet: {},
|
|
162
|
+
walletType: 'tss',
|
|
163
|
+
})
|
|
164
|
+
.should.be.rejectedWith(/not found in delegation calldata/);
|
|
165
|
+
});
|
|
166
|
+
it('should verify a valid forwarder delegation tx (callFromParent shape)', async function () {
|
|
167
|
+
const txHex = await buildForwarderDelegationTxHex(FORWARDER_ADDRESS, ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
|
|
168
|
+
const result = await coin.verifyTransaction({
|
|
169
|
+
txParams: {
|
|
170
|
+
type: 'enabletoken',
|
|
171
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
172
|
+
},
|
|
173
|
+
txPrebuild: { txHex },
|
|
174
|
+
wallet: {},
|
|
175
|
+
walletType: 'tss',
|
|
176
|
+
});
|
|
177
|
+
result.should.equal(true);
|
|
178
|
+
});
|
|
179
|
+
it('should verify a forwarder delegation tx with multiple tokens', async function () {
|
|
180
|
+
const txHex = await buildForwarderDelegationTxHex(FORWARDER_ADDRESS, ZAMA_ACL_ADDRESS, [
|
|
181
|
+
CTEST1_TOKEN_ADDRESS,
|
|
182
|
+
CUSDT_TOKEN_ADDRESS,
|
|
183
|
+
]);
|
|
184
|
+
const result = await coin.verifyTransaction({
|
|
185
|
+
txParams: {
|
|
186
|
+
type: 'enabletoken',
|
|
187
|
+
enableTokens: [{ name: 'hteth:ctest1' }, { name: 'hteth:cusdt' }],
|
|
188
|
+
},
|
|
189
|
+
txPrebuild: { txHex },
|
|
190
|
+
wallet: {},
|
|
191
|
+
walletType: 'tss',
|
|
192
|
+
});
|
|
193
|
+
result.should.equal(true);
|
|
194
|
+
});
|
|
195
|
+
it('should throw when forwarder calldata contains wrong token address', async function () {
|
|
196
|
+
const txHex = await buildForwarderDelegationTxHex(FORWARDER_ADDRESS, ZAMA_ACL_ADDRESS, [WRONG_TOKEN_ADDRESS]);
|
|
197
|
+
await coin
|
|
198
|
+
.verifyTransaction({
|
|
199
|
+
txParams: {
|
|
200
|
+
type: 'enabletoken',
|
|
201
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
202
|
+
},
|
|
203
|
+
txPrebuild: { txHex },
|
|
204
|
+
wallet: {},
|
|
205
|
+
walletType: 'tss',
|
|
206
|
+
})
|
|
207
|
+
.should.be.rejectedWith(/not found in delegation calldata/);
|
|
208
|
+
});
|
|
209
|
+
it('should throw when calldata has unrecognised method ID', async function () {
|
|
210
|
+
// Build a tx with arbitrary calldata that is neither multicall nor callFromParent
|
|
211
|
+
const txBuilder = (0, getBuilder_1.getBuilder)('hteth');
|
|
212
|
+
txBuilder.fee({ fee: '1000000000', gasLimit: '200000' });
|
|
213
|
+
txBuilder.counter(1);
|
|
214
|
+
txBuilder.type(sdk_core_1.TransactionType.ContractCall);
|
|
215
|
+
txBuilder.contract(ZAMA_ACL_ADDRESS);
|
|
216
|
+
txBuilder.data('0xdeadbeef');
|
|
217
|
+
const tx = await txBuilder.build();
|
|
218
|
+
const txHex = tx.toBroadcastFormat();
|
|
219
|
+
await coin
|
|
220
|
+
.verifyTransaction({
|
|
221
|
+
txParams: {
|
|
222
|
+
type: 'enabletoken',
|
|
223
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
224
|
+
},
|
|
225
|
+
txPrebuild: { txHex },
|
|
226
|
+
wallet: {},
|
|
227
|
+
walletType: 'tss',
|
|
228
|
+
})
|
|
229
|
+
.should.be.rejectedWith(/unrecognised calldata method ID/);
|
|
230
|
+
});
|
|
231
|
+
it('should throw when transaction value is not 0', async function () {
|
|
232
|
+
const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS], '1');
|
|
233
|
+
await coin
|
|
234
|
+
.verifyTransaction({
|
|
235
|
+
txParams: {
|
|
236
|
+
type: 'enabletoken',
|
|
237
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
238
|
+
},
|
|
239
|
+
txPrebuild: { txHex },
|
|
240
|
+
wallet: {},
|
|
241
|
+
walletType: 'tss',
|
|
242
|
+
})
|
|
243
|
+
.should.be.rejectedWith(/expected transaction value 0/);
|
|
244
|
+
});
|
|
245
|
+
it('should throw when enableTokens is empty', async function () {
|
|
246
|
+
const txHex = await buildDelegationTxHex(ZAMA_ACL_ADDRESS, [CTEST1_TOKEN_ADDRESS]);
|
|
247
|
+
await coin
|
|
248
|
+
.verifyTransaction({
|
|
249
|
+
txParams: {
|
|
250
|
+
type: 'enabletoken',
|
|
251
|
+
enableTokens: [],
|
|
252
|
+
},
|
|
253
|
+
txPrebuild: { txHex },
|
|
254
|
+
wallet: {},
|
|
255
|
+
walletType: 'tss',
|
|
256
|
+
})
|
|
257
|
+
.should.be.rejectedWith(/enableTokens must be non-empty/);
|
|
258
|
+
});
|
|
259
|
+
it('should throw when txHex is missing', async function () {
|
|
260
|
+
await coin
|
|
261
|
+
.verifyTransaction({
|
|
262
|
+
txParams: {
|
|
263
|
+
type: 'enabletoken',
|
|
264
|
+
enableTokens: [{ name: 'hteth:ctest1' }],
|
|
265
|
+
},
|
|
266
|
+
txPrebuild: {},
|
|
267
|
+
wallet: {},
|
|
268
|
+
walletType: 'tss',
|
|
269
|
+
})
|
|
270
|
+
.should.be.rejectedWith(/missing txHex/);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
// -------------------------------------------------------------------------
|
|
274
|
+
describe('verifyTransaction – multisig path', function () {
|
|
275
|
+
it('should verify valid buildParams recipients', async function () {
|
|
276
|
+
const result = await coin.verifyTransaction({
|
|
277
|
+
txParams: {
|
|
278
|
+
type: 'enabletoken',
|
|
279
|
+
recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
|
|
280
|
+
},
|
|
281
|
+
txPrebuild: {
|
|
282
|
+
buildParams: {
|
|
283
|
+
type: 'enabletoken',
|
|
284
|
+
recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
wallet: {},
|
|
288
|
+
walletType: 'onchain',
|
|
289
|
+
});
|
|
290
|
+
result.should.equal(true);
|
|
291
|
+
});
|
|
292
|
+
it('should verify multiple token recipients', async function () {
|
|
293
|
+
const result = await coin.verifyTransaction({
|
|
294
|
+
txParams: {
|
|
295
|
+
type: 'enabletoken',
|
|
296
|
+
recipients: [
|
|
297
|
+
{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' },
|
|
298
|
+
{ tokenName: 'hteth:cusdt', address: '0xabc', amount: '0' },
|
|
299
|
+
],
|
|
300
|
+
},
|
|
301
|
+
txPrebuild: {
|
|
302
|
+
buildParams: {
|
|
303
|
+
type: 'enabletoken',
|
|
304
|
+
recipients: [
|
|
305
|
+
{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' },
|
|
306
|
+
{ tokenName: 'hteth:cusdt', address: '0xabc', amount: '0' },
|
|
307
|
+
],
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
wallet: {},
|
|
311
|
+
walletType: 'onchain',
|
|
312
|
+
});
|
|
313
|
+
result.should.equal(true);
|
|
314
|
+
});
|
|
315
|
+
it('should throw when buildParams recipients have wrong tokenName', async function () {
|
|
316
|
+
await coin
|
|
317
|
+
.verifyTransaction({
|
|
318
|
+
txParams: {
|
|
319
|
+
type: 'enabletoken',
|
|
320
|
+
recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
|
|
321
|
+
},
|
|
322
|
+
txPrebuild: {
|
|
323
|
+
buildParams: {
|
|
324
|
+
type: 'enabletoken',
|
|
325
|
+
recipients: [{ tokenName: 'hteth:wrongtoken', address: '0xabc', amount: '0' }],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
wallet: {},
|
|
329
|
+
walletType: 'onchain',
|
|
330
|
+
})
|
|
331
|
+
.should.be.rejectedWith(/not found in buildParams recipients/);
|
|
332
|
+
});
|
|
333
|
+
it('should throw when amount is not 0', async function () {
|
|
334
|
+
await coin
|
|
335
|
+
.verifyTransaction({
|
|
336
|
+
txParams: {
|
|
337
|
+
type: 'enabletoken',
|
|
338
|
+
recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '0' }],
|
|
339
|
+
},
|
|
340
|
+
txPrebuild: {
|
|
341
|
+
buildParams: {
|
|
342
|
+
type: 'enabletoken',
|
|
343
|
+
recipients: [{ tokenName: 'hteth:ctest1', address: '0xabc', amount: '100' }],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
wallet: {},
|
|
347
|
+
walletType: 'onchain',
|
|
348
|
+
})
|
|
349
|
+
.should.be.rejectedWith(/expected amount 0/);
|
|
350
|
+
});
|
|
351
|
+
it('should throw when recipients is missing', async function () {
|
|
352
|
+
await coin
|
|
353
|
+
.verifyTransaction({
|
|
354
|
+
txParams: {
|
|
355
|
+
type: 'enabletoken',
|
|
356
|
+
},
|
|
357
|
+
txPrebuild: {
|
|
358
|
+
buildParams: {},
|
|
359
|
+
},
|
|
360
|
+
wallet: {},
|
|
361
|
+
walletType: 'onchain',
|
|
362
|
+
})
|
|
363
|
+
.should.be.rejectedWith(/missing buildParams.recipients/);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
// decodeTokenAddressesFromDelegationCalldata tests
|
|
369
|
+
// ---------------------------------------------------------------------------
|
|
370
|
+
describe('decodeTokenAddressesFromDelegationCalldata', function () {
|
|
371
|
+
it('should decode a single-token multicall calldata', function () {
|
|
372
|
+
const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS], EXPIRY);
|
|
373
|
+
const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(calldata);
|
|
374
|
+
addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase()]);
|
|
375
|
+
});
|
|
376
|
+
it('should decode a multi-token multicall calldata', function () {
|
|
377
|
+
const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS, CUSDT_TOKEN_ADDRESS], EXPIRY);
|
|
378
|
+
const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(calldata);
|
|
379
|
+
addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase(), CUSDT_TOKEN_ADDRESS.toLowerCase()]);
|
|
380
|
+
});
|
|
381
|
+
it('should return addresses in lowercase', function () {
|
|
382
|
+
const mixedCase = '0x7B1D59bbCD291daA59cB6C8C5bc04De1AFC4aBA1';
|
|
383
|
+
const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [mixedCase], EXPIRY);
|
|
384
|
+
const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(calldata);
|
|
385
|
+
addresses[0].should.equal(mixedCase.toLowerCase());
|
|
386
|
+
});
|
|
387
|
+
it('should handle callFromParent-wrapped multicall calldata', function () {
|
|
388
|
+
const inner = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS, CUSDT_TOKEN_ADDRESS], EXPIRY);
|
|
389
|
+
const wrapped = (0, abstract_eth_1.wrapInCallFromParent)(ZAMA_ACL_ADDRESS, inner);
|
|
390
|
+
const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(wrapped);
|
|
391
|
+
addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase(), CUSDT_TOKEN_ADDRESS.toLowerCase()]);
|
|
392
|
+
});
|
|
393
|
+
it('should work with calldata missing 0x prefix', function () {
|
|
394
|
+
const calldata = (0, abstract_eth_1.buildMulticallDelegationCalldata)(DELEGATE_ADDRESS, [CTEST1_TOKEN_ADDRESS], EXPIRY);
|
|
395
|
+
const noPrefix = calldata.slice(2); // strip 0x
|
|
396
|
+
const addresses = (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)(noPrefix);
|
|
397
|
+
addresses.should.deepEqual([CTEST1_TOKEN_ADDRESS.toLowerCase()]);
|
|
398
|
+
});
|
|
399
|
+
it('should throw for unrecognised calldata', function () {
|
|
400
|
+
should_1.default.throws(() => (0, abstract_eth_1.decodeTokenAddressesFromDelegationCalldata)('0xdeadbeef00000000'), /Not a valid delegation calldata/);
|
|
401
|
+
});
|
|
402
|
+
});
|
|
403
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJjNzk4NFRva2VuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2VyYzc5ODRUb2tlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBOzs7Ozs7O0dBT0c7QUFDSCxvREFBNEI7QUFDNUIsNENBQTBDO0FBQzFDLDhDQUEwRDtBQUMxRCw4Q0FBa0Q7QUFDbEQsc0RBSTZCO0FBRzdCLDZDQUEwQztBQUMxQyxpREFBOEM7QUFFOUMsOEVBQThFO0FBQzlFLFlBQVk7QUFDWiw4RUFBOEU7QUFFOUUsMEVBQTBFO0FBQzFFLE1BQU0sZ0JBQWdCLEdBQUcsNENBQTRDLENBQUM7QUFDdEUsTUFBTSxnQkFBZ0IsR0FBRyw0Q0FBNEMsQ0FBQztBQUV0RSxzRUFBc0U7QUFDdEUsTUFBTSxvQkFBb0IsR0FBRyw0Q0FBNEMsQ0FBQztBQUMxRSxxRUFBcUU7QUFDckUsTUFBTSxtQkFBbUIsR0FBRyw0Q0FBNEMsQ0FBQztBQUV6RSxNQUFNLG1CQUFtQixHQUFHLDRDQUE0QyxDQUFDO0FBQ3pFLE1BQU0saUJBQWlCLEdBQUcsNENBQTRDLENBQUM7QUFDdkUsTUFBTSxpQkFBaUIsR0FBRyw0Q0FBNEMsQ0FBQztBQUV2RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDO0FBRTNELDhFQUE4RTtBQUM5RSxVQUFVO0FBQ1YsOEVBQThFO0FBRTlFOztHQUVHO0FBQ0gsS0FBSyxVQUFVLG9CQUFvQixDQUFDLFVBQWtCLEVBQUUsY0FBd0IsRUFBRSxLQUFLLEdBQUcsR0FBRztJQUMzRixNQUFNLFNBQVMsR0FBRyxJQUFBLHVCQUFVLEVBQUMsT0FBTyxDQUF1QixDQUFDO0lBQzVELFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsQ0FBQyxD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QUFDLENBQUMsQ0FBQztJQUN0RyxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw2Q0FBNkMsRUFBRTtRQUNoRCxNQUFNLFFBQVEsR0FBRyxJQUFBLCtDQUFnQyxFQUFDLGdCQUFnQixFQUFFLENBQUMsb0JBQW9CLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNwRyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVztRQUMvQyxNQUFNLFNBQVMsR0FBRyxJQUFBLHlEQUEwQyxFQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZFLFNBQVMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsb0JBQW9CLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ25FLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHdDQUF3QyxFQUFFO1FBQzNDLGdCQUFNLENBQUMsTUFBTSxDQUNYLEdBQUcsRUFBRSxDQUFDLElBQUEseURBQTBDLEVBQUMsb0JBQW9CLENBQUMsRUFDdEUsaUNBQWlDLENBQ2xDLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBVbml0IHRlc3RzIGZvciBFcmM3OTg0VG9rZW4uXG4gKlxuICogQ292ZXJzOlxuICogICAtIGdldFRva2VuRW5hYmxlbWVudENvbmZpZ1xuICogICAtIHZlcmlmeVRyYW5zYWN0aW9uIChUU1MgYW5kIG11bHRpc2lnIHBhdGhzKVxuICogICAtIGRlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YSAocm91bmQtdHJpcCBhbmQgZm9yd2FyZGVyLXdyYXBwZWQpXG4gKi9cbmltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCB7IEJpdEdvQVBJIH0gZnJvbSAnQGJpdGdvL3Nkay1hcGknO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25UeXBlIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7XG4gIGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhLFxuICB3cmFwSW5DYWxsRnJvbVBhcmVudCxcbiAgZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhLFxufSBmcm9tICdAYml0Z28vYWJzdHJhY3QtZXRoJztcbmltcG9ydCB7IEVyYzc5ODRUb2tlbiB9IGZyb20gJy4uLy4uL3NyYy9lcmM3OTg0VG9rZW4nO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25CdWlsZGVyIH0gZnJvbSAnLi4vLi4vc3JjL2xpYic7XG5pbXBvcnQgeyBnZXRCdWlsZGVyIH0gZnJvbSAnLi9nZXRCdWlsZGVyJztcbmltcG9ydCB7IHJlZ2lzdGVyIH0gZnJvbSAnLi4vLi4vc3JjL3JlZ2lzdGVyJztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDb25zdGFudHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vLyBIb29kaSBBQ0wgY29udHJhY3QgYWRkcmVzcyAoTmV0d29ya3MudGVzdC5ob29kaS56YW1hQWNsQ29udHJhY3RBZGRyZXNzKVxuY29uc3QgWkFNQV9BQ0xfQUREUkVTUyA9ICcweDZkM2ZhZjZmODZlMWZmOWYzYjA4MzFkZGE5MjBhYmExY2JkNWJkNjgnO1xuY29uc3QgREVMRUdBVEVfQUREUkVTUyA9ICcweDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEnO1xuXG4vLyBodGV0aDpjdGVzdDEgdG9rZW4gY29udHJhY3QgYWRkcmVzcyAoZnJvbSBzdGF0aWNzL2VyYzc5ODRUb2tlbnMudHMpXG5jb25zdCBDVEVTVDFfVE9LRU5fQUREUkVTUyA9ICcweDdiMWQ1OWJiY2QyOTFkYWE1OWNiNmM4YzViYzA0ZGUxYWZjNGFiYTEnO1xuLy8gaHRldGg6Y3VzZHQgdG9rZW4gY29udHJhY3QgYWRkcmVzcyAoZnJvbSBzdGF0aWNzL2VyYzc5ODRUb2tlbnMudHMpXG5jb25zdCBDVVNEVF9UT0tFTl9BRERSRVNTID0gJzB4MmRlYmJlMDQ4N2VmOTIxZGY0NDU3ZjllMzZlZDA1YmUyZGYxYWM3NSc7XG5cbmNvbnN0IFdST05HX1RPS0VOX0FERFJFU1MgPSAnMHhkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmJztcbmNvbnN0IFdST05HX0FDTF9BRERSRVNTID0gJzB4YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSc7XG5jb25zdCBGT1JXQVJERVJfQUREUkVTUyA9ICcweDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAnO1xuXG5jb25zdCBFWFBJUlkgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKSArIDM2NSAqIDg2NDAwO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIEhlbHBlcnNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEJ1aWxkcyBhIHJvb3Qtd2FsbGV0IGRlbGVnYXRpb24gdHggaGV4ICh0byA9IEFDTCwgZGF0YSA9IG11bHRpY2FsbCkuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGJ1aWxkRGVsZWdhdGlvblR4SGV4KGFjbEFkZHJlc3M6IHN0cmluZywgdG9rZW5BZGRyZXNzZXM6IHN0cmluZ1tdLCB2YWx1ZSA9ICcwJyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2h0ZXRoJykgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMjAwMDAwJyB9KTtcbiAgdHhCdWlsZGVyLmNvdW50ZXIoMSk7XG4gIHR4QnVpbGRlci50eXBlKFRyYW5zYWN0aW9uVHlwZS5Db250cmFjdENhbGwpO1xuICB0eEJ1aWxkZXIuY29udHJhY3QoYWNsQWRkcmVzcyk7XG4gIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgdG9rZW5BZGRyZXNzZXMsIEVYUElSWSk7XG4gIHR4QnVpbGRlci5kYXRhKGNhbGxkYXRhKTtcbiAgaWYgKHZhbHVlICE9PSAnMCcpIHtcbiAgICB0eEJ1aWxkZXIudmFsdWUodmFsdWUpO1xuICB9XG4gIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG4gIHJldHVybiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBhIGZvcndhcmRlciBkZWxlZ2F0aW9uIHR4IGhleCAodG8gPSBmb3J3YXJkZXIsIGRhdGEgPSBjYWxsRnJvbVBhcmVudChBQ0wsIDAsIG11bHRpY2FsbCkpLlxuICogVGhpcyBtaXJyb3JzIHdoYXQgRGVjcnlwdGlvbkRlbGVnYXRpb25CdWlsZGVyLmJ1aWxkKCkgcmV0dXJucyB3aGVuIGZvcndhcmRlckFkZHJlc3MgaXMgc2V0LlxuICovXG5hc3luYyBmdW5jdGlvbiBidWlsZEZvcndhcmRlckRlbGVnYXRpb25UeEhleChcbiAgZm9yd2FyZGVyQWRkcmVzczogc3RyaW5nLFxuICBhY2xBZGRyZXNzOiBzdHJpbmcsXG4gIHRva2VuQWRkcmVzc2VzOiBzdHJpbmdbXVxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gIHR4QnVpbGRlci5mZWUoeyBmZWU6ICcxMDAwMDAwMDAwJywgZ2FzTGltaXQ6ICcyMDAwMDAnIH0pO1xuICB0eEJ1aWxkZXIuY291bnRlcigxKTtcbiAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gIHR4QnVpbGRlci5jb250cmFjdChmb3J3YXJkZXJBZGRyZXNzKTtcbiAgY29uc3QgaW5uZXJDYWxsZGF0YSA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKERFTEVHQVRFX0FERFJFU1MsIHRva2VuQWRkcmVzc2VzLCBFWFBJUlkpO1xuICBjb25zdCBvdXRlckNhbGxkYXRhID0gd3JhcEluQ2FsbEZyb21QYXJlbnQoYWNsQWRkcmVzcywgaW5uZXJDYWxsZGF0YSk7XG4gIHR4QnVpbGRlci5kYXRhKG91dGVyQ2FsbGRhdGEpO1xuICBjb25zdCB0eCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICByZXR1cm4gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBUZXN0c1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmRlc2NyaWJlKCdFcmM3OTg0VG9rZW4nLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgY29pbjogRXJjNzk4NFRva2VuO1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgcmVnaXN0ZXIoYml0Z28pO1xuICAgIGNvaW4gPSBiaXRnby5jb2luKCdodGV0aDpjdGVzdDEnKSBhcyBFcmM3OTg0VG9rZW47XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ2dldFRva2VuRW5hYmxlbWVudENvbmZpZycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiByZXF1aXJlc1Rva2VuRW5hYmxlbWVudDogdHJ1ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbmZpZyA9IGNvaW4uZ2V0VG9rZW5FbmFibGVtZW50Q29uZmlnKCk7XG4gICAgICBjb25maWcucmVxdWlyZXNUb2tlbkVuYWJsZW1lbnQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gc3VwcG9ydHNNdWx0aXBsZVRva2VuRW5hYmxlbWVudHM6IHRydWUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb25maWcgPSBjb2luLmdldFRva2VuRW5hYmxlbWVudENvbmZpZygpO1xuICAgICAgY29uZmlnLnN1cHBvcnRzTXVsdGlwbGVUb2tlbkVuYWJsZW1lbnRzLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24g4oCTIG5vbi1lbmFibGUtdG9rZW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBmYWxsIHRocm91Z2ggdG8gcGFyZW50IHdoZW4gdHlwZSBpcyBub3QgZW5hYmxldG9rZW4nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUaGUgcGFyZW50IHZlcmlmeVRyYW5zYWN0aW9uIHJlcXVpcmVzIHJlY2lwaWVudHMsIHdhbGxldCwgZXRjLiBXaGVuIHdlXG4gICAgICAvLyBwYXNzIGEgcGFyYW1zIG9iamVjdCB3aXRoIG5vIHR5cGUsIGl0IGZhbGxzIGludG8gdGhlIHBhcmVudCBwYXRoIGFuZFxuICAgICAgLy8gdGhyb3dzIHdpdGggdGhlIHBhcmVudCdzIFwibWlzc2luZyBwYXJhbXNcIiBlcnJvciDigJQgY29uZmlybWluZyB0aGVcbiAgICAgIC8vIG92ZXJyaWRlIG9ubHkgaW50ZXJjZXB0cyB0aGUgZW5hYmxldG9rZW4gdHlwZS5cbiAgICAgIGF3YWl0IGNvaW5cbiAgICAgICAgLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFBhcmFtczogeyByZWNpcGllbnRzOiBbXSB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL21pc3NpbmcgcGFyYW1zLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgZGVzY3JpYmUoJ3ZlcmlmeVRyYW5zYWN0aW9uIOKAkyBUU1MgcGF0aCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHZlcmlmeSBhIHZhbGlkIHNpbmdsZS10b2tlbiBkZWxlZ2F0aW9uIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERlbGVnYXRpb25UeEhleChaQU1BX0FDTF9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1NdKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgfSxcbiAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgIHdhbGxldFR5cGU6ICd0c3MnLFxuICAgICAgfSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBtdWx0aS10b2tlbiBkZWxlZ2F0aW9uIHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERlbGVnYXRpb25UeEhleChaQU1BX0FDTF9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1MsIENVU0RUX1RPS0VOX0FERFJFU1NdKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9LCB7IG5hbWU6ICdodGV0aDpjdXNkdCcgfV0sXG4gICAgICAgIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBBQ0wgYWRkcmVzcyBkb2VzIG5vdCBtYXRjaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4SGV4ID0gYXdhaXQgYnVpbGREZWxlZ2F0aW9uVHhIZXgoV1JPTkdfQUNMX0FERFJFU1MsIFtDVEVTVDFfVE9LRU5fQUREUkVTU10pO1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9kb2VzIG5vdCBtYXRjaCBBQ0wgY29udHJhY3QvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBjYWxsZGF0YSBjb250YWlucyB3cm9uZyB0b2tlbiBhZGRyZXNzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZERlbGVnYXRpb25UeEhleChaQU1BX0FDTF9BRERSRVNTLCBbV1JPTkdfVE9LRU5fQUREUkVTU10pO1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9ub3QgZm91bmQgaW4gZGVsZWdhdGlvbiBjYWxsZGF0YS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgYSB2YWxpZCBmb3J3YXJkZXIgZGVsZWdhdGlvbiB0eCAoY2FsbEZyb21QYXJlbnQgc2hhcGUpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHhIZXggPSBhd2FpdCBidWlsZEZvcndhcmRlckRlbGVnYXRpb25UeEhleChGT1JXQVJERVJfQUREUkVTUywgWkFNQV9BQ0xfQUREUkVTUywgW0NURVNUMV9UT0tFTl9BRERSRVNTXSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfV0sXG4gICAgICAgIH0sXG4gICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IGEgZm9yd2FyZGVyIGRlbGVnYXRpb24gdHggd2l0aCBtdWx0aXBsZSB0b2tlbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRm9yd2FyZGVyRGVsZWdhdGlvblR4SGV4KEZPUldBUkRFUl9BRERSRVNTLCBaQU1BX0FDTF9BRERSRVNTLCBbXG4gICAgICAgIENURVNUMV9UT0tFTl9BRERSRVNTLFxuICAgICAgICBDVVNEVF9UT0tFTl9BRERSRVNTLFxuICAgICAgXSk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIGVuYWJsZVRva2VuczogW3sgbmFtZTogJ2h0ZXRoOmN0ZXN0MScgfSwgeyBuYW1lOiAnaHRldGg6Y3VzZHQnIH1dLFxuICAgICAgICB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICB9KTtcbiAgICAgIHJlc3VsdC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gZm9yd2FyZGVyIGNhbGxkYXRhIGNvbnRhaW5zIHdyb25nIHRva2VuIGFkZHJlc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRm9yd2FyZGVyRGVsZWdhdGlvblR4SGV4KEZPUldBUkRFUl9BRERSRVNTLCBaQU1BX0FDTF9BRERSRVNTLCBbV1JPTkdfVE9LRU5fQUREUkVTU10pO1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9ub3QgZm91bmQgaW4gZGVsZWdhdGlvbiBjYWxsZGF0YS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGNhbGxkYXRhIGhhcyB1bnJlY29nbmlzZWQgbWV0aG9kIElEJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQnVpbGQgYSB0eCB3aXRoIGFyYml0cmFyeSBjYWxsZGF0YSB0aGF0IGlzIG5laXRoZXIgbXVsdGljYWxsIG5vciBjYWxsRnJvbVBhcmVudFxuICAgICAgY29uc3QgdHhCdWlsZGVyID0gZ2V0QnVpbGRlcignaHRldGgnKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgICB0eEJ1aWxkZXIuZmVlKHsgZmVlOiAnMTAwMDAwMDAwMCcsIGdhc0xpbWl0OiAnMjAwMDAwJyB9KTtcbiAgICAgIHR4QnVpbGRlci5jb3VudGVyKDEpO1xuICAgICAgdHhCdWlsZGVyLnR5cGUoVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0Q2FsbCk7XG4gICAgICB0eEJ1aWxkZXIuY29udHJhY3QoWkFNQV9BQ0xfQUREUkVTUyk7XG4gICAgICB0eEJ1aWxkZXIuZGF0YSgnMHhkZWFkYmVlZicpO1xuICAgICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IHR4SGV4ID0gdHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC91bnJlY29nbmlzZWQgY2FsbGRhdGEgbWV0aG9kIElELyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gdHJhbnNhY3Rpb24gdmFsdWUgaXMgbm90IDAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRGVsZWdhdGlvblR4SGV4KFpBTUFfQUNMX0FERFJFU1MsIFtDVEVTVDFfVE9LRU5fQUREUkVTU10sICcxJyk7XG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICBlbmFibGVUb2tlbnM6IFt7IG5hbWU6ICdodGV0aDpjdGVzdDEnIH1dLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleCB9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2V4cGVjdGVkIHRyYW5zYWN0aW9uIHZhbHVlIDAvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiBlbmFibGVUb2tlbnMgaXMgZW1wdHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEhleCA9IGF3YWl0IGJ1aWxkRGVsZWdhdGlvblR4SGV4KFpBTUFfQUNMX0FERFJFU1MsIFtDVEVTVDFfVE9LRU5fQUREUkVTU10pO1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHsgdHhIZXggfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ3RzcycsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9lbmFibGVUb2tlbnMgbXVzdCBiZSBub24tZW1wdHkvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiB0eEhleCBpcyBtaXNzaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgZW5hYmxlVG9rZW5zOiBbeyBuYW1lOiAnaHRldGg6Y3Rlc3QxJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHR4UHJlYnVpbGQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgICB3YWxsZXRUeXBlOiAndHNzJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL21pc3NpbmcgdHhIZXgvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICBkZXNjcmliZSgndmVyaWZ5VHJhbnNhY3Rpb24g4oCTIG11bHRpc2lnIHBhdGgnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCB2ZXJpZnkgdmFsaWQgYnVpbGRQYXJhbXMgcmVjaXBpZW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0eFBhcmFtczoge1xuICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgcmVjaXBpZW50czogW3sgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfV0gYXMgYW55LFxuICAgICAgICB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbeyB0b2tlbk5hbWU6ICdodGV0aDpjdGVzdDEnLCBhZGRyZXNzOiAnMHhhYmMnLCBhbW91bnQ6ICcwJyB9XSxcbiAgICAgICAgICB9LFxuICAgICAgICB9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgIHdhbGxldFR5cGU6ICdvbmNoYWluJyxcbiAgICAgIH0pO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdmVyaWZ5IG11bHRpcGxlIHRva2VuIHJlY2lwaWVudHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb2luLnZlcmlmeVRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICAgIHsgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfSxcbiAgICAgICAgICAgIHsgdG9rZW5OYW1lOiAnaHRldGg6Y3VzZHQnLCBhZGRyZXNzOiAnMHhhYmMnLCBhbW91bnQ6ICcwJyB9LFxuICAgICAgICAgIF0gYXMgYW55LFxuICAgICAgICB9LFxuICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHsgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfSxcbiAgICAgICAgICAgICAgeyB0b2tlbk5hbWU6ICdodGV0aDpjdXNkdCcsIGFkZHJlc3M6ICcweGFiYycsIGFtb3VudDogJzAnIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0gYXMgYW55LFxuICAgICAgICB3YWxsZXQ6IHt9IGFzIGFueSxcbiAgICAgICAgd2FsbGV0VHlwZTogJ29uY2hhaW4nLFxuICAgICAgfSk7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGJ1aWxkUGFyYW1zIHJlY2lwaWVudHMgaGF2ZSB3cm9uZyB0b2tlbk5hbWUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbeyB0b2tlbk5hbWU6ICdodGV0aDpjdGVzdDEnLCBhZGRyZXNzOiAnMHhhYmMnLCBhbW91bnQ6ICcwJyB9XSBhcyBhbnksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICBidWlsZFBhcmFtczoge1xuICAgICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgICByZWNpcGllbnRzOiBbeyB0b2tlbk5hbWU6ICdodGV0aDp3cm9uZ3Rva2VuJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfV0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0gYXMgYW55LFxuICAgICAgICAgIHdhbGxldDoge30gYXMgYW55LFxuICAgICAgICAgIHdhbGxldFR5cGU6ICdvbmNoYWluJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL25vdCBmb3VuZCBpbiBidWlsZFBhcmFtcyByZWNpcGllbnRzLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IHdoZW4gYW1vdW50IGlzIG5vdCAwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgY29pblxuICAgICAgICAudmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHR4UGFyYW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnZW5hYmxldG9rZW4nLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW3sgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMCcgfV0gYXMgYW55LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgICAgYnVpbGRQYXJhbXM6IHtcbiAgICAgICAgICAgICAgdHlwZTogJ2VuYWJsZXRva2VuJyxcbiAgICAgICAgICAgICAgcmVjaXBpZW50czogW3sgdG9rZW5OYW1lOiAnaHRldGg6Y3Rlc3QxJywgYWRkcmVzczogJzB4YWJjJywgYW1vdW50OiAnMTAwJyB9XSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ29uY2hhaW4nLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvZXhwZWN0ZWQgYW1vdW50IDAvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByZWNpcGllbnRzIGlzIG1pc3NpbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBjb2luXG4gICAgICAgIC52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgICAgIHR5cGU6ICdlbmFibGV0b2tlbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7XG4gICAgICAgICAgICBidWlsZFBhcmFtczoge30sXG4gICAgICAgICAgfSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0OiB7fSBhcyBhbnksXG4gICAgICAgICAgd2FsbGV0VHlwZTogJ29uY2hhaW4nLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbWlzc2luZyBidWlsZFBhcmFtcy5yZWNpcGllbnRzLyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhIHRlc3RzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZGVzY3JpYmUoJ2RlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgaXQoJ3Nob3VsZCBkZWNvZGUgYSBzaW5nbGUtdG9rZW4gbXVsdGljYWxsIGNhbGxkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoREVMRUdBVEVfQUREUkVTUywgW0NURVNUMV9UT0tFTl9BRERSRVNTXSwgRVhQSVJZKTtcbiAgICBjb25zdCBhZGRyZXNzZXMgPSBkZWNvZGVUb2tlbkFkZHJlc3Nlc0Zyb21EZWxlZ2F0aW9uQ2FsbGRhdGEoY2FsbGRhdGEpO1xuICAgIGFkZHJlc3Nlcy5zaG91bGQuZGVlcEVxdWFsKFtDVEVTVDFfVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpXSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgZGVjb2RlIGEgbXVsdGktdG9rZW4gbXVsdGljYWxsIGNhbGxkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGNhbGxkYXRhID0gYnVpbGRNdWx0aWNhbGxEZWxlZ2F0aW9uQ2FsbGRhdGEoXG4gICAgICBERUxFR0FURV9BRERSRVNTLFxuICAgICAgW0NURVNUMV9UT0tFTl9BRERSRVNTLCBDVVNEVF9UT0tFTl9BRERSRVNTXSxcbiAgICAgIEVYUElSWVxuICAgICk7XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhKGNhbGxkYXRhKTtcbiAgICBhZGRyZXNzZXMuc2hvdWxkLmRlZXBFcXVhbChbQ1RFU1QxX1RPS0VOX0FERFJFU1MudG9Mb3dlckNhc2UoKSwgQ1VTRFRfVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpXSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGFkZHJlc3NlcyBpbiBsb3dlcmNhc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgbWl4ZWRDYXNlID0gJzB4N0IxRDU5YmJDRDI5MWRhQTU5Y0I2QzhDNWJjMDREZTFBRkM0YUJBMSc7XG4gICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbbWl4ZWRDYXNlXSwgRVhQSVJZKTtcbiAgICBjb25zdCBhZGRyZXNzZXMgPSBkZWNvZGVUb2tlbkFkZHJlc3Nlc0Zyb21EZWxlZ2F0aW9uQ2FsbGRhdGEoY2FsbGRhdGEpO1xuICAgIGFkZHJlc3Nlc1swXS5zaG91bGQuZXF1YWwobWl4ZWRDYXNlLnRvTG93ZXJDYXNlKCkpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGhhbmRsZSBjYWxsRnJvbVBhcmVudC13cmFwcGVkIG11bHRpY2FsbCBjYWxsZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBpbm5lciA9IGJ1aWxkTXVsdGljYWxsRGVsZWdhdGlvbkNhbGxkYXRhKFxuICAgICAgREVMRUdBVEVfQUREUkVTUyxcbiAgICAgIFtDVEVTVDFfVE9LRU5fQUREUkVTUywgQ1VTRFRfVE9LRU5fQUREUkVTU10sXG4gICAgICBFWFBJUllcbiAgICApO1xuICAgIGNvbnN0IHdyYXBwZWQgPSB3cmFwSW5DYWxsRnJvbVBhcmVudChaQU1BX0FDTF9BRERSRVNTLCBpbm5lcik7XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhKHdyYXBwZWQpO1xuICAgIGFkZHJlc3Nlcy5zaG91bGQuZGVlcEVxdWFsKFtDVEVTVDFfVE9LRU5fQUREUkVTUy50b0xvd2VyQ2FzZSgpLCBDVVNEVF9UT0tFTl9BRERSRVNTLnRvTG93ZXJDYXNlKCldKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB3b3JrIHdpdGggY2FsbGRhdGEgbWlzc2luZyAweCBwcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgY2FsbGRhdGEgPSBidWlsZE11bHRpY2FsbERlbGVnYXRpb25DYWxsZGF0YShERUxFR0FURV9BRERSRVNTLCBbQ1RFU1QxX1RPS0VOX0FERFJFU1NdLCBFWFBJUlkpO1xuICAgIGNvbnN0IG5vUHJlZml4ID0gY2FsbGRhdGEuc2xpY2UoMik7IC8vIHN0cmlwIDB4XG4gICAgY29uc3QgYWRkcmVzc2VzID0gZGVjb2RlVG9rZW5BZGRyZXNzZXNGcm9tRGVsZWdhdGlvbkNhbGxkYXRhKG5vUHJlZml4KTtcbiAgICBhZGRyZXNzZXMuc2hvdWxkLmRlZXBFcXVhbChbQ1RFU1QxX1RPS0VOX0FERFJFU1MudG9Mb3dlckNhc2UoKV0pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHRocm93IGZvciB1bnJlY29nbmlzZWQgY2FsbGRhdGEnLCBmdW5jdGlvbiAoKSB7XG4gICAgc2hvdWxkLnRocm93cyhcbiAgICAgICgpID0+IGRlY29kZVRva2VuQWRkcmVzc2VzRnJvbURlbGVnYXRpb25DYWxsZGF0YSgnMHhkZWFkYmVlZjAwMDAwMDAwJyksXG4gICAgICAvTm90IGEgdmFsaWQgZGVsZWdhdGlvbiBjYWxsZGF0YS9cbiAgICApO1xuICB9KTtcbn0pO1xuIl19
|