@bitgo-beta/sdk-coin-dot 1.3.3-alpha.472 → 1.3.3-alpha.474
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/dot.d.ts +0 -7
- package/dist/src/dot.d.ts.map +1 -1
- package/dist/src/dot.js +1 -1
- package/dist/src/lib/index.d.ts +2 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +4 -2
- package/dist/src/lib/transaction.d.ts.map +1 -1
- package/dist/src/lib/transaction.js +15 -1
- package/dist/src/lib/wasmParser.d.ts +57 -0
- package/dist/src/lib/wasmParser.d.ts.map +1 -0
- package/dist/src/lib/wasmParser.js +298 -0
- package/dist/test/unit/dot.js +65 -2
- package/dist/test/unit/transactionBuilder/withdrawUnstakedBuilder.js +4 -4
- package/dist/test/unit/wasmBuilderByteComparison.d.ts +17 -0
- package/dist/test/unit/wasmBuilderByteComparison.d.ts.map +1 -0
- package/dist/test/unit/wasmBuilderByteComparison.js +409 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WASM Builder Byte Comparison Tests
|
|
4
|
+
*
|
|
5
|
+
* Compare serialized output between:
|
|
6
|
+
* 1. Legacy approach (using @substrate/txwrapper-polkadot)
|
|
7
|
+
* 2. WASM approach (using @bitgo/wasm-dot DotBuilder)
|
|
8
|
+
*
|
|
9
|
+
* For unsigned transactions, legacy toBroadcastFormat() returns the signing payload
|
|
10
|
+
* (via construct.signingPayload). We compare WASM signablePayload() against it.
|
|
11
|
+
*
|
|
12
|
+
* Format difference: txwrapper encodes the call as `Bytes` (Vec<u8>) which includes
|
|
13
|
+
* a SCALE compact-length prefix. subxt encodes it as raw `Call` (no prefix).
|
|
14
|
+
* We strip this prefix from the legacy side before comparing, since the actual
|
|
15
|
+
* call data, era, nonce, tip, and chain context are identical.
|
|
16
|
+
*/
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const assert_1 = __importDefault(require("assert"));
|
|
22
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
23
|
+
const transactionBuilderFactory_1 = require("../../src/lib/transactionBuilderFactory");
|
|
24
|
+
const iface_1 = require("../../src/lib/iface");
|
|
25
|
+
const fixtures_1 = require("../fixtures");
|
|
26
|
+
const utils_1 = __importDefault(require("../../src/lib/utils"));
|
|
27
|
+
// Import WASM builder
|
|
28
|
+
const wasm_dot_1 = require("@bitgo/wasm-dot");
|
|
29
|
+
describe('WASM vs Legacy Builder Byte Comparison', function () {
|
|
30
|
+
const coin = statics_1.coins.get('tdot');
|
|
31
|
+
// Get material from utils to ensure same metadata as legacy builder
|
|
32
|
+
const material = utils_1.default.getMaterial(coin);
|
|
33
|
+
function createWasmContext(overrides = {}) {
|
|
34
|
+
return {
|
|
35
|
+
sender: fixtures_1.accounts.account1.address,
|
|
36
|
+
nonce: 0,
|
|
37
|
+
tip: 0n,
|
|
38
|
+
material: material,
|
|
39
|
+
validity: {
|
|
40
|
+
firstValid: fixtures_1.westendBlock.blockNumber,
|
|
41
|
+
maxDuration: 2400,
|
|
42
|
+
},
|
|
43
|
+
referenceBlock: fixtures_1.westendBlock.hash,
|
|
44
|
+
...overrides,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Strip SCALE compact-length prefix from the legacy signing payload.
|
|
49
|
+
*
|
|
50
|
+
* Legacy (txwrapper) encodes the call as `Bytes` type, which adds a compact-length
|
|
51
|
+
* prefix. subxt encodes it as raw `Call` (no prefix). Both produce identical
|
|
52
|
+
* call data + era + nonce + tip + chain context after this prefix.
|
|
53
|
+
*/
|
|
54
|
+
function stripCompactPrefix(hex) {
|
|
55
|
+
const data = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
56
|
+
const bytes = Buffer.from(data, 'hex');
|
|
57
|
+
const mode = bytes[0] & 0b11;
|
|
58
|
+
let offset;
|
|
59
|
+
if (mode === 0b00)
|
|
60
|
+
offset = 1;
|
|
61
|
+
else if (mode === 0b01)
|
|
62
|
+
offset = 2;
|
|
63
|
+
else if (mode === 0b10)
|
|
64
|
+
offset = 4;
|
|
65
|
+
else
|
|
66
|
+
throw new Error('Big compact not supported');
|
|
67
|
+
return '0x' + bytes.slice(offset).toString('hex');
|
|
68
|
+
}
|
|
69
|
+
// ===========================================================================
|
|
70
|
+
// Transfer Transaction Tests
|
|
71
|
+
// ===========================================================================
|
|
72
|
+
describe('Transfer Transactions', function () {
|
|
73
|
+
it('should produce identical signing payload for transfer', async function () {
|
|
74
|
+
const to = fixtures_1.accounts.account2.address;
|
|
75
|
+
const amount = '1000000000000'; // 1 DOT
|
|
76
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
77
|
+
const legacyBuilder = factory.getTransferBuilder();
|
|
78
|
+
legacyBuilder
|
|
79
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
80
|
+
.to({ address: to })
|
|
81
|
+
.amount(amount)
|
|
82
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
83
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
84
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
85
|
+
const legacyTx = await legacyBuilder.build();
|
|
86
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
87
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'transfer', to, amount: BigInt(amount), keepAlive: true }, createWasmContext());
|
|
88
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
89
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
90
|
+
});
|
|
91
|
+
it('should produce identical signing payload for transferKeepAlive with different nonce', async function () {
|
|
92
|
+
const to = fixtures_1.accounts.account2.address;
|
|
93
|
+
const amount = '5000000000000'; // 5 DOT
|
|
94
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
95
|
+
const legacyBuilder = factory.getTransferBuilder();
|
|
96
|
+
legacyBuilder
|
|
97
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
98
|
+
.to({ address: to })
|
|
99
|
+
.amount(amount)
|
|
100
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
101
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
102
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 5 });
|
|
103
|
+
const legacyTx = await legacyBuilder.build();
|
|
104
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
105
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'transfer', to, amount: BigInt(amount), keepAlive: true }, createWasmContext({ nonce: 5 }));
|
|
106
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
107
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
// ===========================================================================
|
|
111
|
+
// Staking Transaction Tests
|
|
112
|
+
// ===========================================================================
|
|
113
|
+
describe('Staking Transactions', function () {
|
|
114
|
+
it('should produce identical signing payload for staking bond', async function () {
|
|
115
|
+
const amount = '10000000000000'; // 10 DOT
|
|
116
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
117
|
+
const legacyBuilder = factory.getStakingBuilder();
|
|
118
|
+
legacyBuilder
|
|
119
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
120
|
+
.amount(amount)
|
|
121
|
+
.payee('Staked')
|
|
122
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
123
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
124
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
125
|
+
const legacyTx = await legacyBuilder.build();
|
|
126
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
127
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'stake', amount: BigInt(amount), payee: { type: 'staked' } }, createWasmContext());
|
|
128
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
129
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
130
|
+
});
|
|
131
|
+
it('should produce identical signing payload for staking bond with Stash payee', async function () {
|
|
132
|
+
const amount = '20000000000000'; // 20 DOT
|
|
133
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
134
|
+
const legacyBuilder = factory.getStakingBuilder();
|
|
135
|
+
legacyBuilder
|
|
136
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
137
|
+
.amount(amount)
|
|
138
|
+
.payee('Stash')
|
|
139
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
140
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
141
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
142
|
+
const legacyTx = await legacyBuilder.build();
|
|
143
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
144
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'stake', amount: BigInt(amount), payee: { type: 'stash' } }, createWasmContext());
|
|
145
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
146
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
147
|
+
});
|
|
148
|
+
it('should produce identical signing payload for unstake (unbond)', async function () {
|
|
149
|
+
const amount = '5000000000000'; // 5 DOT
|
|
150
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
151
|
+
const legacyBuilder = factory.getUnstakeBuilder();
|
|
152
|
+
legacyBuilder
|
|
153
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
154
|
+
.amount(amount)
|
|
155
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
156
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
157
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
158
|
+
const legacyTx = await legacyBuilder.build();
|
|
159
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
160
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'unstake', amount: BigInt(amount) }, createWasmContext());
|
|
161
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
162
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
163
|
+
});
|
|
164
|
+
it('should produce identical signing payload for withdrawUnbonded', async function () {
|
|
165
|
+
const slashingSpans = 0;
|
|
166
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
167
|
+
const legacyBuilder = factory.getWithdrawUnstakedBuilder();
|
|
168
|
+
legacyBuilder
|
|
169
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
170
|
+
.slashingSpans(slashingSpans)
|
|
171
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
172
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
173
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
174
|
+
const legacyTx = await legacyBuilder.build();
|
|
175
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
176
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'withdrawUnbonded', slashingSpans }, createWasmContext());
|
|
177
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
178
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
179
|
+
});
|
|
180
|
+
it('should produce identical signing payload for chill (unnominate)', async function () {
|
|
181
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
182
|
+
const legacyBuilder = factory.getUnnominateBuilder();
|
|
183
|
+
legacyBuilder
|
|
184
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
185
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
186
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
187
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
188
|
+
const legacyTx = await legacyBuilder.build();
|
|
189
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
190
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'chill' }, createWasmContext());
|
|
191
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
192
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
// ===========================================================================
|
|
196
|
+
// Proxy Transaction Tests
|
|
197
|
+
// ===========================================================================
|
|
198
|
+
describe('Proxy Transactions', function () {
|
|
199
|
+
it('should produce identical signing payload for addProxy', async function () {
|
|
200
|
+
const delegate = fixtures_1.accounts.account2.address;
|
|
201
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
202
|
+
const legacyBuilder = factory.getAddressInitializationBuilder();
|
|
203
|
+
legacyBuilder
|
|
204
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
205
|
+
.owner({ address: delegate })
|
|
206
|
+
.type(iface_1.ProxyType.ANY)
|
|
207
|
+
.delay('0')
|
|
208
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
209
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
210
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
211
|
+
const legacyTx = await legacyBuilder.build();
|
|
212
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
213
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'addProxy', delegate, proxyType: 'Any', delay: 0 }, createWasmContext());
|
|
214
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
215
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
216
|
+
});
|
|
217
|
+
it('should produce identical signing payload for addProxy with Staking type', async function () {
|
|
218
|
+
const delegate = fixtures_1.accounts.account2.address;
|
|
219
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
220
|
+
const legacyBuilder = factory.getAddressInitializationBuilder();
|
|
221
|
+
legacyBuilder
|
|
222
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
223
|
+
.owner({ address: delegate })
|
|
224
|
+
.type(iface_1.ProxyType.STAKING)
|
|
225
|
+
.delay('100')
|
|
226
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
227
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
228
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
229
|
+
const legacyTx = await legacyBuilder.build();
|
|
230
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
231
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'addProxy', delegate, proxyType: 'Staking', delay: 100 }, createWasmContext());
|
|
232
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
233
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
// ===========================================================================
|
|
237
|
+
// Batch Transaction Tests
|
|
238
|
+
// ===========================================================================
|
|
239
|
+
describe('Batch Transactions', function () {
|
|
240
|
+
it('should produce identical signing payload for batch of transfers', async function () {
|
|
241
|
+
const to1 = fixtures_1.accounts.account2.address;
|
|
242
|
+
const to2 = fixtures_1.accounts.account3.address;
|
|
243
|
+
const amount1 = '1000000000000';
|
|
244
|
+
const amount2 = '2000000000000';
|
|
245
|
+
// Legacy batch requires raw call hex for each sub-call
|
|
246
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
247
|
+
// Build individual transfers to get their call data for the legacy batch
|
|
248
|
+
const t1 = factory.getTransferBuilder();
|
|
249
|
+
t1.sender({ address: fixtures_1.accounts.account1.address })
|
|
250
|
+
.to({ address: to1 })
|
|
251
|
+
.amount(amount1)
|
|
252
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
253
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
254
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
255
|
+
const tx1 = await t1.build();
|
|
256
|
+
const t2 = factory.getTransferBuilder();
|
|
257
|
+
t2.sender({ address: fixtures_1.accounts.account1.address })
|
|
258
|
+
.to({ address: to2 })
|
|
259
|
+
.amount(amount2)
|
|
260
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
261
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
262
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
263
|
+
const tx2 = await t2.build();
|
|
264
|
+
// Extract call data from legacy signing payload for batch construction.
|
|
265
|
+
// Legacy toBroadcastFormat() for unsigned txs returns the signing payload
|
|
266
|
+
// which starts with a compact-length-prefixed call.
|
|
267
|
+
function extractCallFromSigningPayload(signingPayload) {
|
|
268
|
+
const hexData = signingPayload.startsWith('0x') ? signingPayload.slice(2) : signingPayload;
|
|
269
|
+
const bytes = Buffer.from(hexData, 'hex');
|
|
270
|
+
// Decode compact length prefix to find where call data ends
|
|
271
|
+
const mode = bytes[0] & 0b11;
|
|
272
|
+
let callLength;
|
|
273
|
+
let offset;
|
|
274
|
+
if (mode === 0b00) {
|
|
275
|
+
callLength = bytes[0] >> 2;
|
|
276
|
+
offset = 1;
|
|
277
|
+
}
|
|
278
|
+
else if (mode === 0b01) {
|
|
279
|
+
callLength = (bytes[0] | (bytes[1] << 8)) >> 2;
|
|
280
|
+
offset = 2;
|
|
281
|
+
}
|
|
282
|
+
else if (mode === 0b10) {
|
|
283
|
+
callLength = (bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24)) >> 2;
|
|
284
|
+
offset = 4;
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
throw new Error('Unsupported compact length mode');
|
|
288
|
+
}
|
|
289
|
+
return '0x' + bytes.slice(offset, offset + callLength).toString('hex');
|
|
290
|
+
}
|
|
291
|
+
const call1Hex = extractCallFromSigningPayload(tx1.toBroadcastFormat());
|
|
292
|
+
const call2Hex = extractCallFromSigningPayload(tx2.toBroadcastFormat());
|
|
293
|
+
const batchBuilder = factory.getBatchTransactionBuilder();
|
|
294
|
+
batchBuilder
|
|
295
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
296
|
+
.calls([call1Hex, call2Hex])
|
|
297
|
+
.atomic(true)
|
|
298
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
299
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
300
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
301
|
+
const legacyTx = await batchBuilder.build();
|
|
302
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
303
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({
|
|
304
|
+
type: 'batch',
|
|
305
|
+
calls: [
|
|
306
|
+
{ type: 'transfer', to: to1, amount: BigInt(amount1), keepAlive: true },
|
|
307
|
+
{ type: 'transfer', to: to2, amount: BigInt(amount2), keepAlive: true },
|
|
308
|
+
],
|
|
309
|
+
atomic: true,
|
|
310
|
+
}, createWasmContext());
|
|
311
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
312
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
313
|
+
});
|
|
314
|
+
it('should produce identical signing payload for non-atomic batch', async function () {
|
|
315
|
+
const to = fixtures_1.accounts.account2.address;
|
|
316
|
+
const amount = '1000000000000';
|
|
317
|
+
const factory = new transactionBuilderFactory_1.TransactionBuilderFactory(coin);
|
|
318
|
+
const transferBuilder = factory.getTransferBuilder();
|
|
319
|
+
transferBuilder
|
|
320
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
321
|
+
.to({ address: to })
|
|
322
|
+
.amount(amount)
|
|
323
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
324
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
325
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
326
|
+
const transferTx = await transferBuilder.build();
|
|
327
|
+
function extractCallFromSigningPayload(signingPayload) {
|
|
328
|
+
const hexData = signingPayload.startsWith('0x') ? signingPayload.slice(2) : signingPayload;
|
|
329
|
+
const bytes = Buffer.from(hexData, 'hex');
|
|
330
|
+
const mode = bytes[0] & 0b11;
|
|
331
|
+
let callLength;
|
|
332
|
+
let offset;
|
|
333
|
+
if (mode === 0b00) {
|
|
334
|
+
callLength = bytes[0] >> 2;
|
|
335
|
+
offset = 1;
|
|
336
|
+
}
|
|
337
|
+
else if (mode === 0b01) {
|
|
338
|
+
callLength = (bytes[0] | (bytes[1] << 8)) >> 2;
|
|
339
|
+
offset = 2;
|
|
340
|
+
}
|
|
341
|
+
else if (mode === 0b10) {
|
|
342
|
+
callLength = (bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24)) >> 2;
|
|
343
|
+
offset = 4;
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
throw new Error('Unsupported compact length mode');
|
|
347
|
+
}
|
|
348
|
+
return '0x' + bytes.slice(offset, offset + callLength).toString('hex');
|
|
349
|
+
}
|
|
350
|
+
const callHex = extractCallFromSigningPayload(transferTx.toBroadcastFormat());
|
|
351
|
+
const batchBuilder = factory.getBatchTransactionBuilder();
|
|
352
|
+
batchBuilder
|
|
353
|
+
.sender({ address: fixtures_1.accounts.account1.address })
|
|
354
|
+
.calls([callHex])
|
|
355
|
+
.atomic(false)
|
|
356
|
+
.validity({ firstValid: fixtures_1.westendBlock.blockNumber, maxDuration: 2400 })
|
|
357
|
+
.referenceBlock(fixtures_1.westendBlock.hash)
|
|
358
|
+
.sequenceId({ name: 'Nonce', keyword: 'nonce', value: 0 });
|
|
359
|
+
const legacyTx = await batchBuilder.build();
|
|
360
|
+
const legacyHex = legacyTx.toBroadcastFormat();
|
|
361
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({
|
|
362
|
+
type: 'batch',
|
|
363
|
+
calls: [{ type: 'transfer', to, amount: BigInt(amount), keepAlive: true }],
|
|
364
|
+
atomic: false,
|
|
365
|
+
}, createWasmContext());
|
|
366
|
+
const wasmHex = '0x' + Buffer.from(wasmTx.signablePayload()).toString('hex');
|
|
367
|
+
assert_1.default.strictEqual(wasmHex, stripCompactPrefix(legacyHex), 'Signing payload should match');
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
// ===========================================================================
|
|
371
|
+
// Intent-based Transaction Building (sanity checks)
|
|
372
|
+
// ===========================================================================
|
|
373
|
+
describe('Intent-based Transaction Building', function () {
|
|
374
|
+
it('should build transfer from intent', async function () {
|
|
375
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'transfer', to: fixtures_1.accounts.account2.address, amount: 1000000000000n, keepAlive: true }, createWasmContext());
|
|
376
|
+
const serialized = wasmTx.toBroadcastFormat();
|
|
377
|
+
(0, assert_1.default)(serialized.startsWith('0x'), 'Should be hex encoded');
|
|
378
|
+
(0, assert_1.default)(serialized.length > 10, 'Should have content');
|
|
379
|
+
});
|
|
380
|
+
it('should build stake from intent', async function () {
|
|
381
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'stake', amount: 5000000000000n, payee: { type: 'staked' } }, createWasmContext());
|
|
382
|
+
(0, assert_1.default)(wasmTx.toBroadcastFormat().startsWith('0x'));
|
|
383
|
+
});
|
|
384
|
+
it('should build withdrawUnbonded from intent', async function () {
|
|
385
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'withdrawUnbonded', slashingSpans: 0 }, createWasmContext());
|
|
386
|
+
(0, assert_1.default)(wasmTx.toBroadcastFormat().startsWith('0x'));
|
|
387
|
+
});
|
|
388
|
+
it('should build chill from intent', async function () {
|
|
389
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'chill' }, createWasmContext());
|
|
390
|
+
(0, assert_1.default)(wasmTx.toBroadcastFormat().startsWith('0x'));
|
|
391
|
+
});
|
|
392
|
+
it('should build addProxy from intent', async function () {
|
|
393
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({ type: 'addProxy', delegate: fixtures_1.accounts.account2.address, proxyType: 'Any', delay: 0 }, createWasmContext());
|
|
394
|
+
(0, assert_1.default)(wasmTx.toBroadcastFormat().startsWith('0x'));
|
|
395
|
+
});
|
|
396
|
+
it('should build batch from intent', async function () {
|
|
397
|
+
const wasmTx = (0, wasm_dot_1.buildTransaction)({
|
|
398
|
+
type: 'batch',
|
|
399
|
+
calls: [
|
|
400
|
+
{ type: 'transfer', to: fixtures_1.accounts.account2.address, amount: 1000000000000n, keepAlive: true },
|
|
401
|
+
{ type: 'chill' },
|
|
402
|
+
],
|
|
403
|
+
atomic: true,
|
|
404
|
+
}, createWasmContext());
|
|
405
|
+
(0, assert_1.default)(wasmTx.toBroadcastFormat().startsWith('0x'));
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FzbUJ1aWxkZXJCeXRlQ29tcGFyaXNvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC93YXNtQnVpbGRlckJ5dGVDb21wYXJpc29uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7R0FjRzs7Ozs7QUFFSCxvREFBNEI7QUFDNUIsaURBQTRDO0FBQzVDLHVGQUFvRjtBQUVwRiwrQ0FBZ0Q7QUFDaEQsMENBQXFEO0FBQ3JELGdFQUF3QztBQUV4QyxzQkFBc0I7QUFDdEIsOENBQXFGO0FBRXJGLFFBQVEsQ0FBQyx3Q0FBd0MsRUFBRTtJQUNqRCxNQUFNLElBQUksR0FBRyxlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRS9CLG9FQUFvRTtJQUNwRSxNQUFNLFFBQVEsR0FBRyxlQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXpDLFNBQVMsaUJBQWlCLENBQUMsWUFBbUMsRUFBRTtRQUM5RCxPQUFPO1lBQ0wsTUFBTSxFQUFFLG1CQUFRLENBQUMsUUFBUSxDQUFDLE9BQU87WUFDakMsS0FBSyxFQUFFLENBQUM7WUFDUixHQUFHLEVBQUUsRUFBRTtZQUNQLFFBQVEsRUFBRSxRQUFvQjtZQUM5QixRQUFRLEVBQUU7Z0JBQ1IsVUFBVSxFQUFFLHVCQUFZLENBQUMsV0FBVztnQkFDcEMsV0FBVyxFQUFFLElBQUk7YUFDbEI7WUFDRCxjQUFjLEVBQUUsdUJBQVksQ0FBQyxJQUFJO1lBQ2pDLEdBQUcsU0FBUztTQUNiLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxHQUFXO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUN2RCxNQUFN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QUUsUUFBUSxFQUFFLG1CQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFDckYsaUJBQWlCLEVBQUUsQ0FDcEIsQ0FBQztZQUNGLElBQUEsZ0JBQU0sRUFBQyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLO1lBQ3hDLE1BQU0sTUFBTSxHQUFHLElBQUEsMkJBQWdCLEVBQzdCO2dCQUNFLElBQUksRUFBRSxPQUFPO2dCQUNiLEtBQUssRUFBRTtvQkFDTCxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLG1CQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUU7b0JBQzVGLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtpQkFDbEI7Z0JBQ0QsTUFBTSxFQUFFLElBQUk7YUFDYixFQUNELGlCQUFpQixFQUFFLENBQ3BCLENBQUM7WUFDRixJQUFBLGdCQUFNLEVBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDdEQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXQVNNIEJ1aWxkZXIgQnl0ZSBDb21wYXJpc29uIFRlc3RzXG4gKlxuICogQ29tcGFyZSBzZXJpYWxpemVkIG91dHB1dCBiZXR3ZWVuOlxuICogMS4gTGVnYWN5IGFwcHJvYWNoICh1c2luZyBAc3Vic3RyYXRlL3R4d3JhcHBlci1wb2xrYWRvdClcbiAqIDIuIFdBU00gYXBwcm9hY2ggKHVzaW5nIEBiaXRnby93YXNtLWRvdCBEb3RCdWlsZGVyKVxuICpcbiAqIEZvciB1bnNpZ25lZCB0cmFuc2FjdGlvbnMsIGxlZ2FjeSB0b0Jyb2FkY2FzdEZvcm1hdCgpIHJldHVybnMgdGhlIHNpZ25pbmcgcGF5bG9hZFxuICogKHZpYSBjb25zdHJ1Y3Quc2lnbmluZ1BheWxvYWQpLiBXZSBjb21wYXJlIFdBU00gc2lnbmFibGVQYXlsb2FkKCkgYWdhaW5zdCBpdC5cbiAqXG4gKiBGb3JtYXQgZGlmZmVyZW5jZTogdHh3cmFwcGVyIGVuY29kZXMgdGhlIGNhbGwgYXMgYEJ5dGVzYCAoVmVjPHU4Pikgd2hpY2ggaW5jbHVkZXNcbiAqIGEgU0NBTEUgY29tcGFjdC1sZW5ndGggcHJlZml4LiBzdWJ4dCBlbmNvZGVzIGl0IGFzIHJhdyBgQ2FsbGAgKG5vIHByZWZpeCkuXG4gKiBXZSBzdHJpcCB0aGlzIHByZWZpeCBmcm9tIHRoZSBsZWdhY3kgc2lkZSBiZWZvcmUgY29tcGFyaW5nLCBzaW5jZSB0aGUgYWN0dWFsXG4gKiBjYWxsIGRhdGEsIGVyYSwgbm9uY2UsIHRpcCwgYW5kIGNoYWluIGNvbnRleHQgYXJlIGlkZW50aWNhbC5cbiAqL1xuXG5pbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBjb2lucyB9IGZyb20gJ0BiaXRnby1iZXRhL3N0YXRpY3MnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSB9IGZyb20gJy4uLy4uL3NyYy9saWIvdHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSc7XG5pbXBvcnQgeyBUcmFuc2ZlckJ1aWxkZXIgfSBmcm9tICcuLi8uLi9zcmMvbGliL3RyYW5zZmVyQnVpbGRlcic7XG5pbXBvcnQgeyBQcm94eVR5cGUgfSBmcm9tICcuLi8uLi9zcmMvbGliL2lmYWNlJztcbmltcG9ydCB7IGFjY291bnRzLCB3ZXN0ZW5kQmxvY2sgfSBmcm9tICcuLi9maXh0dXJlcyc7XG5pbXBvcnQgdXRpbHMgZnJvbSAnLi4vLi4vc3JjL2xpYi91dGlscyc7XG5cbi8vIEltcG9ydCBXQVNNIGJ1aWxkZXJcbmltcG9ydCB7IGJ1aWxkVHJhbnNhY3Rpb24sIHR5cGUgQnVpbGRDb250ZXh0LCB0eXBlIE1hdGVyaWFsIH0gZnJvbSAnQGJpdGdvL3dhc20tZG90JztcblxuZGVzY3JpYmUoJ1dBU00gdnMgTGVnYWN5IEJ1aWxkZXIgQnl0ZSBDb21wYXJpc29uJywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBjb2luID0gY29pbnMuZ2V0KCd0ZG90Jyk7XG5cbiAgLy8gR2V0IG1hdGVyaWFsIGZyb20gdXRpbHMgdG8gZW5zdXJlIHNhbWUgbWV0YWRhdGEgYXMgbGVnYWN5IGJ1aWxkZXJcbiAgY29uc3QgbWF0ZXJpYWwgPSB1dGlscy5nZXRNYXRlcmlhbChjb2luKTtcblxuICBmdW5jdGlvbiBjcmVhdGVXYXNtQ29udGV4dChvdmVycmlkZXM6IFBhcnRpYWw8QnVpbGRDb250ZXh0PiA9IHt9KTogQnVpbGRDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgc2VuZGVyOiBhY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzLFxuICAgICAgbm9uY2U6IDAsXG4gICAgICB0aXA6IDBuLFxuICAgICAgbWF0ZXJpYWw6IG1hdGVyaWFsIGFzIE1hdGVyaWFsLFxuICAgICAgdmFsaWRpdHk6IHtcbiAgICAgICAgZmlyc3RWYWxpZDogd2VzdGVuZEJsb2NrLmJsb2NrTnVtYmVyLFxuICAgICAgICBtYXhEdXJhdGlvbjogMjQwMCxcbiAgICAgIH0sXG4gICAgICByZWZlcmVuY2VCbG9jazogd2VzdGVuZEJsb2NrLmhhc2gsXG4gICAgICAuLi5vdmVycmlkZXMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdHJpcCBTQ0FMRSBjb21wYWN0LWxlbmd0aCBwcmVmaXggZnJvbSB0aGUgbGVnYWN5IHNpZ25pbmcgcGF5bG9hZC5cbiAgICpcbiAgICogTGVnYWN5ICh0eHdyYXBwZXIpIGVuY29kZXMgdGhlIGNhbGwgYXMgYEJ5dGVzYCB0eXBlLCB3aGljaCBhZGRzIGEgY29tcGFjdC1sZW5ndGhcbiAgICogcHJlZml4LiBzdWJ4dCBlbmNvZGVzIGl0IGFzIHJhdyBgQ2FsbGAgKG5vIHByZWZpeCkuIEJvdGggcHJvZHVjZSBpZGVudGljYWxcbiAgICogY2FsbCBkYXRhICsgZXJhICsgbm9uY2UgKyB0aXAgKyBjaGFpbiBjb250ZXh0IGFmdGVyIHRoaXMgcHJlZml4LlxuICAgKi9cbiAgZnVuY3Rpb24gc3RyaXBDb21wYWN0UHJlZml4KGhleDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBkYXRhID0gaGV4LnN0YXJ0c1dpdGgoJzB4JykgPyBoZXguc2xpY2UoMikgOiBoZXg7XG4gICAgY29uc3QgYnl0ZXMgPSBCdWZmZXIuZnJvbShkYXRhLCAnaGV4Jyk7XG4gICAgY29uc3QgbW9kZSA9IGJ5dGVzWzBdICYgMGIxMTtcbiAgICBsZXQgb2Zmc2V0OiBudW1iZXI7XG4gICAgaWYgKG1vZGUgPT09IDBiMDApIG9mZnNldCA9IDE7XG4gICAgZWxzZSBpZiAobW9kZSA9PT0gMGIwMSkgb2Zmc2V0ID0gMjtcbiAgICBlbHNlIGlmIChtb2RlID09PSAwYjEwKSBvZmZzZXQgPSA0O1xuICAgIGVsc2UgdGhyb3cgbmV3IEVycm9yKCdCaWcgY29tcGFjdCBub3Qgc3VwcG9ydGVkJyk7XG4gICAgcmV0dXJuICcweCcgKyBieXRlcy5zbGljZShvZmZzZXQpLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBUcmFuc2ZlciBUcmFuc2FjdGlvbiBUZXN0c1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgZGVzY3JpYmUoJ1RyYW5zZmVyIFRyYW5zYWN0aW9ucycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgaWRlbnRpY2FsIHNpZ25pbmcgcGF5bG9hZCBmb3IgdHJhbnNmZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0byA9IGFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG4gICAgICBjb25zdCBhbW91bnQgPSAnMTAwMDAwMDAwMDAwMCc7IC8vIDEgRE9UXG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcblxuICAgICAgbGVnYWN5QnVpbGRlclxuICAgICAgICAuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyB9KVxuICAgICAgICAudG8oeyBhZGRyZXNzOiB0byB9KVxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnZhbGlkaXR5KHsgZmlyc3RWYWxpZDogd2VzdGVuZEJsb2NrLmJsb2NrTnVtYmVyLCBtYXhEdXJhdGlvbjogMjQwMCB9KVxuICAgICAgICAucmVmZXJlbmNlQmxvY2sod2VzdGVuZEJsb2NrLmhhc2gpXG4gICAgICAgIC5zZXF1ZW5jZUlkKHsgbmFtZTogJ05vbmNlJywga2V5d29yZDogJ25vbmNlJywgdmFsdWU6IDAgfSk7XG5cbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gYXdhaXQgbGVnYWN5QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgbGVnYWN5SGV4ID0gbGVnYWN5VHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3Qgd2FzbVR4ID0gYnVpbGRUcmFuc2FjdGlvbihcbiAgICAgICAgeyB0eXBlOiAndHJhbnNmZXInLCB0bywgYW1vdW50OiBCaWdJbnQoYW1vdW50KSwga2VlcEFsaXZlOiB0cnVlIH0sXG4gICAgICAgIGNyZWF0ZVdhc21Db250ZXh0KClcbiAgICAgICk7XG4gICAgICBjb25zdCB3YXNtSGV4ID0gJzB4JyArIEJ1ZmZlci5mcm9tKHdhc21UeC5zaWduYWJsZVBheWxvYWQoKSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwod2FzbUhleCwgc3RyaXBDb21wYWN0UHJlZml4KGxlZ2FjeUhleCksICdTaWduaW5nIHBheWxvYWQgc2hvdWxkIG1hdGNoJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgaWRlbnRpY2FsIHNpZ25pbmcgcGF5bG9hZCBmb3IgdHJhbnNmZXJLZWVwQWxpdmUgd2l0aCBkaWZmZXJlbnQgbm9uY2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0byA9IGFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG4gICAgICBjb25zdCBhbW91bnQgPSAnNTAwMDAwMDAwMDAwMCc7IC8vIDUgRE9UXG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcblxuICAgICAgbGVnYWN5QnVpbGRlclxuICAgICAgICAuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyB9KVxuICAgICAgICAudG8oeyBhZGRyZXNzOiB0byB9KVxuICAgICAgICAuYW1vdW50KGFtb3VudClcbiAgICAgICAgLnZhbGlkaXR5KHsgZmlyc3RWYWxpZDogd2VzdGVuZEJsb2NrLmJsb2NrTnVtYmVyLCBtYXhEdXJhdGlvbjogMjQwMCB9KVxuICAgICAgICAucmVmZXJlbmNlQmxvY2sod2VzdGVuZEJsb2NrLmhhc2gpXG4gICAgICAgIC5zZXF1ZW5jZUlkKHsgbmFtZTogJ05vbmNlJywga2V5d29yZDogJ25vbmNlJywgdmFsdWU6IDUgfSk7XG5cbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gYXdhaXQgbGVnYWN5QnVpbGRlci5idWlsZCgpO1xuICAgICAgY29uc3QgbGVnYWN5SGV4ID0gbGVnYWN5VHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcblxuICAgICAgY29uc3Qgd2FzbVR4ID0gYnVpbGRUcmFuc2FjdGlvbihcbiAgICAgICAgeyB0eXBlOiAndHJhbnNmZXInLCB0bywgYW1vdW50OiBCaWdJbnQoYW1vdW50KSwga2VlcEFsaXZlOiB0cnVlIH0sXG4gICAgICAgIGNyZWF0ZVdhc21Db250ZXh0KHsgbm9uY2U6IDUgfSlcbiAgICAgICk7XG4gICAgICBjb25zdCB3YXNtSGV4ID0gJzB4JyArIEJ1ZmZlci5mcm9tKHdhc21UeC5zaWduYWJsZVBheWxvYWQoKSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwod2FzbUhleCwgc3RyaXBDb21wYWN0UHJlZml4KGxlZ2FjeUhleCksICdTaWduaW5nIHBheWxvYWQgc2hvdWxkIG1hdGNoJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBTdGFraW5nIFRyYW5zYWN0aW9uIFRlc3RzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBkZXNjcmliZSgnU3Rha2luZyBUcmFuc2FjdGlvbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGlkZW50aWNhbCBzaWduaW5nIHBheWxvYWQgZm9yIHN0YWtpbmcgYm9uZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFtb3VudCA9ICcxMDAwMDAwMDAwMDAwMCc7IC8vIDEwIERPVFxuXG4gICAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbik7XG4gICAgICBjb25zdCBsZWdhY3lCdWlsZGVyID0gZmFjdG9yeS5nZXRTdGFraW5nQnVpbGRlcigpO1xuXG4gICAgICBsZWdhY3lCdWlsZGVyXG4gICAgICAgIC5zZW5kZXIoeyBhZGRyZXNzOiBhY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzIH0pXG4gICAgICAgIC5hbW91bnQoYW1vdW50KVxuICAgICAgICAucGF5ZWUoJ1N0YWtlZCcpXG4gICAgICAgIC52YWxpZGl0eSh7IGZpcnN0VmFsaWQ6IHdlc3RlbmRCbG9jay5ibG9ja051bWJlciwgbWF4RHVyYXRpb246IDI0MDAgfSlcbiAgICAgICAgLnJlZmVyZW5jZUJsb2NrKHdlc3RlbmRCbG9jay5oYXNoKVxuICAgICAgICAuc2VxdWVuY2VJZCh7IG5hbWU6ICdOb25jZScsIGtleXdvcmQ6ICdub25jZScsIHZhbHVlOiAwIH0pO1xuXG4gICAgICBjb25zdCBsZWdhY3lUeCA9IGF3YWl0IGxlZ2FjeUJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUhleCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHsgdHlwZTogJ3N0YWtlJywgYW1vdW50OiBCaWdJbnQoYW1vdW50KSwgcGF5ZWU6IHsgdHlwZTogJ3N0YWtlZCcgfSB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FzbUhleCA9ICcweCcgKyBCdWZmZXIuZnJvbSh3YXNtVHguc2lnbmFibGVQYXlsb2FkKCkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHdhc21IZXgsIHN0cmlwQ29tcGFjdFByZWZpeChsZWdhY3lIZXgpLCAnU2lnbmluZyBwYXlsb2FkIHNob3VsZCBtYXRjaCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGlkZW50aWNhbCBzaWduaW5nIHBheWxvYWQgZm9yIHN0YWtpbmcgYm9uZCB3aXRoIFN0YXNoIHBheWVlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYW1vdW50ID0gJzIwMDAwMDAwMDAwMDAwJzsgLy8gMjAgRE9UXG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUJ1aWxkZXIgPSBmYWN0b3J5LmdldFN0YWtpbmdCdWlsZGVyKCk7XG5cbiAgICAgIGxlZ2FjeUJ1aWxkZXJcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC5wYXllZSgnU3Rhc2gnKVxuICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiB3ZXN0ZW5kQmxvY2suYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiAyNDAwIH0pXG4gICAgICAgIC5yZWZlcmVuY2VCbG9jayh3ZXN0ZW5kQmxvY2suaGFzaClcbiAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMCB9KTtcblxuICAgICAgY29uc3QgbGVnYWN5VHggPSBhd2FpdCBsZWdhY3lCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBsZWdhY3lIZXggPSBsZWdhY3lUeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKFxuICAgICAgICB7IHR5cGU6ICdzdGFrZScsIGFtb3VudDogQmlnSW50KGFtb3VudCksIHBheWVlOiB7IHR5cGU6ICdzdGFzaCcgfSB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FzbUhleCA9ICcweCcgKyBCdWZmZXIuZnJvbSh3YXNtVHguc2lnbmFibGVQYXlsb2FkKCkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHdhc21IZXgsIHN0cmlwQ29tcGFjdFByZWZpeChsZWdhY3lIZXgpLCAnU2lnbmluZyBwYXlsb2FkIHNob3VsZCBtYXRjaCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGlkZW50aWNhbCBzaWduaW5nIHBheWxvYWQgZm9yIHVuc3Rha2UgKHVuYm9uZCknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhbW91bnQgPSAnNTAwMDAwMDAwMDAwMCc7IC8vIDUgRE9UXG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUJ1aWxkZXIgPSBmYWN0b3J5LmdldFVuc3Rha2VCdWlsZGVyKCk7XG5cbiAgICAgIGxlZ2FjeUJ1aWxkZXJcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC52YWxpZGl0eSh7IGZpcnN0VmFsaWQ6IHdlc3RlbmRCbG9jay5ibG9ja051bWJlciwgbWF4RHVyYXRpb246IDI0MDAgfSlcbiAgICAgICAgLnJlZmVyZW5jZUJsb2NrKHdlc3RlbmRCbG9jay5oYXNoKVxuICAgICAgICAuc2VxdWVuY2VJZCh7IG5hbWU6ICdOb25jZScsIGtleXdvcmQ6ICdub25jZScsIHZhbHVlOiAwIH0pO1xuXG4gICAgICBjb25zdCBsZWdhY3lUeCA9IGF3YWl0IGxlZ2FjeUJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUhleCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oeyB0eXBlOiAndW5zdGFrZScsIGFtb3VudDogQmlnSW50KGFtb3VudCkgfSwgY3JlYXRlV2FzbUNvbnRleHQoKSk7XG4gICAgICBjb25zdCB3YXNtSGV4ID0gJzB4JyArIEJ1ZmZlci5mcm9tKHdhc21UeC5zaWduYWJsZVBheWxvYWQoKSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwod2FzbUhleCwgc3RyaXBDb21wYWN0UHJlZml4KGxlZ2FjeUhleCksICdTaWduaW5nIHBheWxvYWQgc2hvdWxkIG1hdGNoJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgaWRlbnRpY2FsIHNpZ25pbmcgcGF5bG9hZCBmb3Igd2l0aGRyYXdVbmJvbmRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNsYXNoaW5nU3BhbnMgPSAwO1xuXG4gICAgICBjb25zdCBmYWN0b3J5ID0gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbik7XG4gICAgICBjb25zdCBsZWdhY3lCdWlsZGVyID0gZmFjdG9yeS5nZXRXaXRoZHJhd1Vuc3Rha2VkQnVpbGRlcigpO1xuXG4gICAgICBsZWdhY3lCdWlsZGVyXG4gICAgICAgIC5zZW5kZXIoeyBhZGRyZXNzOiBhY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzIH0pXG4gICAgICAgIC5zbGFzaGluZ1NwYW5zKHNsYXNoaW5nU3BhbnMpXG4gICAgICAgIC52YWxpZGl0eSh7IGZpcnN0VmFsaWQ6IHdlc3RlbmRCbG9jay5ibG9ja051bWJlciwgbWF4RHVyYXRpb246IDI0MDAgfSlcbiAgICAgICAgLnJlZmVyZW5jZUJsb2NrKHdlc3RlbmRCbG9jay5oYXNoKVxuICAgICAgICAuc2VxdWVuY2VJZCh7IG5hbWU6ICdOb25jZScsIGtleXdvcmQ6ICdub25jZScsIHZhbHVlOiAwIH0pO1xuXG4gICAgICBjb25zdCBsZWdhY3lUeCA9IGF3YWl0IGxlZ2FjeUJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUhleCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oeyB0eXBlOiAnd2l0aGRyYXdVbmJvbmRlZCcsIHNsYXNoaW5nU3BhbnMgfSwgY3JlYXRlV2FzbUNvbnRleHQoKSk7XG4gICAgICBjb25zdCB3YXNtSGV4ID0gJzB4JyArIEJ1ZmZlci5mcm9tKHdhc21UeC5zaWduYWJsZVBheWxvYWQoKSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwod2FzbUhleCwgc3RyaXBDb21wYWN0UHJlZml4KGxlZ2FjeUhleCksICdTaWduaW5nIHBheWxvYWQgc2hvdWxkIG1hdGNoJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgaWRlbnRpY2FsIHNpZ25pbmcgcGF5bG9hZCBmb3IgY2hpbGwgKHVubm9taW5hdGUpJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW4pO1xuICAgICAgY29uc3QgbGVnYWN5QnVpbGRlciA9IGZhY3RvcnkuZ2V0VW5ub21pbmF0ZUJ1aWxkZXIoKTtcblxuICAgICAgbGVnYWN5QnVpbGRlclxuICAgICAgICAuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyB9KVxuICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiB3ZXN0ZW5kQmxvY2suYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiAyNDAwIH0pXG4gICAgICAgIC5yZWZlcmVuY2VCbG9jayh3ZXN0ZW5kQmxvY2suaGFzaClcbiAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMCB9KTtcblxuICAgICAgY29uc3QgbGVnYWN5VHggPSBhd2FpdCBsZWdhY3lCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBsZWdhY3lIZXggPSBsZWdhY3lUeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKHsgdHlwZTogJ2NoaWxsJyB9LCBjcmVhdGVXYXNtQ29udGV4dCgpKTtcbiAgICAgIGNvbnN0IHdhc21IZXggPSAnMHgnICsgQnVmZmVyLmZyb20od2FzbVR4LnNpZ25hYmxlUGF5bG9hZCgpKS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh3YXNtSGV4LCBzdHJpcENvbXBhY3RQcmVmaXgobGVnYWN5SGV4KSwgJ1NpZ25pbmcgcGF5bG9hZCBzaG91bGQgbWF0Y2gnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFByb3h5IFRyYW5zYWN0aW9uIFRlc3RzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBkZXNjcmliZSgnUHJveHkgVHJhbnNhY3Rpb25zJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcHJvZHVjZSBpZGVudGljYWwgc2lnbmluZyBwYXlsb2FkIGZvciBhZGRQcm94eScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRlbGVnYXRlID0gYWNjb3VudHMuYWNjb3VudDIuYWRkcmVzcztcblxuICAgICAgY29uc3QgZmFjdG9yeSA9IG5ldyBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5KGNvaW4pO1xuICAgICAgY29uc3QgbGVnYWN5QnVpbGRlciA9IGZhY3RvcnkuZ2V0QWRkcmVzc0luaXRpYWxpemF0aW9uQnVpbGRlcigpO1xuXG4gICAgICBsZWdhY3lCdWlsZGVyXG4gICAgICAgIC5zZW5kZXIoeyBhZGRyZXNzOiBhY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzIH0pXG4gICAgICAgIC5vd25lcih7IGFkZHJlc3M6IGRlbGVnYXRlIH0pXG4gICAgICAgIC50eXBlKFByb3h5VHlwZS5BTlkpXG4gICAgICAgIC5kZWxheSgnMCcpXG4gICAgICAgIC52YWxpZGl0eSh7IGZpcnN0VmFsaWQ6IHdlc3RlbmRCbG9jay5ibG9ja051bWJlciwgbWF4RHVyYXRpb246IDI0MDAgfSlcbiAgICAgICAgLnJlZmVyZW5jZUJsb2NrKHdlc3RlbmRCbG9jay5oYXNoKVxuICAgICAgICAuc2VxdWVuY2VJZCh7IG5hbWU6ICdOb25jZScsIGtleXdvcmQ6ICdub25jZScsIHZhbHVlOiAwIH0pO1xuXG4gICAgICBjb25zdCBsZWdhY3lUeCA9IGF3YWl0IGxlZ2FjeUJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUhleCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oeyB0eXBlOiAnYWRkUHJveHknLCBkZWxlZ2F0ZSwgcHJveHlUeXBlOiAnQW55JywgZGVsYXk6IDAgfSwgY3JlYXRlV2FzbUNvbnRleHQoKSk7XG4gICAgICBjb25zdCB3YXNtSGV4ID0gJzB4JyArIEJ1ZmZlci5mcm9tKHdhc21UeC5zaWduYWJsZVBheWxvYWQoKSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwod2FzbUhleCwgc3RyaXBDb21wYWN0UHJlZml4KGxlZ2FjeUhleCksICdTaWduaW5nIHBheWxvYWQgc2hvdWxkIG1hdGNoJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgaWRlbnRpY2FsIHNpZ25pbmcgcGF5bG9hZCBmb3IgYWRkUHJveHkgd2l0aCBTdGFraW5nIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBkZWxlZ2F0ZSA9IGFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUJ1aWxkZXIgPSBmYWN0b3J5LmdldEFkZHJlc3NJbml0aWFsaXphdGlvbkJ1aWxkZXIoKTtcblxuICAgICAgbGVnYWN5QnVpbGRlclxuICAgICAgICAuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyB9KVxuICAgICAgICAub3duZXIoeyBhZGRyZXNzOiBkZWxlZ2F0ZSB9KVxuICAgICAgICAudHlwZShQcm94eVR5cGUuU1RBS0lORylcbiAgICAgICAgLmRlbGF5KCcxMDAnKVxuICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiB3ZXN0ZW5kQmxvY2suYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiAyNDAwIH0pXG4gICAgICAgIC5yZWZlcmVuY2VCbG9jayh3ZXN0ZW5kQmxvY2suaGFzaClcbiAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMCB9KTtcblxuICAgICAgY29uc3QgbGVnYWN5VHggPSBhd2FpdCBsZWdhY3lCdWlsZGVyLmJ1aWxkKCk7XG4gICAgICBjb25zdCBsZWdhY3lIZXggPSBsZWdhY3lUeC50b0Jyb2FkY2FzdEZvcm1hdCgpO1xuXG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKFxuICAgICAgICB7IHR5cGU6ICdhZGRQcm94eScsIGRlbGVnYXRlLCBwcm94eVR5cGU6ICdTdGFraW5nJywgZGVsYXk6IDEwMCB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FzbUhleCA9ICcweCcgKyBCdWZmZXIuZnJvbSh3YXNtVHguc2lnbmFibGVQYXlsb2FkKCkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHdhc21IZXgsIHN0cmlwQ29tcGFjdFByZWZpeChsZWdhY3lIZXgpLCAnU2lnbmluZyBwYXlsb2FkIHNob3VsZCBtYXRjaCcpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gQmF0Y2ggVHJhbnNhY3Rpb24gVGVzdHNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIGRlc2NyaWJlKCdCYXRjaCBUcmFuc2FjdGlvbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGlkZW50aWNhbCBzaWduaW5nIHBheWxvYWQgZm9yIGJhdGNoIG9mIHRyYW5zZmVycycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHRvMSA9IGFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG4gICAgICBjb25zdCB0bzIgPSBhY2NvdW50cy5hY2NvdW50My5hZGRyZXNzO1xuICAgICAgY29uc3QgYW1vdW50MSA9ICcxMDAwMDAwMDAwMDAwJztcbiAgICAgIGNvbnN0IGFtb3VudDIgPSAnMjAwMDAwMDAwMDAwMCc7XG5cbiAgICAgIC8vIExlZ2FjeSBiYXRjaCByZXF1aXJlcyByYXcgY2FsbCBoZXggZm9yIGVhY2ggc3ViLWNhbGxcbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcblxuICAgICAgLy8gQnVpbGQgaW5kaXZpZHVhbCB0cmFuc2ZlcnMgdG8gZ2V0IHRoZWlyIGNhbGwgZGF0YSBmb3IgdGhlIGxlZ2FjeSBiYXRjaFxuICAgICAgY29uc3QgdDEgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcbiAgICAgIHQxLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLnRvKHsgYWRkcmVzczogdG8xIH0pXG4gICAgICAgIC5hbW91bnQoYW1vdW50MSlcbiAgICAgICAgLnZhbGlkaXR5KHsgZmlyc3RWYWxpZDogd2VzdGVuZEJsb2NrLmJsb2NrTnVtYmVyLCBtYXhEdXJhdGlvbjogMjQwMCB9KVxuICAgICAgICAucmVmZXJlbmNlQmxvY2sod2VzdGVuZEJsb2NrLmhhc2gpXG4gICAgICAgIC5zZXF1ZW5jZUlkKHsgbmFtZTogJ05vbmNlJywga2V5d29yZDogJ25vbmNlJywgdmFsdWU6IDAgfSk7XG4gICAgICBjb25zdCB0eDEgPSBhd2FpdCB0MS5idWlsZCgpO1xuXG4gICAgICBjb25zdCB0MiA9IGZhY3RvcnkuZ2V0VHJhbnNmZXJCdWlsZGVyKCkgYXMgVHJhbnNmZXJCdWlsZGVyO1xuICAgICAgdDIuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyB9KVxuICAgICAgICAudG8oeyBhZGRyZXNzOiB0bzIgfSlcbiAgICAgICAgLmFtb3VudChhbW91bnQyKVxuICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiB3ZXN0ZW5kQmxvY2suYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiAyNDAwIH0pXG4gICAgICAgIC5yZWZlcmVuY2VCbG9jayh3ZXN0ZW5kQmxvY2suaGFzaClcbiAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMCB9KTtcbiAgICAgIGNvbnN0IHR4MiA9IGF3YWl0IHQyLmJ1aWxkKCk7XG5cbiAgICAgIC8vIEV4dHJhY3QgY2FsbCBkYXRhIGZyb20gbGVnYWN5IHNpZ25pbmcgcGF5bG9hZCBmb3IgYmF0Y2ggY29uc3RydWN0aW9uLlxuICAgICAgLy8gTGVnYWN5IHRvQnJvYWRjYXN0Rm9ybWF0KCkgZm9yIHVuc2lnbmVkIHR4cyByZXR1cm5zIHRoZSBzaWduaW5nIHBheWxvYWRcbiAgICAgIC8vIHdoaWNoIHN0YXJ0cyB3aXRoIGEgY29tcGFjdC1sZW5ndGgtcHJlZml4ZWQgY2FsbC5cbiAgICAgIGZ1bmN0aW9uIGV4dHJhY3RDYWxsRnJvbVNpZ25pbmdQYXlsb2FkKHNpZ25pbmdQYXlsb2FkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBoZXhEYXRhID0gc2lnbmluZ1BheWxvYWQuc3RhcnRzV2l0aCgnMHgnKSA/IHNpZ25pbmdQYXlsb2FkLnNsaWNlKDIpIDogc2lnbmluZ1BheWxvYWQ7XG4gICAgICAgIGNvbnN0IGJ5dGVzID0gQnVmZmVyLmZyb20oaGV4RGF0YSwgJ2hleCcpO1xuICAgICAgICAvLyBEZWNvZGUgY29tcGFjdCBsZW5ndGggcHJlZml4IHRvIGZpbmQgd2hlcmUgY2FsbCBkYXRhIGVuZHNcbiAgICAgICAgY29uc3QgbW9kZSA9IGJ5dGVzWzBdICYgMGIxMTtcbiAgICAgICAgbGV0IGNhbGxMZW5ndGg6IG51bWJlcjtcbiAgICAgICAgbGV0IG9mZnNldDogbnVtYmVyO1xuICAgICAgICBpZiAobW9kZSA9PT0gMGIwMCkge1xuICAgICAgICAgIGNhbGxMZW5ndGggPSBieXRlc1swXSA+PiAyO1xuICAgICAgICAgIG9mZnNldCA9IDE7XG4gICAgICAgIH0gZWxzZSBpZiAobW9kZSA9PT0gMGIwMSkge1xuICAgICAgICAgIGNhbGxMZW5ndGggPSAoYnl0ZXNbMF0gfCAoYnl0ZXNbMV0gPDwgOCkpID4+IDI7XG4gICAgICAgICAgb2Zmc2V0ID0gMjtcbiAgICAgICAgfSBlbHNlIGlmIChtb2RlID09PSAwYjEwKSB7XG4gICAgICAgICAgY2FsbExlbmd0aCA9IChieXRlc1swXSB8IChieXRlc1sxXSA8PCA4KSB8IChieXRlc1syXSA8PCAxNikgfCAoYnl0ZXNbM10gPDwgMjQpKSA+PiAyO1xuICAgICAgICAgIG9mZnNldCA9IDQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBjb21wYWN0IGxlbmd0aCBtb2RlJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcweCcgKyBieXRlcy5zbGljZShvZmZzZXQsIG9mZnNldCArIGNhbGxMZW5ndGgpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FsbDFIZXggPSBleHRyYWN0Q2FsbEZyb21TaWduaW5nUGF5bG9hZCh0eDEudG9Ccm9hZGNhc3RGb3JtYXQoKSk7XG4gICAgICBjb25zdCBjYWxsMkhleCA9IGV4dHJhY3RDYWxsRnJvbVNpZ25pbmdQYXlsb2FkKHR4Mi50b0Jyb2FkY2FzdEZvcm1hdCgpKTtcblxuICAgICAgY29uc3QgYmF0Y2hCdWlsZGVyID0gZmFjdG9yeS5nZXRCYXRjaFRyYW5zYWN0aW9uQnVpbGRlcigpO1xuICAgICAgYmF0Y2hCdWlsZGVyXG4gICAgICAgIC5zZW5kZXIoeyBhZGRyZXNzOiBhY2NvdW50cy5hY2NvdW50MS5hZGRyZXNzIH0pXG4gICAgICAgIC5jYWxscyhbY2FsbDFIZXgsIGNhbGwySGV4XSlcbiAgICAgICAgLmF0b21pYyh0cnVlKVxuICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiB3ZXN0ZW5kQmxvY2suYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiAyNDAwIH0pXG4gICAgICAgIC5yZWZlcmVuY2VCbG9jayh3ZXN0ZW5kQmxvY2suaGFzaClcbiAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMCB9KTtcblxuICAgICAgY29uc3QgbGVnYWN5VHggPSBhd2FpdCBiYXRjaEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUhleCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAnYmF0Y2gnLFxuICAgICAgICAgIGNhbGxzOiBbXG4gICAgICAgICAgICB7IHR5cGU6ICd0cmFuc2ZlcicsIHRvOiB0bzEsIGFtb3VudDogQmlnSW50KGFtb3VudDEpLCBrZWVwQWxpdmU6IHRydWUgfSxcbiAgICAgICAgICAgIHsgdHlwZTogJ3RyYW5zZmVyJywgdG86IHRvMiwgYW1vdW50OiBCaWdJbnQoYW1vdW50MiksIGtlZXBBbGl2ZTogdHJ1ZSB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYXRvbWljOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgY29uc3Qgd2FzbUhleCA9ICcweCcgKyBCdWZmZXIuZnJvbSh3YXNtVHguc2lnbmFibGVQYXlsb2FkKCkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHdhc21IZXgsIHN0cmlwQ29tcGFjdFByZWZpeChsZWdhY3lIZXgpLCAnU2lnbmluZyBwYXlsb2FkIHNob3VsZCBtYXRjaCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwcm9kdWNlIGlkZW50aWNhbCBzaWduaW5nIHBheWxvYWQgZm9yIG5vbi1hdG9taWMgYmF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0byA9IGFjY291bnRzLmFjY291bnQyLmFkZHJlc3M7XG4gICAgICBjb25zdCBhbW91bnQgPSAnMTAwMDAwMDAwMDAwMCc7XG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeShjb2luKTtcblxuICAgICAgY29uc3QgdHJhbnNmZXJCdWlsZGVyID0gZmFjdG9yeS5nZXRUcmFuc2ZlckJ1aWxkZXIoKSBhcyBUcmFuc2ZlckJ1aWxkZXI7XG4gICAgICB0cmFuc2ZlckJ1aWxkZXJcbiAgICAgICAgLnNlbmRlcih7IGFkZHJlc3M6IGFjY291bnRzLmFjY291bnQxLmFkZHJlc3MgfSlcbiAgICAgICAgLnRvKHsgYWRkcmVzczogdG8gfSlcbiAgICAgICAgLmFtb3VudChhbW91bnQpXG4gICAgICAgIC52YWxpZGl0eSh7IGZpcnN0VmFsaWQ6IHdlc3RlbmRCbG9jay5ibG9ja051bWJlciwgbWF4RHVyYXRpb246IDI0MDAgfSlcbiAgICAgICAgLnJlZmVyZW5jZUJsb2NrKHdlc3RlbmRCbG9jay5oYXNoKVxuICAgICAgICAuc2VxdWVuY2VJZCh7IG5hbWU6ICdOb25jZScsIGtleXdvcmQ6ICdub25jZScsIHZhbHVlOiAwIH0pO1xuICAgICAgY29uc3QgdHJhbnNmZXJUeCA9IGF3YWl0IHRyYW5zZmVyQnVpbGRlci5idWlsZCgpO1xuXG4gICAgICBmdW5jdGlvbiBleHRyYWN0Q2FsbEZyb21TaWduaW5nUGF5bG9hZChzaWduaW5nUGF5bG9hZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgaGV4RGF0YSA9IHNpZ25pbmdQYXlsb2FkLnN0YXJ0c1dpdGgoJzB4JykgPyBzaWduaW5nUGF5bG9hZC5zbGljZSgyKSA6IHNpZ25pbmdQYXlsb2FkO1xuICAgICAgICBjb25zdCBieXRlcyA9IEJ1ZmZlci5mcm9tKGhleERhdGEsICdoZXgnKTtcbiAgICAgICAgY29uc3QgbW9kZSA9IGJ5dGVzWzBdICYgMGIxMTtcbiAgICAgICAgbGV0IGNhbGxMZW5ndGg6IG51bWJlcjtcbiAgICAgICAgbGV0IG9mZnNldDogbnVtYmVyO1xuICAgICAgICBpZiAobW9kZSA9PT0gMGIwMCkge1xuICAgICAgICAgIGNhbGxMZW5ndGggPSBieXRlc1swXSA+PiAyO1xuICAgICAgICAgIG9mZnNldCA9IDE7XG4gICAgICAgIH0gZWxzZSBpZiAobW9kZSA9PT0gMGIwMSkge1xuICAgICAgICAgIGNhbGxMZW5ndGggPSAoYnl0ZXNbMF0gfCAoYnl0ZXNbMV0gPDwgOCkpID4+IDI7XG4gICAgICAgICAgb2Zmc2V0ID0gMjtcbiAgICAgICAgfSBlbHNlIGlmIChtb2RlID09PSAwYjEwKSB7XG4gICAgICAgICAgY2FsbExlbmd0aCA9IChieXRlc1swXSB8IChieXRlc1sxXSA8PCA4KSB8IChieXRlc1syXSA8PCAxNikgfCAoYnl0ZXNbM10gPDwgMjQpKSA+PiAyO1xuICAgICAgICAgIG9mZnNldCA9IDQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBjb21wYWN0IGxlbmd0aCBtb2RlJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcweCcgKyBieXRlcy5zbGljZShvZmZzZXQsIG9mZnNldCArIGNhbGxMZW5ndGgpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2FsbEhleCA9IGV4dHJhY3RDYWxsRnJvbVNpZ25pbmdQYXlsb2FkKHRyYW5zZmVyVHgudG9Ccm9hZGNhc3RGb3JtYXQoKSk7XG5cbiAgICAgIGNvbnN0IGJhdGNoQnVpbGRlciA9IGZhY3RvcnkuZ2V0QmF0Y2hUcmFuc2FjdGlvbkJ1aWxkZXIoKTtcbiAgICAgIGJhdGNoQnVpbGRlclxuICAgICAgICAuc2VuZGVyKHsgYWRkcmVzczogYWNjb3VudHMuYWNjb3VudDEuYWRkcmVzcyB9KVxuICAgICAgICAuY2FsbHMoW2NhbGxIZXhdKVxuICAgICAgICAuYXRvbWljKGZhbHNlKVxuICAgICAgICAudmFsaWRpdHkoeyBmaXJzdFZhbGlkOiB3ZXN0ZW5kQmxvY2suYmxvY2tOdW1iZXIsIG1heER1cmF0aW9uOiAyNDAwIH0pXG4gICAgICAgIC5yZWZlcmVuY2VCbG9jayh3ZXN0ZW5kQmxvY2suaGFzaClcbiAgICAgICAgLnNlcXVlbmNlSWQoeyBuYW1lOiAnTm9uY2UnLCBrZXl3b3JkOiAnbm9uY2UnLCB2YWx1ZTogMCB9KTtcblxuICAgICAgY29uc3QgbGVnYWN5VHggPSBhd2FpdCBiYXRjaEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGNvbnN0IGxlZ2FjeUhleCA9IGxlZ2FjeVR4LnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG5cbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAnYmF0Y2gnLFxuICAgICAgICAgIGNhbGxzOiBbeyB0eXBlOiAndHJhbnNmZXInLCB0bywgYW1vdW50OiBCaWdJbnQoYW1vdW50KSwga2VlcEFsaXZlOiB0cnVlIH1dLFxuICAgICAgICAgIGF0b21pYzogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIGNyZWF0ZVdhc21Db250ZXh0KClcbiAgICAgICk7XG4gICAgICBjb25zdCB3YXNtSGV4ID0gJzB4JyArIEJ1ZmZlci5mcm9tKHdhc21UeC5zaWduYWJsZVBheWxvYWQoKSkudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwod2FzbUhleCwgc3RyaXBDb21wYWN0UHJlZml4KGxlZ2FjeUhleCksICdTaWduaW5nIHBheWxvYWQgc2hvdWxkIG1hdGNoJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBJbnRlbnQtYmFzZWQgVHJhbnNhY3Rpb24gQnVpbGRpbmcgKHNhbml0eSBjaGVja3MpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICBkZXNjcmliZSgnSW50ZW50LWJhc2VkIFRyYW5zYWN0aW9uIEJ1aWxkaW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgYnVpbGQgdHJhbnNmZXIgZnJvbSBpbnRlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKFxuICAgICAgICB7IHR5cGU6ICd0cmFuc2ZlcicsIHRvOiBhY2NvdW50cy5hY2NvdW50Mi5hZGRyZXNzLCBhbW91bnQ6IDEwMDAwMDAwMDAwMDBuLCBrZWVwQWxpdmU6IHRydWUgfSxcbiAgICAgICAgY3JlYXRlV2FzbUNvbnRleHQoKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWQgPSB3YXNtVHgudG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIGFzc2VydChzZXJpYWxpemVkLnN0YXJ0c1dpdGgoJzB4JyksICdTaG91bGQgYmUgaGV4IGVuY29kZWQnKTtcbiAgICAgIGFzc2VydChzZXJpYWxpemVkLmxlbmd0aCA+IDEwLCAnU2hvdWxkIGhhdmUgY29udGVudCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBzdGFrZSBmcm9tIGludGVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHsgdHlwZTogJ3N0YWtlJywgYW1vdW50OiA1MDAwMDAwMDAwMDAwbiwgcGF5ZWU6IHsgdHlwZTogJ3N0YWtlZCcgfSB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgYXNzZXJ0KHdhc21UeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnN0YXJ0c1dpdGgoJzB4JykpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCB3aXRoZHJhd1VuYm9uZGVkIGZyb20gaW50ZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FzbVR4ID0gYnVpbGRUcmFuc2FjdGlvbih7IHR5cGU6ICd3aXRoZHJhd1VuYm9uZGVkJywgc2xhc2hpbmdTcGFuczogMCB9LCBjcmVhdGVXYXNtQ29udGV4dCgpKTtcbiAgICAgIGFzc2VydCh3YXNtVHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zdGFydHNXaXRoKCcweCcpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgY2hpbGwgZnJvbSBpbnRlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKHsgdHlwZTogJ2NoaWxsJyB9LCBjcmVhdGVXYXNtQ29udGV4dCgpKTtcbiAgICAgIGFzc2VydCh3YXNtVHgudG9Ccm9hZGNhc3RGb3JtYXQoKS5zdGFydHNXaXRoKCcweCcpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgYWRkUHJveHkgZnJvbSBpbnRlbnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB3YXNtVHggPSBidWlsZFRyYW5zYWN0aW9uKFxuICAgICAgICB7IHR5cGU6ICdhZGRQcm94eScsIGRlbGVnYXRlOiBhY2NvdW50cy5hY2NvdW50Mi5hZGRyZXNzLCBwcm94eVR5cGU6ICdBbnknLCBkZWxheTogMCB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgYXNzZXJ0KHdhc21UeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnN0YXJ0c1dpdGgoJzB4JykpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBiYXRjaCBmcm9tIGludGVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHdhc21UeCA9IGJ1aWxkVHJhbnNhY3Rpb24oXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiAnYmF0Y2gnLFxuICAgICAgICAgIGNhbGxzOiBbXG4gICAgICAgICAgICB7IHR5cGU6ICd0cmFuc2ZlcicsIHRvOiBhY2NvdW50cy5hY2NvdW50Mi5hZGRyZXNzLCBhbW91bnQ6IDEwMDAwMDAwMDAwMDBuLCBrZWVwQWxpdmU6IHRydWUgfSxcbiAgICAgICAgICAgIHsgdHlwZTogJ2NoaWxsJyB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYXRvbWljOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBjcmVhdGVXYXNtQ29udGV4dCgpXG4gICAgICApO1xuICAgICAgYXNzZXJ0KHdhc21UeC50b0Jyb2FkY2FzdEZvcm1hdCgpLnN0YXJ0c1dpdGgoJzB4JykpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|