@bitgo-beta/sdk-coin-flrp 1.0.1-beta.8 → 1.0.1-beta.80
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/flrp.d.ts +82 -61
- package/dist/src/flrp.d.ts.map +1 -1
- package/dist/src/flrp.js +293 -134
- package/dist/src/lib/atomicTransactionBuilder.d.ts +42 -6
- package/dist/src/lib/atomicTransactionBuilder.d.ts.map +1 -1
- package/dist/src/lib/atomicTransactionBuilder.js +233 -29
- package/dist/src/lib/constants.d.ts +160 -1
- package/dist/src/lib/constants.d.ts.map +1 -1
- package/dist/src/lib/constants.js +213 -3
- package/dist/src/lib/delegatorTxBuilder.d.ts +58 -0
- package/dist/src/lib/delegatorTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/delegatorTxBuilder.js +224 -0
- package/dist/src/lib/exportInCTxBuilder.d.ts +1 -1
- package/dist/src/lib/exportInCTxBuilder.d.ts.map +1 -1
- package/dist/src/lib/exportInCTxBuilder.js +46 -17
- package/dist/src/lib/exportInPTxBuilder.d.ts +1 -1
- package/dist/src/lib/exportInPTxBuilder.d.ts.map +1 -1
- package/dist/src/lib/exportInPTxBuilder.js +70 -6
- package/dist/src/lib/iface.d.ts +52 -1
- package/dist/src/lib/iface.d.ts.map +1 -1
- package/dist/src/lib/iface.js +1 -1
- package/dist/src/lib/importInCTxBuilder.d.ts +67 -0
- package/dist/src/lib/importInCTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/importInCTxBuilder.js +403 -0
- package/dist/src/lib/importInPTxBuilder.d.ts +73 -0
- package/dist/src/lib/importInPTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/importInPTxBuilder.js +464 -0
- package/dist/src/lib/index.d.ts +7 -0
- package/dist/src/lib/index.d.ts.map +1 -1
- package/dist/src/lib/index.js +15 -2
- package/dist/src/lib/keyPair.d.ts.map +1 -1
- package/dist/src/lib/keyPair.js +4 -6
- package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts +81 -0
- package/dist/src/lib/permissionlessValidatorTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/permissionlessValidatorTxBuilder.js +248 -0
- package/dist/src/lib/transaction.d.ts +111 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +322 -0
- package/dist/src/lib/transactionBuilder.d.ts +85 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +167 -0
- package/dist/src/lib/transactionBuilderFactory.d.ts +37 -0
- package/dist/src/lib/transactionBuilderFactory.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilderFactory.js +91 -0
- package/dist/src/lib/types.d.ts +78 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/dist/src/lib/types.js +5 -0
- package/dist/src/lib/utils.d.ts +59 -0
- package/dist/src/lib/utils.d.ts.map +1 -1
- package/dist/src/lib/utils.js +160 -52
- package/dist/src/lib/validatorTxBuilder.d.ts +40 -0
- package/dist/src/lib/validatorTxBuilder.d.ts.map +1 -0
- package/dist/src/lib/validatorTxBuilder.js +180 -0
- package/dist/test/unit/delegatorTxBuilder.test.d.ts +2 -0
- package/dist/test/unit/delegatorTxBuilder.test.d.ts.map +1 -0
- package/dist/test/unit/delegatorTxBuilder.test.js +233 -0
- package/dist/test/unit/lib/atomicTransactionBuilder.js +37 -11
- package/dist/test/unit/lib/exportInCTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/exportInCTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/exportInCTxBuilder.js +584 -0
- package/dist/test/unit/lib/exportInPTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/exportInPTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/exportInPTxBuilder.js +377 -0
- package/dist/test/unit/lib/importInCTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/importInCTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/importInCTxBuilder.js +257 -0
- package/dist/test/unit/lib/importInPTxBuilder.d.ts +2 -0
- package/dist/test/unit/lib/importInPTxBuilder.d.ts.map +1 -0
- package/dist/test/unit/lib/importInPTxBuilder.js +500 -0
- package/dist/test/unit/lib/transaction.d.ts +2 -0
- package/dist/test/unit/lib/transaction.d.ts.map +1 -0
- package/dist/test/unit/lib/transaction.js +460 -0
- package/dist/test/unit/lib/utils.js +55 -1
- package/dist/test/unit/permissionlessValidatorTxBuilder.test.d.ts +2 -0
- package/dist/test/unit/permissionlessValidatorTxBuilder.test.d.ts.map +1 -0
- package/dist/test/unit/permissionlessValidatorTxBuilder.test.js +271 -0
- package/dist/test/unit/transactionBuilder.test.d.ts +2 -0
- package/dist/test/unit/transactionBuilder.test.d.ts.map +1 -0
- package/dist/test/unit/transactionBuilder.test.js +114 -0
- package/dist/test/unit/validatorTxBuilder.test.d.ts +2 -0
- package/dist/test/unit/validatorTxBuilder.test.d.ts.map +1 -0
- package/dist/test/unit/validatorTxBuilder.test.js +293 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/.eslintignore +0 -5
- package/.eslintrc.json +0 -7
- package/.mocharc.yml +0 -8
- package/CHANGELOG.md +0 -0
- package/dist/test/unit/lib/exportTxBuilder.d.ts +0 -2
- package/dist/test/unit/lib/exportTxBuilder.d.ts.map +0 -1
- package/dist/test/unit/lib/exportTxBuilder.js +0 -45
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const statics_1 = require("@bitgo-beta/statics");
|
|
37
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
38
|
+
const assert = __importStar(require("assert"));
|
|
39
|
+
const transaction_1 = require("../../../src/lib/transaction");
|
|
40
|
+
const keyPair_1 = require("../../../src/lib/keyPair");
|
|
41
|
+
describe('FLRP Transaction', function () {
|
|
42
|
+
let transaction;
|
|
43
|
+
const coinConfig = statics_1.coins.get('tflrp');
|
|
44
|
+
// Helper to create a mock transaction for testing
|
|
45
|
+
const createMockTx = () => ({ test: 'transaction' });
|
|
46
|
+
beforeEach(function () {
|
|
47
|
+
transaction = new transaction_1.Transaction(coinConfig);
|
|
48
|
+
});
|
|
49
|
+
describe('Constructor', function () {
|
|
50
|
+
it('should initialize with correct network configuration', function () {
|
|
51
|
+
assert.strictEqual(transaction._assetId, 'FLR');
|
|
52
|
+
assert.strictEqual(transaction._blockchainID, '11111111111111111111111111111111LpoYY');
|
|
53
|
+
assert.strictEqual(transaction._networkID, 114);
|
|
54
|
+
assert.strictEqual(transaction._threshold, 2);
|
|
55
|
+
assert.strictEqual(transaction._locktime, BigInt(0));
|
|
56
|
+
});
|
|
57
|
+
it('should initialize empty arrays and default values', function () {
|
|
58
|
+
assert.deepStrictEqual(transaction._fromAddresses, []);
|
|
59
|
+
assert.deepStrictEqual(transaction._rewardAddresses, []);
|
|
60
|
+
assert.deepStrictEqual(transaction._utxos, []);
|
|
61
|
+
assert.deepStrictEqual(transaction._fee, {});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('Transaction Type Management', function () {
|
|
65
|
+
it('should set supported transaction types', function () {
|
|
66
|
+
const supportedTypes = [
|
|
67
|
+
sdk_core_1.TransactionType.Export,
|
|
68
|
+
sdk_core_1.TransactionType.Import,
|
|
69
|
+
sdk_core_1.TransactionType.AddValidator,
|
|
70
|
+
sdk_core_1.TransactionType.AddDelegator,
|
|
71
|
+
sdk_core_1.TransactionType.AddPermissionlessValidator,
|
|
72
|
+
sdk_core_1.TransactionType.AddPermissionlessDelegator,
|
|
73
|
+
];
|
|
74
|
+
supportedTypes.forEach((type) => {
|
|
75
|
+
assert.doesNotThrow(() => {
|
|
76
|
+
transaction.setTransactionType(type);
|
|
77
|
+
assert.strictEqual(transaction._type, type);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
it('should throw error for unsupported transaction types', function () {
|
|
82
|
+
assert.throws(() => {
|
|
83
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Send);
|
|
84
|
+
}, /Transaction type .* is not supported/);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('Getters', function () {
|
|
88
|
+
it('should return correct flareTransaction', function () {
|
|
89
|
+
const mockTx = createMockTx();
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
91
|
+
transaction.setTransaction(mockTx);
|
|
92
|
+
assert.strictEqual(transaction.flareTransaction, mockTx);
|
|
93
|
+
});
|
|
94
|
+
it('should return empty signature array when no credentials', function () {
|
|
95
|
+
assert.deepStrictEqual(transaction.signature, []);
|
|
96
|
+
});
|
|
97
|
+
it('should return empty credentials array', function () {
|
|
98
|
+
assert.deepStrictEqual(transaction.credentials, []);
|
|
99
|
+
});
|
|
100
|
+
it('should return false for hasCredentials when no credentials', function () {
|
|
101
|
+
assert.strictEqual(transaction.hasCredentials, false);
|
|
102
|
+
});
|
|
103
|
+
it('should return placeholder ID when no transaction set', function () {
|
|
104
|
+
// This should throw error when no transaction is set
|
|
105
|
+
assert.throws(() => {
|
|
106
|
+
transaction.id;
|
|
107
|
+
}, sdk_core_1.InvalidTransactionError);
|
|
108
|
+
});
|
|
109
|
+
it('should return placeholder signablePayload when no transaction set', function () {
|
|
110
|
+
// This should throw error when no transaction is set
|
|
111
|
+
assert.throws(() => {
|
|
112
|
+
void transaction.signablePayload;
|
|
113
|
+
}, sdk_core_1.InvalidTransactionError);
|
|
114
|
+
});
|
|
115
|
+
it('should return formatted fromAddresses', function () {
|
|
116
|
+
transaction._fromAddresses = ['address1', 'address2'];
|
|
117
|
+
const addresses = transaction.fromAddresses;
|
|
118
|
+
assert.deepStrictEqual(addresses, ['address1', 'address2']);
|
|
119
|
+
});
|
|
120
|
+
it('should return formatted rewardAddresses', function () {
|
|
121
|
+
transaction._rewardAddresses = ['reward1', 'reward2'];
|
|
122
|
+
const addresses = transaction.rewardAddresses;
|
|
123
|
+
assert.deepStrictEqual(addresses, ['reward1', 'reward2']);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('Transaction Outputs', function () {
|
|
127
|
+
beforeEach(function () {
|
|
128
|
+
transaction._nodeID = 'test-node-id';
|
|
129
|
+
transaction._stakeAmount = BigInt('1000000000000000'); // 1M FLR
|
|
130
|
+
});
|
|
131
|
+
it('should return empty outputs for Export type', function () {
|
|
132
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Export);
|
|
133
|
+
const outputs = transaction.outputs;
|
|
134
|
+
assert.deepStrictEqual(outputs, []);
|
|
135
|
+
});
|
|
136
|
+
it('should return empty outputs for Import type', function () {
|
|
137
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Import);
|
|
138
|
+
const outputs = transaction.outputs;
|
|
139
|
+
assert.deepStrictEqual(outputs, []);
|
|
140
|
+
});
|
|
141
|
+
it('should return staking outputs for AddValidator type', function () {
|
|
142
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddValidator);
|
|
143
|
+
const outputs = transaction.outputs;
|
|
144
|
+
assert.strictEqual(outputs.length, 1);
|
|
145
|
+
assert.strictEqual(outputs[0].address, 'test-node-id');
|
|
146
|
+
assert.strictEqual(outputs[0].value, '1000000000000000');
|
|
147
|
+
});
|
|
148
|
+
it('should return staking outputs for AddPermissionlessValidator type', function () {
|
|
149
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddPermissionlessValidator);
|
|
150
|
+
const outputs = transaction.outputs;
|
|
151
|
+
assert.strictEqual(outputs.length, 1);
|
|
152
|
+
assert.strictEqual(outputs[0].address, 'test-node-id');
|
|
153
|
+
assert.strictEqual(outputs[0].value, '1000000000000000');
|
|
154
|
+
});
|
|
155
|
+
it('should return staking outputs for AddDelegator type', function () {
|
|
156
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddDelegator);
|
|
157
|
+
const outputs = transaction.outputs;
|
|
158
|
+
assert.strictEqual(outputs.length, 1);
|
|
159
|
+
assert.strictEqual(outputs[0].address, 'test-node-id');
|
|
160
|
+
assert.strictEqual(outputs[0].value, '1000000000000000');
|
|
161
|
+
});
|
|
162
|
+
it('should return staking outputs for AddPermissionlessDelegator type', function () {
|
|
163
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddPermissionlessDelegator);
|
|
164
|
+
const outputs = transaction.outputs;
|
|
165
|
+
assert.strictEqual(outputs.length, 1);
|
|
166
|
+
assert.strictEqual(outputs[0].address, 'test-node-id');
|
|
167
|
+
assert.strictEqual(outputs[0].value, '1000000000000000');
|
|
168
|
+
});
|
|
169
|
+
it('should return empty outputs for unknown type', function () {
|
|
170
|
+
// Don't set type, should default to empty
|
|
171
|
+
const outputs = transaction.outputs;
|
|
172
|
+
assert.deepStrictEqual(outputs, []);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe('Transaction Inputs', function () {
|
|
176
|
+
it('should return inputs from UTXOs', function () {
|
|
177
|
+
transaction._utxos = [
|
|
178
|
+
{
|
|
179
|
+
outputID: 1,
|
|
180
|
+
amount: '1000000',
|
|
181
|
+
txid: 'test-txid-1',
|
|
182
|
+
outputidx: '0',
|
|
183
|
+
threshold: 2,
|
|
184
|
+
addresses: ['addr1', 'addr2'],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
outputID: 2,
|
|
188
|
+
amount: '2000000',
|
|
189
|
+
txid: 'test-txid-2',
|
|
190
|
+
outputidx: '1',
|
|
191
|
+
threshold: 2,
|
|
192
|
+
addresses: ['addr3', 'addr4'],
|
|
193
|
+
},
|
|
194
|
+
];
|
|
195
|
+
transaction._fromAddresses = ['addr1', 'addr2', 'addr3', 'addr4'];
|
|
196
|
+
const inputs = transaction.inputs;
|
|
197
|
+
assert.strictEqual(inputs.length, 2);
|
|
198
|
+
assert.strictEqual(inputs[0].id, 'test-txid-1:0');
|
|
199
|
+
assert.strictEqual(inputs[0].value, '1000000');
|
|
200
|
+
assert.strictEqual(inputs[0].address, 'addr1~addr2~addr3~addr4');
|
|
201
|
+
assert.strictEqual(inputs[1].id, 'test-txid-2:1');
|
|
202
|
+
assert.strictEqual(inputs[1].value, '2000000');
|
|
203
|
+
});
|
|
204
|
+
it('should return empty inputs when no UTXOs', function () {
|
|
205
|
+
const inputs = transaction.inputs;
|
|
206
|
+
assert.deepStrictEqual(inputs, []);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
describe('Change Outputs', function () {
|
|
210
|
+
it('should return empty change outputs', function () {
|
|
211
|
+
const changeOutputs = transaction.changeOutputs;
|
|
212
|
+
assert.deepStrictEqual(changeOutputs, []);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('Fee Handling', function () {
|
|
216
|
+
it('should return default fee when no fee set', function () {
|
|
217
|
+
const fee = transaction.fee;
|
|
218
|
+
assert.deepStrictEqual(fee, { fee: '0' });
|
|
219
|
+
});
|
|
220
|
+
it('should return custom fee when set', function () {
|
|
221
|
+
transaction._fee = { fee: '1000000' };
|
|
222
|
+
const fee = transaction.fee;
|
|
223
|
+
assert.deepStrictEqual(fee, { fee: '1000000' });
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
describe('Signing', function () {
|
|
227
|
+
let keyPair;
|
|
228
|
+
beforeEach(function () {
|
|
229
|
+
// Create a test key pair with a private key
|
|
230
|
+
keyPair = new keyPair_1.KeyPair({ prv: '01'.repeat(32) });
|
|
231
|
+
});
|
|
232
|
+
it('should throw error when no private key', async function () {
|
|
233
|
+
const emptyKeyPair = new keyPair_1.KeyPair();
|
|
234
|
+
await assert.rejects(async () => {
|
|
235
|
+
await transaction.sign(emptyKeyPair);
|
|
236
|
+
}, sdk_core_1.InvalidTransactionError); // Will throw InvalidTransactionError for empty transaction first
|
|
237
|
+
});
|
|
238
|
+
it('should throw error when no transaction to sign', async function () {
|
|
239
|
+
await assert.rejects(async () => {
|
|
240
|
+
await transaction.sign(keyPair);
|
|
241
|
+
}, sdk_core_1.InvalidTransactionError);
|
|
242
|
+
});
|
|
243
|
+
it('should throw error for FlareJS signing not implemented', async function () {
|
|
244
|
+
// Set a mock transaction and mock credentials to pass validation
|
|
245
|
+
const mockTx = createMockTx();
|
|
246
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
247
|
+
transaction.setTransaction(mockTx);
|
|
248
|
+
// Mock hasCredentials to return true
|
|
249
|
+
Object.defineProperty(transaction, 'hasCredentials', {
|
|
250
|
+
get: () => true,
|
|
251
|
+
});
|
|
252
|
+
await assert.rejects(async () => {
|
|
253
|
+
await transaction.sign(keyPair);
|
|
254
|
+
}, /FlareJS signing not yet implemented/);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
describe('Serialization', function () {
|
|
258
|
+
it('should throw error for toBroadcastFormat when no transaction', function () {
|
|
259
|
+
assert.throws(() => {
|
|
260
|
+
transaction.toBroadcastFormat();
|
|
261
|
+
}, sdk_core_1.InvalidTransactionError);
|
|
262
|
+
});
|
|
263
|
+
it('should return placeholder for toBroadcastFormat when transaction set', function () {
|
|
264
|
+
const mockTx = createMockTx();
|
|
265
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
266
|
+
transaction.setTransaction(mockTx);
|
|
267
|
+
const broadcastFormat = transaction.toBroadcastFormat();
|
|
268
|
+
assert.strictEqual(broadcastFormat, 'flare-tx-hex-placeholder');
|
|
269
|
+
});
|
|
270
|
+
it('should throw error for toJson when no transaction', function () {
|
|
271
|
+
assert.throws(() => {
|
|
272
|
+
transaction.toJson();
|
|
273
|
+
}, sdk_core_1.InvalidTransactionError);
|
|
274
|
+
});
|
|
275
|
+
it('should return transaction data for toJson when transaction set', function () {
|
|
276
|
+
const mockTx = createMockTx();
|
|
277
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
278
|
+
transaction.setTransaction(mockTx);
|
|
279
|
+
transaction._fromAddresses = ['addr1'];
|
|
280
|
+
transaction._threshold = 2;
|
|
281
|
+
transaction._locktime = BigInt(100);
|
|
282
|
+
const jsonData = transaction.toJson();
|
|
283
|
+
assert.strictEqual(jsonData.id, 'flare-transaction-id-placeholder');
|
|
284
|
+
assert.deepStrictEqual(jsonData.fromAddresses, ['addr1']);
|
|
285
|
+
assert.strictEqual(jsonData.threshold, 2);
|
|
286
|
+
assert.strictEqual(jsonData.locktime, '100');
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
describe('Cross-chain Properties', function () {
|
|
290
|
+
it('should identify Export as cross-chain transaction', function () {
|
|
291
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Export);
|
|
292
|
+
assert.strictEqual(transaction.isTransactionForCChain, true);
|
|
293
|
+
});
|
|
294
|
+
it('should identify Import as cross-chain transaction', function () {
|
|
295
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Import);
|
|
296
|
+
assert.strictEqual(transaction.isTransactionForCChain, true);
|
|
297
|
+
});
|
|
298
|
+
it('should identify AddValidator as non-cross-chain transaction', function () {
|
|
299
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddValidator);
|
|
300
|
+
assert.strictEqual(transaction.isTransactionForCChain, false);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
describe('Transaction Explanation', function () {
|
|
304
|
+
beforeEach(function () {
|
|
305
|
+
const mockTx = createMockTx();
|
|
306
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
307
|
+
transaction.setTransaction(mockTx);
|
|
308
|
+
transaction._fromAddresses = ['test-address'];
|
|
309
|
+
transaction._fee = { fee: '1000000' };
|
|
310
|
+
});
|
|
311
|
+
it('should explain a basic transaction', function () {
|
|
312
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Export);
|
|
313
|
+
const explanation = transaction.explainTransaction();
|
|
314
|
+
assert.ok(explanation.displayOrder);
|
|
315
|
+
assert.ok(Array.isArray(explanation.displayOrder));
|
|
316
|
+
assert.strictEqual(explanation.id, 'flare-transaction-id-placeholder');
|
|
317
|
+
assert.deepStrictEqual(explanation.fee, { fee: '1000000' });
|
|
318
|
+
assert.strictEqual(explanation.type, sdk_core_1.TransactionType.Export);
|
|
319
|
+
});
|
|
320
|
+
it('should include reward addresses for staking transactions', function () {
|
|
321
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddValidator);
|
|
322
|
+
transaction._rewardAddresses = ['reward-addr-1'];
|
|
323
|
+
const explanation = transaction.explainTransaction();
|
|
324
|
+
assert.ok(explanation.displayOrder);
|
|
325
|
+
assert.ok(explanation.displayOrder.includes('rewardAddresses'));
|
|
326
|
+
assert.deepStrictEqual(explanation.rewardAddresses, ['reward-addr-1']);
|
|
327
|
+
});
|
|
328
|
+
it('should include cross-chain information for export/import', function () {
|
|
329
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Export);
|
|
330
|
+
const explanation = transaction.explainTransaction();
|
|
331
|
+
assert.ok(explanation.displayOrder);
|
|
332
|
+
assert.ok(explanation.displayOrder.includes('sourceChain'));
|
|
333
|
+
assert.ok(explanation.displayOrder.includes('destinationChain'));
|
|
334
|
+
});
|
|
335
|
+
it('should calculate output amounts correctly', function () {
|
|
336
|
+
transaction._nodeID = 'test-node';
|
|
337
|
+
transaction._stakeAmount = BigInt('5000000000000000');
|
|
338
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.AddValidator);
|
|
339
|
+
const explanation = transaction.explainTransaction();
|
|
340
|
+
assert.strictEqual(explanation.outputAmount, '5000000000000000');
|
|
341
|
+
assert.strictEqual(explanation.changeAmount, '0');
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
describe('Signature Creation', function () {
|
|
345
|
+
it('should create signature placeholder', function () {
|
|
346
|
+
const mockPrivateKey = Buffer.from('1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', 'hex');
|
|
347
|
+
const mockTx = createMockTx();
|
|
348
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
349
|
+
transaction.setTransaction(mockTx);
|
|
350
|
+
const signature = transaction.createSignature(mockPrivateKey);
|
|
351
|
+
assert.ok(typeof signature === 'string');
|
|
352
|
+
assert.ok(signature.length > 0);
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
describe('Validation', function () {
|
|
356
|
+
it('should allow signing with valid key', function () {
|
|
357
|
+
const keyPair = new keyPair_1.KeyPair({ prv: '01'.repeat(32) });
|
|
358
|
+
const canSign = transaction.canSign({ key: keyPair });
|
|
359
|
+
assert.strictEqual(canSign, true);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
describe('Transaction Setting', function () {
|
|
363
|
+
it('should set transaction correctly', function () {
|
|
364
|
+
const mockTx = createMockTx();
|
|
365
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
366
|
+
transaction.setTransaction(mockTx);
|
|
367
|
+
// Can't directly access _flareTransaction (protected), but can test via getter
|
|
368
|
+
assert.strictEqual(transaction.flareTransaction, mockTx);
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
describe('Hex Conversion', function () {
|
|
372
|
+
it('should convert byte array to hex string', function () {
|
|
373
|
+
const byteArray = new Uint8Array([0x01, 0x23, 0xab, 0xcd]);
|
|
374
|
+
const hexString = transaction.toHexString(byteArray);
|
|
375
|
+
assert.strictEqual(hexString, '0123abcd');
|
|
376
|
+
});
|
|
377
|
+
it('should handle empty byte array', function () {
|
|
378
|
+
const byteArray = new Uint8Array([]);
|
|
379
|
+
const hexString = transaction.toHexString(byteArray);
|
|
380
|
+
assert.strictEqual(hexString, '');
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
describe('Memo Functionality', function () {
|
|
384
|
+
it('should initialize with empty memo', function () {
|
|
385
|
+
assert.strictEqual(transaction.hasMemo(), false);
|
|
386
|
+
assert.strictEqual(transaction.getMemoString(), '');
|
|
387
|
+
assert.deepStrictEqual(transaction.getMemoBytes(), new Uint8Array());
|
|
388
|
+
});
|
|
389
|
+
it('should set memo from string', function () {
|
|
390
|
+
const memoText = 'Test transaction memo';
|
|
391
|
+
transaction.setMemo(memoText);
|
|
392
|
+
assert.strictEqual(transaction.hasMemo(), true);
|
|
393
|
+
assert.strictEqual(transaction.getMemoString(), memoText);
|
|
394
|
+
assert.deepStrictEqual(transaction.getMemoBytes(), new TextEncoder().encode(memoText));
|
|
395
|
+
});
|
|
396
|
+
it('should set memo from JSON object', function () {
|
|
397
|
+
const memoObj = { user: 'alice', amount: 1000 };
|
|
398
|
+
transaction.setMemoData(memoObj);
|
|
399
|
+
assert.strictEqual(transaction.hasMemo(), true);
|
|
400
|
+
assert.strictEqual(transaction.getMemoString(), JSON.stringify(memoObj));
|
|
401
|
+
});
|
|
402
|
+
it('should set memo from bytes', function () {
|
|
403
|
+
const memoBytes = new TextEncoder().encode('Binary memo data');
|
|
404
|
+
transaction.setMemoData(memoBytes);
|
|
405
|
+
assert.strictEqual(transaction.hasMemo(), true);
|
|
406
|
+
assert.deepStrictEqual(transaction.getMemoBytes(), memoBytes);
|
|
407
|
+
assert.strictEqual(transaction.getMemoString(), 'Binary memo data');
|
|
408
|
+
});
|
|
409
|
+
it('should handle empty string memo', function () {
|
|
410
|
+
transaction.setMemo('');
|
|
411
|
+
assert.strictEqual(transaction.hasMemo(), false);
|
|
412
|
+
assert.strictEqual(transaction.getMemoString(), '');
|
|
413
|
+
});
|
|
414
|
+
it('should handle UTF-8 memo', function () {
|
|
415
|
+
const utf8Memo = 'Hello 世界 🌍 Flare!';
|
|
416
|
+
transaction.setMemo(utf8Memo);
|
|
417
|
+
assert.strictEqual(transaction.hasMemo(), true);
|
|
418
|
+
assert.strictEqual(transaction.getMemoString(), utf8Memo);
|
|
419
|
+
});
|
|
420
|
+
it('should include memo in transaction JSON when present', function () {
|
|
421
|
+
const memoText = 'Transaction metadata';
|
|
422
|
+
transaction.setMemo(memoText);
|
|
423
|
+
// Mock the FlareJS transaction
|
|
424
|
+
const mockTx = createMockTx();
|
|
425
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
426
|
+
transaction.setTransaction(mockTx);
|
|
427
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Export);
|
|
428
|
+
const txData = transaction.toJson();
|
|
429
|
+
assert.strictEqual(txData.memo, memoText);
|
|
430
|
+
});
|
|
431
|
+
it('should not include memo in JSON when empty', function () {
|
|
432
|
+
// Mock the FlareJS transaction
|
|
433
|
+
const mockTx = createMockTx();
|
|
434
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
435
|
+
transaction.setTransaction(mockTx);
|
|
436
|
+
transaction.setTransactionType(sdk_core_1.TransactionType.Export);
|
|
437
|
+
const txData = transaction.toJson();
|
|
438
|
+
assert.strictEqual(txData.memo, '');
|
|
439
|
+
});
|
|
440
|
+
it('should validate memo size limits', function () {
|
|
441
|
+
// Test large memo - this should be validated by utils
|
|
442
|
+
const largeMemo = 'x'.repeat(5000); // 5KB memo
|
|
443
|
+
transaction.setMemo(largeMemo);
|
|
444
|
+
assert.strictEqual(transaction.getMemoString(), largeMemo);
|
|
445
|
+
});
|
|
446
|
+
it('should handle special characters in memo', function () {
|
|
447
|
+
const specialMemo = 'Special chars: \n\t\r\0\x01\xff';
|
|
448
|
+
transaction.setMemo(specialMemo);
|
|
449
|
+
assert.strictEqual(transaction.getMemoString(), specialMemo);
|
|
450
|
+
});
|
|
451
|
+
it('should throw error for invalid memo format in setMemoData', function () {
|
|
452
|
+
// This should be tested in utils, but we can check basic behavior
|
|
453
|
+
assert.throws(() => {
|
|
454
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
455
|
+
transaction.setMemoData(123);
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
});
|
|
460
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90ZXN0L3VuaXQvbGliL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQTRDO0FBQzVDLG1EQUFnRjtBQUNoRiwrQ0FBaUM7QUFDakMsOERBQTJEO0FBQzNELHNEQUFtRDtBQU9uRCxRQUFRLENBQUMsa0JBQWtCLEVBQUU7SUFDM0IsSUFBSSxXQUF3QixDQUFDO0lBQzdCLE1BQU0sVUFBVSxHQUFHLGVBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFdEMsa0RBQWtEO0lBQ2xELE1BQU0sWUFBWSxHQUFHLEdBQVcsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQztJQUU3RCxVQUFVLENBQUM7UUFDVCxXQUFXLEdBQUcsSUFBSSx5QkFBVyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzVDLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGFBQWEsRUFBRTtRQUN0QixFQUFFLENBQUMsc0RBQXNELEVBQUU7WUFDekQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2hELE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSx1Q0FBdUMsQ0FBQyxDQUFDO1lBQ3ZGLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNoRCxNQUFNLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDOUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQyxD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TUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUU7Z0JBQ2pCLDhEQUE4RDtnQkFDOUQsV0FBVyxDQUFDLFdBQVcsQ0FBQyxHQUFVLENBQUMsQ0FBQztZQUN0QyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvaW5zIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblR5cGUsIEludmFsaWRUcmFuc2FjdGlvbkVycm9yIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBUcmFuc2FjdGlvbiB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWIvdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgS2V5UGFpciB9IGZyb20gJy4uLy4uLy4uL3NyYy9saWIva2V5UGFpcic7XG5cbi8vIE1vY2sgdHJhbnNhY3Rpb24gZm9yIHRlc3RpbmdcbmludGVyZmFjZSBNb2NrVHgge1xuICB0ZXN0OiBzdHJpbmc7XG59XG5cbmRlc2NyaWJlKCdGTFJQIFRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICBsZXQgdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uO1xuICBjb25zdCBjb2luQ29uZmlnID0gY29pbnMuZ2V0KCd0ZmxycCcpO1xuXG4gIC8vIEhlbHBlciB0byBjcmVhdGUgYSBtb2NrIHRyYW5zYWN0aW9uIGZvciB0ZXN0aW5nXG4gIGNvbnN0IGNyZWF0ZU1vY2tUeCA9ICgpOiBNb2NrVHggPT4gKHsgdGVzdDogJ3RyYW5zYWN0aW9uJyB9KTtcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICB0cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihjb2luQ29uZmlnKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0NvbnN0cnVjdG9yJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgaW5pdGlhbGl6ZSB3aXRoIGNvcnJlY3QgbmV0d29yayBjb25maWd1cmF0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLl9hc3NldElkLCAnRkxSJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uX2Jsb2NrY2hhaW5JRCwgJzExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExTHBvWVknKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5fbmV0d29ya0lELCAxMTQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLl90aHJlc2hvbGQsIDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLl9sb2NrdGltZSwgQmlnSW50KDApKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaW5pdGlhbGl6ZSBlbXB0eSBhcnJheXMgYW5kIGRlZmF1bHQgdmFsdWVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5fZnJvbUFkZHJlc3NlcywgW10pO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5fcmV3YXJkQWRkcmVzc2VzLCBbXSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLl91dHhvcywgW10pO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5fZmVlLCB7fSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUcmFuc2FjdGlvbiBUeXBlIE1hbmFnZW1lbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBzZXQgc3VwcG9ydGVkIHRyYW5zYWN0aW9uIHR5cGVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc3VwcG9ydGVkVHlwZXMgPSBbXG4gICAgICAgIFRyYW5zYWN0aW9uVHlwZS5FeHBvcnQsXG4gICAgICAgIFRyYW5zYWN0aW9uVHlwZS5JbXBvcnQsXG4gICAgICAgIFRyYW5zYWN0aW9uVHlwZS5BZGRWYWxpZGF0b3IsXG4gICAgICAgIFRyYW5zYWN0aW9uVHlwZS5BZGREZWxlZ2F0b3IsXG4gICAgICAgIFRyYW5zYWN0aW9uVHlwZS5BZGRQZXJtaXNzaW9ubGVzc1ZhbGlkYXRvcixcbiAgICAgICAgVHJhbnNhY3Rpb25UeXBlLkFkZFBlcm1pc3Npb25sZXNzRGVsZWdhdG9yLFxuICAgICAgXTtcblxuICAgICAgc3VwcG9ydGVkVHlwZXMuZm9yRWFjaCgodHlwZSkgPT4ge1xuICAgICAgICBhc3NlcnQuZG9lc05vdFRocm93KCgpID0+IHtcbiAgICAgICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUodHlwZSk7XG4gICAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLl90eXBlLCB0eXBlKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIHVuc3VwcG9ydGVkIHRyYW5zYWN0aW9uIHR5cGVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICB9LCAvVHJhbnNhY3Rpb24gdHlwZSAuKiBpcyBub3Qgc3VwcG9ydGVkLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZXR0ZXJzJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGNvcnJlY3QgZmxhcmVUcmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1vY2tUeCA9IGNyZWF0ZU1vY2tUeCgpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uKG1vY2tUeCBhcyBhbnkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmZsYXJlVHJhbnNhY3Rpb24sIG1vY2tUeCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBzaWduYXR1cmUgYXJyYXkgd2hlbiBubyBjcmVkZW50aWFscycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uc2lnbmF0dXJlLCBbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBjcmVkZW50aWFscyBhcnJheScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uY3JlZGVudGlhbHMsIFtdKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBoYXNDcmVkZW50aWFscyB3aGVuIG5vIGNyZWRlbnRpYWxzJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmhhc0NyZWRlbnRpYWxzLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBwbGFjZWhvbGRlciBJRCB3aGVuIG5vIHRyYW5zYWN0aW9uIHNldCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFRoaXMgc2hvdWxkIHRocm93IGVycm9yIHdoZW4gbm8gdHJhbnNhY3Rpb24gaXMgc2V0XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHtcbiAgICAgICAgdHJhbnNhY3Rpb24uaWQ7XG4gICAgICB9LCBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBwbGFjZWhvbGRlciBzaWduYWJsZVBheWxvYWQgd2hlbiBubyB0cmFuc2FjdGlvbiBzZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUaGlzIHNob3VsZCB0aHJvdyBlcnJvciB3aGVuIG5vIHRyYW5zYWN0aW9uIGlzIHNldFxuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICAgIHZvaWQgdHJhbnNhY3Rpb24uc2lnbmFibGVQYXlsb2FkO1xuICAgICAgfSwgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZm9ybWF0dGVkIGZyb21BZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5fZnJvbUFkZHJlc3NlcyA9IFsnYWRkcmVzczEnLCAnYWRkcmVzczInXTtcbiAgICAgIGNvbnN0IGFkZHJlc3NlcyA9IHRyYW5zYWN0aW9uLmZyb21BZGRyZXNzZXM7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGFkZHJlc3NlcywgWydhZGRyZXNzMScsICdhZGRyZXNzMiddKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZvcm1hdHRlZCByZXdhcmRBZGRyZXNzZXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5fcmV3YXJkQWRkcmVzc2VzID0gWydyZXdhcmQxJywgJ3Jld2FyZDInXTtcbiAgICAgIGNvbnN0IGFkZHJlc3NlcyA9IHRyYW5zYWN0aW9uLnJld2FyZEFkZHJlc3NlcztcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoYWRkcmVzc2VzLCBbJ3Jld2FyZDEnLCAncmV3YXJkMiddKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIE91dHB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5fbm9kZUlEID0gJ3Rlc3Qtbm9kZS1pZCc7XG4gICAgICB0cmFuc2FjdGlvbi5fc3Rha2VBbW91bnQgPSBCaWdJbnQoJzEwMDAwMDAwMDAwMDAwMDAnKTsgLy8gMU0gRkxSXG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBvdXRwdXRzIGZvciBFeHBvcnQgdHlwZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuRXhwb3J0KTtcbiAgICAgIGNvbnN0IG91dHB1dHMgPSB0cmFuc2FjdGlvbi5vdXRwdXRzO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChvdXRwdXRzLCBbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBvdXRwdXRzIGZvciBJbXBvcnQgdHlwZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuSW1wb3J0KTtcbiAgICAgIGNvbnN0IG91dHB1dHMgPSB0cmFuc2FjdGlvbi5vdXRwdXRzO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChvdXRwdXRzLCBbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBzdGFraW5nIG91dHB1dHMgZm9yIEFkZFZhbGlkYXRvciB0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5BZGRWYWxpZGF0b3IpO1xuICAgICAgY29uc3Qgb3V0cHV0cyA9IHRyYW5zYWN0aW9uLm91dHB1dHM7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3V0cHV0cy5sZW5ndGgsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG91dHB1dHNbMF0uYWRkcmVzcywgJ3Rlc3Qtbm9kZS1pZCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG91dHB1dHNbMF0udmFsdWUsICcxMDAwMDAwMDAwMDAwMDAwJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBzdGFraW5nIG91dHB1dHMgZm9yIEFkZFBlcm1pc3Npb25sZXNzVmFsaWRhdG9yIHR5cGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkFkZFBlcm1pc3Npb25sZXNzVmFsaWRhdG9yKTtcbiAgICAgIGNvbnN0IG91dHB1dHMgPSB0cmFuc2FjdGlvbi5vdXRwdXRzO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG91dHB1dHMubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvdXRwdXRzWzBdLmFkZHJlc3MsICd0ZXN0LW5vZGUtaWQnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvdXRwdXRzWzBdLnZhbHVlLCAnMTAwMDAwMDAwMDAwMDAwMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gc3Rha2luZyBvdXRwdXRzIGZvciBBZGREZWxlZ2F0b3IgdHlwZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuQWRkRGVsZWdhdG9yKTtcbiAgICAgIGNvbnN0IG91dHB1dHMgPSB0cmFuc2FjdGlvbi5vdXRwdXRzO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG91dHB1dHMubGVuZ3RoLCAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvdXRwdXRzWzBdLmFkZHJlc3MsICd0ZXN0LW5vZGUtaWQnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvdXRwdXRzWzBdLnZhbHVlLCAnMTAwMDAwMDAwMDAwMDAwMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gc3Rha2luZyBvdXRwdXRzIGZvciBBZGRQZXJtaXNzaW9ubGVzc0RlbGVnYXRvciB0eXBlJywgZnVuY3Rpb24gKCkge1xuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5BZGRQZXJtaXNzaW9ubGVzc0RlbGVnYXRvcik7XG4gICAgICBjb25zdCBvdXRwdXRzID0gdHJhbnNhY3Rpb24ub3V0cHV0cztcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChvdXRwdXRzLmxlbmd0aCwgMSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3V0cHV0c1swXS5hZGRyZXNzLCAndGVzdC1ub2RlLWlkJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwob3V0cHV0c1swXS52YWx1ZSwgJzEwMDAwMDAwMDAwMDAwMDAnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGVtcHR5IG91dHB1dHMgZm9yIHVua25vd24gdHlwZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIERvbid0IHNldCB0eXBlLCBzaG91bGQgZGVmYXVsdCB0byBlbXB0eVxuICAgICAgY29uc3Qgb3V0cHV0cyA9IHRyYW5zYWN0aW9uLm91dHB1dHM7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKG91dHB1dHMsIFtdKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIElucHV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBpbnB1dHMgZnJvbSBVVFhPcycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLl91dHhvcyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIG91dHB1dElEOiAxLFxuICAgICAgICAgIGFtb3VudDogJzEwMDAwMDAnLFxuICAgICAgICAgIHR4aWQ6ICd0ZXN0LXR4aWQtMScsXG4gICAgICAgICAgb3V0cHV0aWR4OiAnMCcsXG4gICAgICAgICAgdGhyZXNob2xkOiAyLFxuICAgICAgICAgIGFkZHJlc3NlczogWydhZGRyMScsICdhZGRyMiddLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgb3V0cHV0SUQ6IDIsXG4gICAgICAgICAgYW1vdW50OiAnMjAwMDAwMCcsXG4gICAgICAgICAgdHhpZDogJ3Rlc3QtdHhpZC0yJyxcbiAgICAgICAgICBvdXRwdXRpZHg6ICcxJyxcbiAgICAgICAgICB0aHJlc2hvbGQ6IDIsXG4gICAgICAgICAgYWRkcmVzc2VzOiBbJ2FkZHIzJywgJ2FkZHI0J10sXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgdHJhbnNhY3Rpb24uX2Zyb21BZGRyZXNzZXMgPSBbJ2FkZHIxJywgJ2FkZHIyJywgJ2FkZHIzJywgJ2FkZHI0J107XG5cbiAgICAgIGNvbnN0IGlucHV0cyA9IHRyYW5zYWN0aW9uLmlucHV0cztcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpbnB1dHMubGVuZ3RoLCAyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpbnB1dHNbMF0uaWQsICd0ZXN0LXR4aWQtMTowJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaW5wdXRzWzBdLnZhbHVlLCAnMTAwMDAwMCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlucHV0c1swXS5hZGRyZXNzLCAnYWRkcjF+YWRkcjJ+YWRkcjN+YWRkcjQnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpbnB1dHNbMV0uaWQsICd0ZXN0LXR4aWQtMjoxJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaW5wdXRzWzFdLnZhbHVlLCAnMjAwMDAwMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZW1wdHkgaW5wdXRzIHdoZW4gbm8gVVRYT3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBpbnB1dHMgPSB0cmFuc2FjdGlvbi5pbnB1dHM7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGlucHV0cywgW10pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ2hhbmdlIE91dHB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZW1wdHkgY2hhbmdlIG91dHB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjaGFuZ2VPdXRwdXRzID0gdHJhbnNhY3Rpb24uY2hhbmdlT3V0cHV0cztcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoY2hhbmdlT3V0cHV0cywgW10pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRmVlIEhhbmRsaW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGRlZmF1bHQgZmVlIHdoZW4gbm8gZmVlIHNldCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGZlZSA9IHRyYW5zYWN0aW9uLmZlZTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoZmVlLCB7IGZlZTogJzAnIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gY3VzdG9tIGZlZSB3aGVuIHNldCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLl9mZWUgPSB7IGZlZTogJzEwMDAwMDAnIH07XG4gICAgICBjb25zdCBmZWUgPSB0cmFuc2FjdGlvbi5mZWU7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGZlZSwgeyBmZWU6ICcxMDAwMDAwJyB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1NpZ25pbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGtleVBhaXI6IEtleVBhaXI7XG5cbiAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIENyZWF0ZSBhIHRlc3Qga2V5IHBhaXIgd2l0aCBhIHByaXZhdGUga2V5XG4gICAgICBrZXlQYWlyID0gbmV3IEtleVBhaXIoeyBwcnY6ICcwMScucmVwZWF0KDMyKSB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBubyBwcml2YXRlIGtleScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGVtcHR5S2V5UGFpciA9IG5ldyBLZXlQYWlyKCk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgdHJhbnNhY3Rpb24uc2lnbihlbXB0eUtleVBhaXIpO1xuICAgICAgfSwgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IpOyAvLyBXaWxsIHRocm93IEludmFsaWRUcmFuc2FjdGlvbkVycm9yIGZvciBlbXB0eSB0cmFuc2FjdGlvbiBmaXJzdFxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciB3aGVuIG5vIHRyYW5zYWN0aW9uIHRvIHNpZ24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRyYW5zYWN0aW9uLnNpZ24oa2V5UGFpcik7XG4gICAgICB9LCBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciBGbGFyZUpTIHNpZ25pbmcgbm90IGltcGxlbWVudGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gU2V0IGEgbW9jayB0cmFuc2FjdGlvbiBhbmQgbW9jayBjcmVkZW50aWFscyB0byBwYXNzIHZhbGlkYXRpb25cbiAgICAgIGNvbnN0IG1vY2tUeCA9IGNyZWF0ZU1vY2tUeCgpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uKG1vY2tUeCBhcyBhbnkpO1xuXG4gICAgICAvLyBNb2NrIGhhc0NyZWRlbnRpYWxzIHRvIHJldHVybiB0cnVlXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodHJhbnNhY3Rpb24sICdoYXNDcmVkZW50aWFscycsIHtcbiAgICAgICAgZ2V0OiAoKSA9PiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgdHJhbnNhY3Rpb24uc2lnbihrZXlQYWlyKTtcbiAgICAgIH0sIC9GbGFyZUpTIHNpZ25pbmcgbm90IHlldCBpbXBsZW1lbnRlZC8pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnU2VyaWFsaXphdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciB0b0Jyb2FkY2FzdEZvcm1hdCB3aGVuIG5vIHRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICAgIHRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICB9LCBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBwbGFjZWhvbGRlciBmb3IgdG9Ccm9hZGNhc3RGb3JtYXQgd2hlbiB0cmFuc2FjdGlvbiBzZXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrVHggPSBjcmVhdGVNb2NrVHgoKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvbihtb2NrVHggYXMgYW55KTtcbiAgICAgIGNvbnN0IGJyb2FkY2FzdEZvcm1hdCA9IHRyYW5zYWN0aW9uLnRvQnJvYWRjYXN0Rm9ybWF0KCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYnJvYWRjYXN0Rm9ybWF0LCAnZmxhcmUtdHgtaGV4LXBsYWNlaG9sZGVyJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGZvciB0b0pzb24gd2hlbiBubyB0cmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4ge1xuICAgICAgICB0cmFuc2FjdGlvbi50b0pzb24oKTtcbiAgICAgIH0sIEludmFsaWRUcmFuc2FjdGlvbkVycm9yKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRyYW5zYWN0aW9uIGRhdGEgZm9yIHRvSnNvbiB3aGVuIHRyYW5zYWN0aW9uIHNldCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1vY2tUeCA9IGNyZWF0ZU1vY2tUeCgpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uKG1vY2tUeCBhcyBhbnkpO1xuICAgICAgdHJhbnNhY3Rpb24uX2Zyb21BZGRyZXNzZXMgPSBbJ2FkZHIxJ107XG4gICAgICB0cmFuc2FjdGlvbi5fdGhyZXNob2xkID0gMjtcbiAgICAgIHRyYW5zYWN0aW9uLl9sb2NrdGltZSA9IEJpZ0ludCgxMDApO1xuXG4gICAgICBjb25zdCBqc29uRGF0YSA9IHRyYW5zYWN0aW9uLnRvSnNvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb25EYXRhLmlkLCAnZmxhcmUtdHJhbnNhY3Rpb24taWQtcGxhY2Vob2xkZXInKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoanNvbkRhdGEuZnJvbUFkZHJlc3NlcywgWydhZGRyMSddKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChqc29uRGF0YS50aHJlc2hvbGQsIDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGpzb25EYXRhLmxvY2t0aW1lLCAnMTAwJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdDcm9zcy1jaGFpbiBQcm9wZXJ0aWVzJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgaWRlbnRpZnkgRXhwb3J0IGFzIGNyb3NzLWNoYWluIHRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5FeHBvcnQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmlzVHJhbnNhY3Rpb25Gb3JDQ2hhaW4sIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBpZGVudGlmeSBJbXBvcnQgYXMgY3Jvc3MtY2hhaW4gdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkltcG9ydCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uaXNUcmFuc2FjdGlvbkZvckNDaGFpbiwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGlkZW50aWZ5IEFkZFZhbGlkYXRvciBhcyBub24tY3Jvc3MtY2hhaW4gdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkFkZFZhbGlkYXRvcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uaXNUcmFuc2FjdGlvbkZvckNDaGFpbiwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVHJhbnNhY3Rpb24gRXhwbGFuYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtb2NrVHggPSBjcmVhdGVNb2NrVHgoKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvbihtb2NrVHggYXMgYW55KTtcbiAgICAgIHRyYW5zYWN0aW9uLl9mcm9tQWRkcmVzc2VzID0gWyd0ZXN0LWFkZHJlc3MnXTtcbiAgICAgIHRyYW5zYWN0aW9uLl9mZWUgPSB7IGZlZTogJzEwMDAwMDAnIH07XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGV4cGxhaW4gYSBiYXNpYyB0cmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuRXhwb3J0KTtcblxuICAgICAgY29uc3QgZXhwbGFuYXRpb24gPSB0cmFuc2FjdGlvbi5leHBsYWluVHJhbnNhY3Rpb24oKTtcbiAgICAgIGFzc2VydC5vayhleHBsYW5hdGlvbi5kaXNwbGF5T3JkZXIpO1xuICAgICAgYXNzZXJ0Lm9rKEFycmF5LmlzQXJyYXkoZXhwbGFuYXRpb24uZGlzcGxheU9yZGVyKSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZXhwbGFuYXRpb24uaWQsICdmbGFyZS10cmFuc2FjdGlvbi1pZC1wbGFjZWhvbGRlcicpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChleHBsYW5hdGlvbi5mZWUsIHsgZmVlOiAnMTAwMDAwMCcgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZXhwbGFuYXRpb24udHlwZSwgVHJhbnNhY3Rpb25UeXBlLkV4cG9ydCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgcmV3YXJkIGFkZHJlc3NlcyBmb3Igc3Rha2luZyB0cmFuc2FjdGlvbnMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkFkZFZhbGlkYXRvcik7XG4gICAgICB0cmFuc2FjdGlvbi5fcmV3YXJkQWRkcmVzc2VzID0gWydyZXdhcmQtYWRkci0xJ107XG5cbiAgICAgIGNvbnN0IGV4cGxhbmF0aW9uID0gdHJhbnNhY3Rpb24uZXhwbGFpblRyYW5zYWN0aW9uKCk7XG4gICAgICBhc3NlcnQub2soZXhwbGFuYXRpb24uZGlzcGxheU9yZGVyKTtcbiAgICAgIGFzc2VydC5vayhleHBsYW5hdGlvbi5kaXNwbGF5T3JkZXIuaW5jbHVkZXMoJ3Jld2FyZEFkZHJlc3NlcycpKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoZXhwbGFuYXRpb24ucmV3YXJkQWRkcmVzc2VzLCBbJ3Jld2FyZC1hZGRyLTEnXSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGluY2x1ZGUgY3Jvc3MtY2hhaW4gaW5mb3JtYXRpb24gZm9yIGV4cG9ydC9pbXBvcnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkV4cG9ydCk7XG5cbiAgICAgIGNvbnN0IGV4cGxhbmF0aW9uID0gdHJhbnNhY3Rpb24uZXhwbGFpblRyYW5zYWN0aW9uKCk7XG4gICAgICBhc3NlcnQub2soZXhwbGFuYXRpb24uZGlzcGxheU9yZGVyKTtcbiAgICAgIGFzc2VydC5vayhleHBsYW5hdGlvbi5kaXNwbGF5T3JkZXIuaW5jbHVkZXMoJ3NvdXJjZUNoYWluJykpO1xuICAgICAgYXNzZXJ0Lm9rKGV4cGxhbmF0aW9uLmRpc3BsYXlPcmRlci5pbmNsdWRlcygnZGVzdGluYXRpb25DaGFpbicpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsY3VsYXRlIG91dHB1dCBhbW91bnRzIGNvcnJlY3RseScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRyYW5zYWN0aW9uLl9ub2RlSUQgPSAndGVzdC1ub2RlJztcbiAgICAgIHRyYW5zYWN0aW9uLl9zdGFrZUFtb3VudCA9IEJpZ0ludCgnNTAwMDAwMDAwMDAwMDAwMCcpO1xuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5BZGRWYWxpZGF0b3IpO1xuXG4gICAgICBjb25zdCBleHBsYW5hdGlvbiA9IHRyYW5zYWN0aW9uLmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGV4cGxhbmF0aW9uLm91dHB1dEFtb3VudCwgJzUwMDAwMDAwMDAwMDAwMDAnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChleHBsYW5hdGlvbi5jaGFuZ2VBbW91bnQsICcwJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTaWduYXR1cmUgQ3JlYXRpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgc2lnbmF0dXJlIHBsYWNlaG9sZGVyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja1ByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbSgnMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZicsICdoZXgnKTtcbiAgICAgIGNvbnN0IG1vY2tUeCA9IGNyZWF0ZU1vY2tUeCgpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIHRyYW5zYWN0aW9uLnNldFRyYW5zYWN0aW9uKG1vY2tUeCBhcyBhbnkpO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmUgPSB0cmFuc2FjdGlvbi5jcmVhdGVTaWduYXR1cmUobW9ja1ByaXZhdGVLZXkpO1xuICAgICAgYXNzZXJ0Lm9rKHR5cGVvZiBzaWduYXR1cmUgPT09ICdzdHJpbmcnKTtcbiAgICAgIGFzc2VydC5vayhzaWduYXR1cmUubGVuZ3RoID4gMCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWYWxpZGF0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgYWxsb3cgc2lnbmluZyB3aXRoIHZhbGlkIGtleScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGtleVBhaXIgPSBuZXcgS2V5UGFpcih7IHBydjogJzAxJy5yZXBlYXQoMzIpIH0pO1xuXG4gICAgICBjb25zdCBjYW5TaWduID0gdHJhbnNhY3Rpb24uY2FuU2lnbih7IGtleToga2V5UGFpciB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChjYW5TaWduLCB0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1RyYW5zYWN0aW9uIFNldHRpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBzZXQgdHJhbnNhY3Rpb24gY29ycmVjdGx5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbW9ja1R4ID0gY3JlYXRlTW9ja1R4KCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb24obW9ja1R4IGFzIGFueSk7XG4gICAgICAvLyBDYW4ndCBkaXJlY3RseSBhY2Nlc3MgX2ZsYXJlVHJhbnNhY3Rpb24gKHByb3RlY3RlZCksIGJ1dCBjYW4gdGVzdCB2aWEgZ2V0dGVyXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uZmxhcmVUcmFuc2FjdGlvbiwgbW9ja1R4KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0hleCBDb252ZXJzaW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgY29udmVydCBieXRlIGFycmF5IHRvIGhleCBzdHJpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBieXRlQXJyYXkgPSBuZXcgVWludDhBcnJheShbMHgwMSwgMHgyMywgMHhhYiwgMHhjZF0pO1xuICAgICAgY29uc3QgaGV4U3RyaW5nID0gdHJhbnNhY3Rpb24udG9IZXhTdHJpbmcoYnl0ZUFycmF5KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChoZXhTdHJpbmcsICcwMTIzYWJjZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgZW1wdHkgYnl0ZSBhcnJheScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJ5dGVBcnJheSA9IG5ldyBVaW50OEFycmF5KFtdKTtcbiAgICAgIGNvbnN0IGhleFN0cmluZyA9IHRyYW5zYWN0aW9uLnRvSGV4U3RyaW5nKGJ5dGVBcnJheSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaGV4U3RyaW5nLCAnJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdNZW1vIEZ1bmN0aW9uYWxpdHknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIHdpdGggZW1wdHkgbWVtbycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5oYXNNZW1vKCksIGZhbHNlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5nZXRNZW1vU3RyaW5nKCksICcnKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uZ2V0TWVtb0J5dGVzKCksIG5ldyBVaW50OEFycmF5KCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXQgbWVtbyBmcm9tIHN0cmluZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lbW9UZXh0ID0gJ1Rlc3QgdHJhbnNhY3Rpb24gbWVtbyc7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRNZW1vKG1lbW9UZXh0KTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmhhc01lbW8oKSwgdHJ1ZSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uZ2V0TWVtb1N0cmluZygpLCBtZW1vVGV4dCk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmdldE1lbW9CeXRlcygpLCBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUobWVtb1RleHQpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2V0IG1lbW8gZnJvbSBKU09OIG9iamVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG1lbW9PYmogPSB7IHVzZXI6ICdhbGljZScsIGFtb3VudDogMTAwMCB9O1xuICAgICAgdHJhbnNhY3Rpb24uc2V0TWVtb0RhdGEobWVtb09iaik7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5oYXNNZW1vKCksIHRydWUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmdldE1lbW9TdHJpbmcoKSwgSlNPTi5zdHJpbmdpZnkobWVtb09iaikpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXQgbWVtbyBmcm9tIGJ5dGVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgbWVtb0J5dGVzID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKCdCaW5hcnkgbWVtbyBkYXRhJyk7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRNZW1vRGF0YShtZW1vQnl0ZXMpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uaGFzTWVtbygpLCB0cnVlKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uZ2V0TWVtb0J5dGVzKCksIG1lbW9CeXRlcyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uZ2V0TWVtb1N0cmluZygpLCAnQmluYXJ5IG1lbW8gZGF0YScpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgZW1wdHkgc3RyaW5nIG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRNZW1vKCcnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5oYXNNZW1vKCksIGZhbHNlKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5nZXRNZW1vU3RyaW5nKCksICcnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGFuZGxlIFVURi04IG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1dGY4TWVtbyA9ICdIZWxsbyDkuJbnlYwg8J+MjSBGbGFyZSEnO1xuICAgICAgdHJhbnNhY3Rpb24uc2V0TWVtbyh1dGY4TWVtbyk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cmFuc2FjdGlvbi5oYXNNZW1vKCksIHRydWUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmdldE1lbW9TdHJpbmcoKSwgdXRmOE1lbW8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBpbmNsdWRlIG1lbW8gaW4gdHJhbnNhY3Rpb24gSlNPTiB3aGVuIHByZXNlbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBtZW1vVGV4dCA9ICdUcmFuc2FjdGlvbiBtZXRhZGF0YSc7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRNZW1vKG1lbW9UZXh0KTtcblxuICAgICAgLy8gTW9jayB0aGUgRmxhcmVKUyB0cmFuc2FjdGlvblxuICAgICAgY29uc3QgbW9ja1R4ID0gY3JlYXRlTW9ja1R4KCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb24obW9ja1R4IGFzIGFueSk7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkV4cG9ydCk7XG5cbiAgICAgIGNvbnN0IHR4RGF0YSA9IHRyYW5zYWN0aW9uLnRvSnNvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4RGF0YS5tZW1vLCBtZW1vVGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCBpbmNsdWRlIG1lbW8gaW4gSlNPTiB3aGVuIGVtcHR5JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gTW9jayB0aGUgRmxhcmVKUyB0cmFuc2FjdGlvblxuICAgICAgY29uc3QgbW9ja1R4ID0gY3JlYXRlTW9ja1R4KCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgdHJhbnNhY3Rpb24uc2V0VHJhbnNhY3Rpb24obW9ja1R4IGFzIGFueSk7XG4gICAgICB0cmFuc2FjdGlvbi5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkV4cG9ydCk7XG5cbiAgICAgIGNvbnN0IHR4RGF0YSA9IHRyYW5zYWN0aW9uLnRvSnNvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4RGF0YS5tZW1vLCAnJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHZhbGlkYXRlIG1lbW8gc2l6ZSBsaW1pdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBUZXN0IGxhcmdlIG1lbW8gLSB0aGlzIHNob3VsZCBiZSB2YWxpZGF0ZWQgYnkgdXRpbHNcbiAgICAgIGNvbnN0IGxhcmdlTWVtbyA9ICd4Jy5yZXBlYXQoNTAwMCk7IC8vIDVLQiBtZW1vXG4gICAgICB0cmFuc2FjdGlvbi5zZXRNZW1vKGxhcmdlTWVtbyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJhbnNhY3Rpb24uZ2V0TWVtb1N0cmluZygpLCBsYXJnZU1lbW8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYW5kbGUgc3BlY2lhbCBjaGFyYWN0ZXJzIGluIG1lbW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzcGVjaWFsTWVtbyA9ICdTcGVjaWFsIGNoYXJzOiBcXG5cXHRcXHJcXDBcXHgwMVxceGZmJztcbiAgICAgIHRyYW5zYWN0aW9uLnNldE1lbW8oc3BlY2lhbE1lbW8pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHRyYW5zYWN0aW9uLmdldE1lbW9TdHJpbmcoKSwgc3BlY2lhbE1lbW8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBmb3IgaW52YWxpZCBtZW1vIGZvcm1hdCBpbiBzZXRNZW1vRGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFRoaXMgc2hvdWxkIGJlIHRlc3RlZCBpbiB1dGlscywgYnV0IHdlIGNhbiBjaGVjayBiYXNpYyBiZWhhdmlvclxuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgIHRyYW5zYWN0aW9uLnNldE1lbW9EYXRhKDEyMyBhcyBhbnkpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|